|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2015 - ROLI Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
- */
-
- class ErrorListComp : public TreePanelBase,
- private ChangeListener
- {
- public:
- ErrorListComp (ErrorList& el)
- : TreePanelBase (nullptr, String()),
- errorList (el)
- {
- setName ("Errors and Warnings");
- setEmptyTreeMessage ("(No Messages)");
-
- tree.setMultiSelectEnabled (false);
- tree.setRootItemVisible (false);
- setRoot (new ErrorRootTreeItem (errorList));
-
- errorList.addChangeListener (this);
- errorListChanged();
- }
-
- ~ErrorListComp()
- {
- errorList.removeChangeListener (this);
- }
-
- void errorListChanged()
- {
- static_cast<ErrorRootTreeItem*> (rootItem.get())->refreshSubItems();
- }
-
- void moveBy (const int delta)
- {
- if (delta < 0)
- if (TreeViewItem* selected = tree.getSelectedItem (0))
- if (selected->getRowNumberInTree() <= 1)
- return;
-
- tree.moveSelectedRow (delta);
-
- if (dynamic_cast<ErrorMessageTreeItem*> (tree.getSelectedItem (0)) == nullptr)
- tree.moveSelectedRow (delta);
- }
-
- void showNext() { moveBy (1); }
- void showPrevious() { moveBy (-1); }
-
- private:
- TreeView list;
- ErrorList& errorList;
- struct ErrorMessageTreeItem;
-
- void changeListenerCallback (ChangeBroadcaster*) override
- {
- errorListChanged();
- }
-
- static void limitNumberOfSubItems (TreeViewItem& item, const int maxSubItems)
- {
- while (item.getNumSubItems() > maxSubItems)
- item.removeSubItem (item.getNumSubItems() - 1);
- }
-
- //==============================================================================
- class ErrorRootTreeItem : public JucerTreeViewBase
- {
- public:
- ErrorRootTreeItem (ErrorList& el) : errorList (el) {}
-
- String getRenamingName() const override { return getDisplayName(); }
- String getDisplayName() const override { return "Errors and Warnings"; }
- void setName (const String&) override {}
- bool isMissing() const override { return false; }
- Icon getIcon() const override { return Icon (getIcons().bug, getContentColour (true)); }
- bool canBeSelected() const override { return true; }
- bool mightContainSubItems() override { return true; }
- String getUniqueName() const override { return "errors"; }
-
- void refreshSubItems()
- {
- Array<DiagnosticMessage> errors;
- errorList.takeCopy (errors);
-
- StringArray files;
-
- for (const auto& m : errors)
- {
- files.addIfNotAlreadyThere (m.mainFile);
-
- if (m.associatedDiagnostic != nullptr)
- files.addIfNotAlreadyThere (m.associatedDiagnostic->mainFile);
- }
-
- limitNumberOfSubItems (*this, files.size());
-
- int i = 0;
-
- for (const auto& f : files)
- {
- if (i >= getNumSubItems() || static_cast<CompileUnitTreeItem*> (getSubItem (i))->compileUnit != f)
- {
- limitNumberOfSubItems (*this, i);
- addSubItem (new CompileUnitTreeItem (f));
- }
-
- static_cast<CompileUnitTreeItem*> (getSubItem (i))->refresh (errors);
- ++i;
- }
- }
-
- private:
- ErrorList& errorList;
- };
-
- //==============================================================================
- struct CompileUnitTreeItem : public JucerTreeViewBase
- {
- CompileUnitTreeItem (const String& filename) : compileUnit (filename) {}
-
- void setName (const String&) override {}
- void addSubItems() override {}
- bool isMissing() const override { return false; }
- Icon getIcon() const override { return Icon (getIcons().bug, getContentColour (true)); }
- bool canBeSelected() const override { return true; }
- bool mightContainSubItems() override { return true; }
- String getUniqueName() const override { return String::toHexString (compileUnit.hashCode64()); }
-
- String getRenamingName() const override { return getDisplayName(); }
- String getDisplayName() const override
- {
- if (File::isAbsolutePath (compileUnit))
- {
- File f (compileUnit);
- return f.exists() ? f.getFileName() : compileUnit;
- }
-
- if (! compileUnit.isEmpty())
- return compileUnit;
-
- return String ("Global");
- }
-
- void showOverlays()
- {
- for (int i = 0; i < getNumSubItems(); ++i)
- if (auto* e = dynamic_cast<ErrorMessageTreeItem*> (getSubItem (i)))
- e->showOverlays();
- }
-
- ErrorMessageTreeItem* getItemForError (const DiagnosticMessage& m) const
- {
- for (int i = 0; i < getNumSubItems(); ++i)
- if (auto* item = dynamic_cast<ErrorMessageTreeItem*> (getSubItem(i)))
- if (item->message == m)
- return item;
-
- return nullptr;
- }
-
- void refresh (const Array<DiagnosticMessage>& allErrors)
- {
- clearSubItems();
-
- for (const auto& error : allErrors)
- if (error.mainFile == compileUnit && error.associatedDiagnostic == nullptr)
- addSubItem (new ErrorMessageTreeItem (error));
-
- for (const auto& error : allErrors)
- if (error.mainFile == compileUnit && error.associatedDiagnostic != nullptr)
- if (ErrorMessageTreeItem* parent = getItemForError (*error.associatedDiagnostic))
- parent->addSubItem (new ErrorMessageTreeItem (error));
- }
-
- void showDocument() override
- {
- if (ProjectContentComponent* pcc = getProjectContentComponent())
- if (File::isAbsolutePath (compileUnit) && File (compileUnit).exists())
- pcc->showEditorForFile (File (compileUnit), true);
- }
-
- String compileUnit;
- };
-
- //==============================================================================
- struct ErrorMessageTreeItem : public JucerTreeViewBase
- {
- ErrorMessageTreeItem (const DiagnosticMessage& m)
- : message (m), itemHeight (25)
- {
- setOpenness (Openness::opennessClosed);
- uniqueID << message.message << ':' << message.range.toString();
- }
-
- ~ErrorMessageTreeItem()
- {
- overlay.deleteAndZero();
- }
-
- String getRenamingName() const override { return getDisplayName(); }
- String getDisplayName() const override { return message.message; }
- void setName (const String&) override {}
- bool isMissing() const override { return false; }
- Icon getIcon() const override { return Icon (message.isNote() ? getIcons().info
- : getIcons().warning, getContentColour (true)); }
- bool canBeSelected() const override { return true; }
- bool mightContainSubItems() override { return getNumSubItems() != 0; }
- String getUniqueName() const override { return uniqueID; }
-
- void paintContent (Graphics& g, const Rectangle<int>& area) override
- {
- jassert (area.getWidth() >= 0);
-
- AttributedString s (message.message);
- s.setFont (Font (12.0f));
- s.setColour (getContentColour (false));
- s.setJustification (Justification::centredLeft);
-
- text.createLayout (s, (float) area.getWidth());
-
- const auto newHeight = 2 + jmax (25, (int) text.getHeight());
- if (itemHeight != newHeight)
- {
- itemHeight = newHeight;
- treeHasChanged();
- }
-
- text.draw (g, area.toFloat());
- }
-
- Colour getContentColour (bool isIcon) const override
- {
- return message.isError() ? Colours::red
- : message.isWarning() ? Colours::yellow
- : getOwnerView()->findColour (isIcon ? treeIconColourId
- : defaultTextColourId);
- }
-
- void showPopupMenu() override
- {
- PopupMenu menu;
- menu.addItem (1, "Copy");
- launchPopupMenu (menu);
- }
-
- void handlePopupMenuResult (int resultCode) override
- {
- if (resultCode == 1)
- SystemClipboard::copyTextToClipboard (message.toString());
- }
-
- int getItemHeight() const override
- {
- return itemHeight;
- }
-
- SourceCodeEditor* getEditor()
- {
- if (ProjectContentComponent* pcc = getProjectContentComponent())
- {
- const File file (File::createFileWithoutCheckingPath (message.range.file));
-
- if (message.range.isValid() && file.exists() && pcc->showEditorForFile (file, false))
- {
- if (SourceCodeEditor* ed = dynamic_cast<SourceCodeEditor*> (pcc->getEditorComponent()))
- {
- return ed;
- }
- }
- }
-
- return nullptr;
- }
-
- void showDocument() override
- {
- if (SourceCodeEditor* ed = getEditor())
- {
- ed->grabKeyboardFocus();
- ed->highlight (message.range.range, false);
-
- if (auto cu = findCompileUnitParent())
- cu->showOverlays();
- }
- }
-
- CompileUnitTreeItem* findCompileUnitParent()
- {
- for (TreeViewItem* p = getParentItem(); p != nullptr; p = p->getParentItem())
- if (auto cu = dynamic_cast<CompileUnitTreeItem*> (p))
- return cu;
-
- return nullptr;
- }
-
- void showOverlays()
- {
- overlay.deleteAndZero();
-
- if (ProjectContentComponent* pcc = getProjectContentComponent())
- {
- if (SourceCodeEditor* ed = dynamic_cast<SourceCodeEditor*> (pcc->getEditorComponent()))
- {
- auto start = CodeDocument::Position (ed->editor->getDocument(), message.range.range.getStart());
- auto end = CodeDocument::Position (ed->editor->getDocument(), message.range.range.getEnd());
-
- if (auto* ce = dynamic_cast<LiveBuildCodeEditor*> (ed->editor.get()))
- overlay = ce->addDiagnosticOverlay (start, end, message.type);
- }
- }
-
- for (int i = 0; i < getNumSubItems(); ++i)
- if (auto* e = dynamic_cast<ErrorMessageTreeItem*> (getSubItem (i)))
- e->showOverlays();
- }
-
- DiagnosticMessage message;
-
- private:
- String uniqueID;
- TextLayout text;
- int itemHeight;
- Component::SafePointer<Component> overlay;
- };
- };
|