| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 -    Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 -    27th April 2017).
 - 
 -    End User License Agreement: www.juce.com/juce-5-licence
 -    Privacy Policy: www.juce.com/juce-5-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "../JuceDemoHeader.h"
 - 
 - //==============================================================================
 - class XmlTreeItem  : public TreeViewItem
 - {
 - public:
 -     XmlTreeItem (XmlElement& x)  : xml (x)
 -     {
 -     }
 - 
 -     String getUniqueName() const override
 -     {
 -         if (xml.getTagName().isEmpty())
 -             return "unknown";
 - 
 -         return xml.getTagName();
 -     }
 - 
 -     bool mightContainSubItems() override
 -     {
 -         return xml.getFirstChildElement() != nullptr;
 -     }
 - 
 -     void paintItem (Graphics& g, int width, int height) override
 -     {
 -         // if this item is selected, fill it with a background colour..
 -         if (isSelected())
 -             g.fillAll (Colours::blue.withAlpha (0.3f));
 - 
 -         // use a "colour" attribute in the xml tag for this node to set the text colour..
 -         g.setColour (Colour::fromString (xml.getStringAttribute ("colour", "ff000000")));
 -         g.setFont (height * 0.7f);
 - 
 -         // draw the xml element's tag name..
 -         g.drawText (xml.getTagName(),
 -                     4, 0, width - 4, height,
 -                     Justification::centredLeft, true);
 -     }
 - 
 -     void itemOpennessChanged (bool isNowOpen) override
 -     {
 -         if (isNowOpen)
 -         {
 -             // if we've not already done so, we'll now add the tree's sub-items. You could
 -             // also choose to delete the existing ones and refresh them if that's more suitable
 -             // in your app.
 -             if (getNumSubItems() == 0)
 -             {
 -                 // create and add sub-items to this node of the tree, corresponding to
 -                 // each sub-element in the XML..
 - 
 -                 forEachXmlChildElement (xml, child)
 -                 {
 -                     jassert (child != nullptr);
 -                     addSubItem (new XmlTreeItem (*child));
 -                 }
 -             }
 -         }
 -         else
 -         {
 -             // in this case, we'll leave any sub-items in the tree when the node gets closed,
 -             // though you could choose to delete them if that's more appropriate for
 -             // your application.
 -         }
 -     }
 - 
 - private:
 -     XmlElement& xml;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XmlTreeItem)
 - };
 - 
 - //==============================================================================
 - class JsonTreeItem  : public TreeViewItem
 - {
 - public:
 -     JsonTreeItem (Identifier i, var value)   : identifier (i), json (value)
 -     {
 -     }
 - 
 -     String getUniqueName() const override
 -     {
 -         return identifier.toString() + "_id";
 -     }
 - 
 -     bool mightContainSubItems() override
 -     {
 -         if (DynamicObject* obj = json.getDynamicObject())
 -             return obj->getProperties().size() > 0;
 - 
 -         return json.isArray();
 -     }
 - 
 -     void paintItem (Graphics& g, int width, int height) override
 -     {
 -         // if this item is selected, fill it with a background colour..
 -         if (isSelected())
 -             g.fillAll (Colours::blue.withAlpha (0.3f));
 - 
 -         g.setColour (Colours::black);
 -         g.setFont (height * 0.7f);
 - 
 -         // draw the element's tag name..
 -         g.drawText (getText(),
 -                     4, 0, width - 4, height,
 -                     Justification::centredLeft, true);
 -     }
 - 
 -     void itemOpennessChanged (bool isNowOpen) override
 -     {
 -         if (isNowOpen)
 -         {
 -             // if we've not already done so, we'll now add the tree's sub-items. You could
 -             // also choose to delete the existing ones and refresh them if that's more suitable
 -             // in your app.
 -             if (getNumSubItems() == 0)
 -             {
 -                 // create and add sub-items to this node of the tree, corresponding to
 -                 // the type of object this var represents
 - 
 -                 if (json.isArray())
 -                 {
 -                     for (int i = 0; i < json.size(); ++i)
 -                     {
 -                         var& child (json[i]);
 -                         jassert (! child.isVoid());
 -                         addSubItem (new JsonTreeItem (Identifier(), child));
 -                     }
 -                 }
 -                 else if (DynamicObject* obj = json.getDynamicObject())
 -                 {
 -                     NamedValueSet& props (obj->getProperties());
 - 
 -                     for (int i = 0; i < props.size(); ++i)
 -                     {
 -                         const Identifier id (props.getName (i));
 -                         var child (props[id]);
 -                         jassert (! child.isVoid());
 -                         addSubItem (new JsonTreeItem (id, child));
 -                     }
 -                 }
 -             }
 -         }
 -         else
 -         {
 -             // in this case, we'll leave any sub-items in the tree when the node gets closed,
 -             // though you could choose to delete them if that's more appropriate for
 -             // your application.
 -         }
 -     }
 - 
 - private:
 -     Identifier identifier;
 -     var json;
 - 
 -     /** Returns the text to display in the tree.
 -         This is a little more complex for JSON than XML as nodes can be strings, objects or arrays.
 -      */
 -     String getText() const
 -     {
 -         String text;
 - 
 -         if (identifier.isValid())
 -             text << identifier.toString();
 - 
 -         if (! json.isVoid())
 -         {
 -             if (text.isNotEmpty() && (! json.isArray()))
 -                 text << ": ";
 - 
 -             if (json.isObject() && (! identifier.isValid()))
 -                 text << "[Array]";
 -             else if (! json.isArray())
 -                 text << json.toString();
 -         }
 - 
 -         return text;
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JsonTreeItem)
 - };
 - 
 - //==============================================================================
 - class StringsDemo   : public Component,
 -                       private ComboBox::Listener,
 -                       private CodeDocument::Listener
 - {
 - public:
 -     /** The type of database to parse. */
 -     enum Type
 -     {
 -         xml,
 -         json
 -     };
 - 
 -     StringsDemo()
 -         : codeDocumentComponent (codeDocument, nullptr)
 -     {
 -         setOpaque (true);
 - 
 -         addAndMakeVisible (typeBox);
 -         typeBox.addListener (this);
 -         typeBox.addItem ("XML", 1);
 -         typeBox.addItem ("JSON", 2);
 - 
 -         comboBoxLabel.setText ("Database Type:", dontSendNotification);
 -         comboBoxLabel.attachToComponent (&typeBox, true);
 - 
 -         addAndMakeVisible (codeDocumentComponent);
 -         codeDocument.addListener (this);
 - 
 -         addAndMakeVisible (resultsTree);
 -         resultsTree.setColour (TreeView::backgroundColourId, Colours::white);
 -         resultsTree.setDefaultOpenness (true);
 - 
 -         addAndMakeVisible (errorMessage);
 -         errorMessage.setReadOnly (true);
 -         errorMessage.setMultiLine (true);
 -         errorMessage.setCaretVisible (false);
 -         errorMessage.setColour (TextEditor::outlineColourId, Colours::transparentWhite);
 -         errorMessage.setColour (TextEditor::shadowColourId, Colours::transparentWhite);
 - 
 -         typeBox.setSelectedId (1);
 -     }
 - 
 -     ~StringsDemo()
 -     {
 -         resultsTree.setRootItem (nullptr);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground));
 -     }
 - 
 -     void resized() override
 -     {
 -         Rectangle<int> area (getLocalBounds());
 -         typeBox.setBounds (area.removeFromTop (36).removeFromRight (150).reduced (8));
 -         codeDocumentComponent.setBounds (area.removeFromTop(area.getHeight() / 2).reduced (8));
 -         resultsTree.setBounds (area.reduced (8));
 -         errorMessage.setBounds (resultsTree.getBounds());
 -     }
 - 
 - private:
 -     ComboBox typeBox;
 -     Label comboBoxLabel;
 -     CodeDocument codeDocument;
 -     CodeEditorComponent codeDocumentComponent;
 -     TreeView resultsTree;
 - 
 -     ScopedPointer<TreeViewItem> rootItem;
 -     ScopedPointer<XmlElement> parsedXml;
 -     TextEditor errorMessage;
 - 
 -     void rebuildTree()
 -     {
 -         ScopedPointer<XmlElement> openness;
 - 
 -         if (rootItem != nullptr)
 -             openness = rootItem->getOpennessState();
 - 
 -         createNewRootNode();
 - 
 -         if (openness != nullptr && rootItem != nullptr)
 -             rootItem->restoreOpennessState (*openness);
 -     }
 - 
 -     void createNewRootNode()
 -     {
 -         // clear the current tree
 -         resultsTree.setRootItem (nullptr);
 -         rootItem = nullptr;
 - 
 -         // try and parse the editor's contents
 -         switch (typeBox.getSelectedItemIndex())
 -         {
 -             case xml:           rootItem = rebuildXml();        break;
 -             case json:          rootItem = rebuildJson();       break;
 -             default:            rootItem = nullptr;             break;
 -         }
 - 
 -         // if we have a valid TreeViewItem hide any old error messages and set our TreeView to use it
 -         if (rootItem != nullptr)
 -             errorMessage.clear();
 - 
 -         errorMessage.setVisible (! errorMessage.isEmpty());
 - 
 -         resultsTree.setRootItem (rootItem);
 -     }
 - 
 -     /** Parses the editors contects as XML. */
 -     TreeViewItem* rebuildXml()
 -     {
 -         parsedXml = nullptr;
 - 
 -         XmlDocument doc (codeDocument.getAllContent());
 -         parsedXml = doc.getDocumentElement();
 - 
 -         if (parsedXml == nullptr)
 -         {
 -             String error (doc.getLastParseError());
 - 
 -             if (error.isEmpty())
 -                 error = "Unknown error";
 - 
 -             errorMessage.setText ("Error parsing XML: " + error, dontSendNotification);
 - 
 -             return nullptr;
 -         }
 - 
 -         return new XmlTreeItem (*parsedXml);
 -     }
 - 
 -     /** Parses the editors contects as JSON. */
 -     TreeViewItem* rebuildJson()
 -     {
 -         var parsedJson;
 -         Result result = JSON::parse (codeDocument.getAllContent(), parsedJson);
 - 
 -         if (! result.wasOk())
 -         {
 -             errorMessage.setText ("Error parsing JSON: " + result.getErrorMessage());
 -             return nullptr;
 -         }
 - 
 -         return new JsonTreeItem (Identifier(), parsedJson);
 -     }
 - 
 -     /** Clears the editor and loads some default text. */
 -     void reset (Type type)
 -     {
 -         switch (type)
 -         {
 -             case xml:   codeDocument.replaceAllContent (BinaryData::treedemo_xml);      break;
 -             case json:  codeDocument.replaceAllContent (BinaryData::juce_module_info);  break;
 -             default:    codeDocument.replaceAllContent (String());                      break;
 -         }
 -     }
 - 
 -     void comboBoxChanged (ComboBox* box) override
 -     {
 -         if (box == &typeBox)
 -         {
 -             if (typeBox.getSelectedId() == 1)
 -                 reset (xml);
 -             else
 -                 reset (json);
 -         }
 -     }
 - 
 -     void codeDocumentTextInserted (const String&, int) override     { rebuildTree(); }
 -     void codeDocumentTextDeleted (int, int) override                { rebuildTree(); }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringsDemo)
 - };
 - 
 - 
 - // This static object will register this demo type in a global list of demos..
 - static JuceDemoType<StringsDemo> demo ("40 XML & JSON");
 
 
  |