| @@ -26,11 +26,11 @@ | |||
| #include "jucer_TextButton.h" | |||
| #include "jucer_ToggleButton.h" | |||
| #include "jucer_TextEditor.h" | |||
| #include "jucer_Viewport.h" | |||
| #include "jucer_Label.h" | |||
| #include "jucer_ComboBox.h" | |||
| #include "jucer_Slider.h" | |||
| #include "jucer_GroupComponent.h" | |||
| #include "jucer_Viewport.h" | |||
| #include "jucer_TabbedComponent.h" | |||
| #include "jucer_JucerComponent.h" | |||
| #include "jucer_GenericComponent.h" | |||
| #include "jucer_Label.h" | |||
| #include "jucer_Slider.h" | |||
| #include "jucer_TabbedComponent.h" | |||
| @@ -29,6 +29,7 @@ | |||
| #include "../jucer_ComponentDocument.h" | |||
| //============================================================================== | |||
| class TextButtonHandler : public ComponentTypeHelper<TextButton> | |||
| { | |||
| @@ -443,3 +443,19 @@ UndoManager* ComponentDocument::getUndoManager() | |||
| { | |||
| return &undoManager; | |||
| } | |||
| //============================================================================== | |||
| void ComponentDocument::createClassProperties (Array <PropertyComponent*>& props) | |||
| { | |||
| props.add (new TextPropertyComponent (getClassName(), "Class Name", 256, false)); | |||
| props.getLast()->setTooltip ("The C++ class name for the component class."); | |||
| props.add (new TextPropertyComponent (getClassDescription(), "Description", 512, false)); | |||
| props.getLast()->setTooltip ("A freeform description of the component."); | |||
| props.add (new SliderPropertyComponent (getCanvasWidth(), "Initial Width", 1.0, 8192.0, 1.0)); | |||
| props.getLast()->setTooltip ("The initial width of the component when it is created."); | |||
| props.add (new SliderPropertyComponent (getCanvasHeight(), "Initial Height", 1.0, 8192.0, 1.0)); | |||
| props.getLast()->setTooltip ("The initial height of the component when it is created."); | |||
| } | |||
| @@ -48,11 +48,13 @@ public: | |||
| typedef SelectedItemSet<uint32> SelectedItems; | |||
| //============================================================================== | |||
| Value getClassName() { return getRootValue ("className"); } | |||
| Value getClassDescription() { return getRootValue ("classDesc"); } | |||
| Value getClassName() { return getRootValueNonUndoable ("className"); } | |||
| Value getClassDescription() { return getRootValueNonUndoable ("classDesc"); } | |||
| Value getCanvasWidth() { return root.getPropertyAsValue ("width", 0); } // (deliberately not undoable) | |||
| Value getCanvasHeight() { return root.getPropertyAsValue ("height", 0); } | |||
| Value getCanvasWidth() { return getRootValueNonUndoable ("width"); } | |||
| Value getCanvasHeight() { return getRootValueNonUndoable ("height"); } | |||
| void createClassProperties (Array <PropertyComponent*>& props); | |||
| const String getNonExistentMemberName (String suggestedName); | |||
| @@ -103,7 +105,9 @@ private: | |||
| void checkRootObject(); | |||
| ValueTree getComponentGroup() const; | |||
| Value getRootValue (const var::identifier& name) { return root.getPropertyAsValue (name, getUndoManager()); } | |||
| Value getRootValueUndoable (const var::identifier& name) { return root.getPropertyAsValue (name, getUndoManager()); } | |||
| Value getRootValueNonUndoable (const var::identifier& name) { return root.getPropertyAsValue (name, 0); } | |||
| void writeCode (OutputStream& cpp, OutputStream& header); | |||
| void writeMetadata (OutputStream& out); | |||
| @@ -1086,52 +1086,152 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| class ComponentEditor::InfoPanel : public Component, | |||
| public ChangeListener | |||
| class ComponentEditor::ClassInfoHolder : public Component | |||
| { | |||
| public: | |||
| InfoPanel (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| ClassInfoHolder (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (panel = new PropertyPanelWithTooltips()); | |||
| Array <PropertyComponent*> props; | |||
| editor.getDocument().createClassProperties (props); | |||
| panel->getPanel()->addSection ("Component Properties", props, true); | |||
| } | |||
| addAndMakeVisible (props = new PropertyPanel()); | |||
| ~ClassInfoHolder() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| editor.getCanvas()->getSelection().addChangeListener (this); | |||
| void resized() | |||
| { | |||
| panel->setBounds (getLocalBounds()); | |||
| } | |||
| ~InfoPanel() | |||
| private: | |||
| ComponentEditor& editor; | |||
| PropertyPanelWithTooltips* panel; | |||
| }; | |||
| //============================================================================== | |||
| class ComponentEditor::LayoutEditorHolder : public Component | |||
| { | |||
| public: | |||
| LayoutEditorHolder (ComponentEditor& editor_) | |||
| : editor (editor_), infoPanel (0) | |||
| { | |||
| editor.getCanvas()->getSelection().removeChangeListener (this); | |||
| addAndMakeVisible (viewport = new Viewport()); | |||
| } | |||
| props->clear(); | |||
| ~LayoutEditorHolder() | |||
| { | |||
| deleteAndZero (infoPanel); | |||
| deleteAllChildren(); | |||
| } | |||
| void changeListenerCallback (void*) | |||
| void createCanvas() | |||
| { | |||
| Array <PropertyComponent*> newComps; | |||
| editor.getCanvas()->getSelectedItemProperties (newComps); | |||
| viewport->setViewedComponent (new Canvas (editor)); | |||
| addAndMakeVisible (infoPanel = new InfoPanel (editor)); | |||
| } | |||
| props->clear(); | |||
| props->addProperties (newComps); | |||
| void resized() | |||
| { | |||
| const int infoPanelWidth = 200; | |||
| viewport->setBounds (0, 0, getWidth() - infoPanelWidth, getHeight()); | |||
| if (infoPanel != 0) | |||
| infoPanel->setBounds (getWidth() - infoPanelWidth, 0, infoPanelWidth, getHeight()); | |||
| } | |||
| void paint (Graphics& g) | |||
| Viewport* getViewport() const { return viewport; } | |||
| private: | |||
| class InfoPanel : public Component, | |||
| public ChangeListener | |||
| { | |||
| public: | |||
| InfoPanel (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (props = new PropertyPanel()); | |||
| editor.getCanvas()->getSelection().addChangeListener (this); | |||
| } | |||
| ~InfoPanel() | |||
| { | |||
| editor.getCanvas()->getSelection().removeChangeListener (this); | |||
| props->clear(); | |||
| deleteAllChildren(); | |||
| } | |||
| void changeListenerCallback (void*) | |||
| { | |||
| Array <PropertyComponent*> newComps; | |||
| editor.getCanvas()->getSelectedItemProperties (newComps); | |||
| props->clear(); | |||
| props->addProperties (newComps); | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.fillAll (Colour::greyLevel (0.92f)); | |||
| } | |||
| void resized() | |||
| { | |||
| props->setSize (getWidth(), getHeight()); | |||
| } | |||
| private: | |||
| ComponentEditor& editor; | |||
| PropertyPanel* props; | |||
| }; | |||
| ComponentEditor& editor; | |||
| Viewport* viewport; | |||
| InfoPanel* infoPanel; | |||
| }; | |||
| //============================================================================== | |||
| class ComponentEditor::BackgroundEditorHolder : public Component | |||
| { | |||
| public: | |||
| BackgroundEditorHolder (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| { | |||
| g.fillAll (Colour::greyLevel (0.92f)); | |||
| } | |||
| void resized() | |||
| ~BackgroundEditorHolder() | |||
| { | |||
| props->setSize (getWidth(), getHeight()); | |||
| } | |||
| private: | |||
| ComponentEditor& editor; | |||
| PropertyPanel* props; | |||
| }; | |||
| //============================================================================== | |||
| class ComponentEditor::CodeEditorHolder : public Component | |||
| { | |||
| public: | |||
| CodeEditorHolder (ComponentEditor& editor_) | |||
| : editor (editor_) | |||
| { | |||
| } | |||
| ~CodeEditorHolder() | |||
| { | |||
| } | |||
| private: | |||
| ComponentEditor& editor; | |||
| }; | |||
| //============================================================================== | |||
| ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document, | |||
| @@ -1139,22 +1239,35 @@ ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document, | |||
| : DocumentEditorComponent (document), | |||
| project (project_), | |||
| componentDocument (componentDocument_), | |||
| infoPanel (0) | |||
| classInfoHolder (0), | |||
| layoutEditorHolder (0), | |||
| backgroundEditorHolder (0), | |||
| codeEditorHolder (0) | |||
| { | |||
| setOpaque (true); | |||
| addAndMakeVisible (viewport = new Viewport()); | |||
| if (document != 0) | |||
| if (componentDocument != 0) | |||
| { | |||
| viewport->setViewedComponent (new Canvas (*this)); | |||
| addAndMakeVisible (infoPanel = new InfoPanel (*this)); | |||
| classInfoHolder = new ClassInfoHolder (*this); | |||
| layoutEditorHolder = new LayoutEditorHolder (*this); | |||
| backgroundEditorHolder = new BackgroundEditorHolder (*this); | |||
| codeEditorHolder = new CodeEditorHolder (*this); | |||
| layoutEditorHolder->createCanvas(); | |||
| } | |||
| addAndMakeVisible (tabs = new TabbedComponent (TabbedButtonBar::TabsAtRight)); | |||
| tabs->setTabBarDepth (22); | |||
| tabs->addTab ("Class Settings", Colour::greyLevel (0.88f), classInfoHolder, true); | |||
| tabs->addTab ("Components", Colours::white, layoutEditorHolder, true); | |||
| tabs->addTab ("Background", Colours::white, backgroundEditorHolder, true); | |||
| tabs->addTab ("Source Code", Colours::white, codeEditorHolder, true); | |||
| tabs->setCurrentTabIndex (1); | |||
| } | |||
| ComponentEditor::~ComponentEditor() | |||
| { | |||
| deleteAndZero (infoPanel); | |||
| deleteAllChildren(); | |||
| } | |||
| @@ -1165,16 +1278,17 @@ void ComponentEditor::paint (Graphics& g) | |||
| void ComponentEditor::resized() | |||
| { | |||
| const int infoPanelWidth = 200; | |||
| viewport->setBounds (0, 0, getWidth() - infoPanelWidth, getHeight()); | |||
| if (infoPanel != 0) | |||
| infoPanel->setBounds (getWidth() - infoPanelWidth, 0, infoPanelWidth, getHeight()); | |||
| tabs->setBounds (getLocalBounds()); | |||
| } | |||
| ComponentEditor::Canvas* ComponentEditor::getCanvas() const | |||
| { | |||
| return dynamic_cast <Canvas*> (viewport->getViewedComponent()); | |||
| return dynamic_cast <Canvas*> (getViewport()->getViewedComponent()); | |||
| } | |||
| Viewport* ComponentEditor::getViewport() const | |||
| { | |||
| return layoutEditorHolder->getViewport(); | |||
| } | |||
| void ComponentEditor::getAllCommands (Array <CommandID>& commands) | |||
| @@ -53,19 +53,25 @@ public: | |||
| ComponentDocument& getDocument() const { return *componentDocument; } | |||
| Viewport* getViewport() const throw() { return viewport; } | |||
| Viewport* getViewport() const; | |||
| class Canvas; | |||
| Canvas* getCanvas() const; | |||
| private: | |||
| class InfoPanel; | |||
| class ClassInfoHolder; | |||
| class LayoutEditorHolder; | |||
| class BackgroundEditorHolder; | |||
| class CodeEditorHolder; | |||
| Project* project; | |||
| ComponentDocument* componentDocument; | |||
| Viewport* viewport; | |||
| InfoPanel* infoPanel; | |||
| TabbedComponent* tabs; | |||
| ClassInfoHolder* classInfoHolder; | |||
| LayoutEditorHolder* layoutEditorHolder; | |||
| BackgroundEditorHolder* backgroundEditorHolder; | |||
| CodeEditorHolder* codeEditorHolder; | |||
| }; | |||
| @@ -27,27 +27,21 @@ | |||
| //[MiscUserDefs] You can add your own user definitions and misc code here... | |||
| class PropertiesWithHelpComponent : public Component, | |||
| public Timer | |||
| class PropertiesWithHelpComponent : public PropertyPanelWithTooltips | |||
| { | |||
| public: | |||
| PropertiesWithHelpComponent (Project& project_, int tabIndex_) | |||
| : project (project_), lastComp (0), tabIndex (tabIndex_) | |||
| : project (project_), tabIndex (tabIndex_) | |||
| { | |||
| addAndMakeVisible (panel = new PropertyPanel()); | |||
| startTimer (150); | |||
| } | |||
| ~PropertiesWithHelpComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| PropertyPanel* getPanel() const { return panel; } | |||
| void rebuildProperties() | |||
| { | |||
| panel->clear(); | |||
| getPanel()->clear(); | |||
| Array <PropertyComponent*> props; | |||
| if (tabIndex == 0) | |||
| @@ -91,7 +85,7 @@ public: | |||
| exp->createPropertyEditors (props); | |||
| } | |||
| panel->addProperties (props); | |||
| getPanel()->addProperties (props); | |||
| } | |||
| void visibilityChanged() | |||
| @@ -100,71 +94,9 @@ public: | |||
| rebuildProperties(); | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.setColour (Colour::greyLevel (0.15f)); | |||
| g.setFont (13.0f); | |||
| TextLayout tl; | |||
| tl.appendText (lastTip, Font (14.0f)); | |||
| tl.layout (getWidth() - 10, Justification::left, true); // try to make it look nice | |||
| if (tl.getNumLines() > 3) | |||
| tl.layout (getWidth() - 10, Justification::left, false); // too big, so just squash it in.. | |||
| tl.drawWithin (g, 5, panel->getBottom() + 2, getWidth() - 10, | |||
| getHeight() - panel->getBottom() - 4, | |||
| Justification::centredLeft); | |||
| } | |||
| void resized() | |||
| { | |||
| panel->setBounds (0, 0, getWidth(), jmax (getHeight() - 60, proportionOfHeight (0.6f))); | |||
| } | |||
| void timerCallback() | |||
| { | |||
| Component* const newComp = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); | |||
| if (newComp != lastComp) | |||
| { | |||
| lastComp = newComp; | |||
| String newTip (findTip (newComp)); | |||
| if (newTip != lastTip) | |||
| { | |||
| lastTip = newTip; | |||
| repaint (0, panel->getBottom(), getWidth(), getHeight()); | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| Project& project; | |||
| PropertyPanel* panel; | |||
| TextLayout layout; | |||
| Component* lastComp; | |||
| String lastTip; | |||
| int tabIndex; | |||
| const String findTip (Component* c) | |||
| { | |||
| while (c != 0 && c != this) | |||
| { | |||
| TooltipClient* tc = dynamic_cast <TooltipClient*> (c); | |||
| if (tc != 0) | |||
| { | |||
| String tip (tc->getTooltip()); | |||
| if (tip.isNotEmpty()) | |||
| return tip; | |||
| } | |||
| c = c->getParentComponent(); | |||
| } | |||
| return String::empty; | |||
| } | |||
| }; | |||
| //[/MiscUserDefs] | |||
| @@ -349,21 +349,21 @@ const String makeValidCppIdentifier (String s, | |||
| n = "_" + n; | |||
| // make sure it's not a reserved c++ keyword.. | |||
| static const tchar* const reservedWords[] = | |||
| static const char* const reservedWords[] = | |||
| { | |||
| T("auto"), T("const"), T("double"), T("float"), T("int"), T("short"), T("struct"), | |||
| T("return"), T("static"), T("union"), T("while"), T("asm"), T("dynamic_cast"), | |||
| T("unsigned"), T("break"), T("continue"), T("else"), T("for"), T("long"), T("signed"), | |||
| T("switch"), T("void"), T("case"), T("default"), T("enum"), T("goto"), T("register"), | |||
| T("sizeof"), T("typedef"), T("volatile"), T("char"), T("do"), T("extern"), T("if"), | |||
| T("namespace"), T("reinterpret_cast"), T("try"), T("bool"), T("explicit"), T("new"), | |||
| T("static_cast"), T("typeid"), T("catch"), T("false"), T("operator"), T("template"), | |||
| T("typename"), T("class"), T("friend"), T("private"), T("this"), T("using"), T("const_cast"), | |||
| T("inline"), T("public"), T("throw"), T("virtual"), T("delete"), T("mutable"), T("protected"), | |||
| T("true"), T("wchar_t"), T("and"), T("bitand"), T("compl"), T("not_eq"), T("or_eq"), | |||
| T("xor_eq"), T("and_eq"), T("bitor"), T("not"), T("or"), T("xor"), T("cin"), T("endl"), | |||
| T("INT_MIN"), T("iomanip"), T("main"), T("npos"), T("std"), T("cout"), T("include"), | |||
| T("INT_MAX"), T("iostream"), T("MAX_RAND"), T("NULL"), T("string"), T("id") | |||
| "auto", "const", "double", "float", "int", "short", "struct", | |||
| "return", "static", "union", "while", "asm", "dynamic_cast", | |||
| "unsigned", "break", "continue", "else", "for", "long", "signed", | |||
| "switch", "void", "case", "default", "enum", "goto", "register", | |||
| "sizeof", "typedef", "volatile", "char", "do", "extern", "if", | |||
| "namespace", "reinterpret_cast", "try", "bool", "explicit", "new", | |||
| "static_cast", "typeid", "catch", "false", "operator", "template", | |||
| "typename", "class", "friend", "private", "this", "using", "const_cast", | |||
| "inline", "public", "throw", "virtual", "delete", "mutable", "protected", | |||
| "true", "wchar_t", "and", "bitand", "compl", "not_eq", "or_eq", | |||
| "xor_eq", "and_eq", "bitor", "not", "or", "xor", "cin", "endl", | |||
| "INT_MIN", "iomanip", "main", "npos", "std", "cout", "include", | |||
| "INT_MAX", "iostream", "MAX_RAND", "NULL", "string", "id", "std" | |||
| }; | |||
| for (i = 0; i < numElementsInArray (reservedWords); ++i) | |||
| @@ -503,3 +503,75 @@ int indexOfLineStartingWith (const StringArray& lines, const String& text, int s | |||
| return -1; | |||
| } | |||
| //============================================================================== | |||
| PropertyPanelWithTooltips::PropertyPanelWithTooltips() | |||
| : lastComp (0) | |||
| { | |||
| addAndMakeVisible (panel = new PropertyPanel()); | |||
| startTimer (150); | |||
| } | |||
| PropertyPanelWithTooltips::~PropertyPanelWithTooltips() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void PropertyPanelWithTooltips::paint (Graphics& g) | |||
| { | |||
| g.setColour (Colour::greyLevel (0.15f)); | |||
| g.setFont (13.0f); | |||
| TextLayout tl; | |||
| tl.appendText (lastTip, Font (14.0f)); | |||
| tl.layout (getWidth() - 10, Justification::left, true); // try to make it look nice | |||
| if (tl.getNumLines() > 3) | |||
| tl.layout (getWidth() - 10, Justification::left, false); // too big, so just squash it in.. | |||
| tl.drawWithin (g, 5, panel->getBottom() + 2, getWidth() - 10, | |||
| getHeight() - panel->getBottom() - 4, | |||
| Justification::centredLeft); | |||
| } | |||
| void PropertyPanelWithTooltips::resized() | |||
| { | |||
| panel->setBounds (0, 0, getWidth(), jmax (getHeight() - 60, proportionOfHeight (0.6f))); | |||
| } | |||
| void PropertyPanelWithTooltips::timerCallback() | |||
| { | |||
| Component* const newComp = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse(); | |||
| if (newComp != lastComp) | |||
| { | |||
| lastComp = newComp; | |||
| String newTip (findTip (newComp)); | |||
| if (newTip != lastTip) | |||
| { | |||
| lastTip = newTip; | |||
| repaint (0, panel->getBottom(), getWidth(), getHeight()); | |||
| } | |||
| } | |||
| } | |||
| const String PropertyPanelWithTooltips::findTip (Component* c) | |||
| { | |||
| while (c != 0 && c != this) | |||
| { | |||
| TooltipClient* const tc = dynamic_cast <TooltipClient*> (c); | |||
| if (tc != 0) | |||
| { | |||
| const String tip (tc->getTooltip()); | |||
| if (tip.isNotEmpty()) | |||
| return tip; | |||
| } | |||
| c = c->getParentComponent(); | |||
| } | |||
| return String::empty; | |||
| } | |||
| @@ -109,6 +109,30 @@ private: | |||
| int64 fileHashCode, fileSize; | |||
| }; | |||
| //============================================================================== | |||
| class PropertyPanelWithTooltips : public Component, | |||
| public Timer | |||
| { | |||
| public: | |||
| PropertyPanelWithTooltips(); | |||
| ~PropertyPanelWithTooltips(); | |||
| PropertyPanel* getPanel() const { return panel; } | |||
| void paint (Graphics& g); | |||
| void resized(); | |||
| void timerCallback(); | |||
| private: | |||
| PropertyPanel* panel; | |||
| TextLayout layout; | |||
| Component* lastComp; | |||
| String lastTip; | |||
| const String findTip (Component* c); | |||
| }; | |||
| //============================================================================== | |||
| static const double tickSizes[] = { 1.0, 2.0, 5.0, | |||
| 10.0, 20.0, 50.0, | |||
| @@ -110,9 +110,6 @@ void removeSubWindow (void* nsWindow, Component* comp) | |||
| [hostWindow removeChildWindow: pluginWindow]; | |||
| comp->removeFromDesktop(); | |||
| [hostWindow release]; | |||
| for (int i = 20; --i >= 0;) | |||
| MessageManager::getInstance()->runDispatchLoopUntil (1); | |||
| } | |||
| static bool isJuceWindow (WindowRef w) | |||
| @@ -184,7 +184,15 @@ public: | |||
| delete juceFilter; | |||
| if (--numInstances == 0) | |||
| { | |||
| #if JUCE_MAC | |||
| // Hack to allow any NSWindows to clear themselves up before returning to PT.. | |||
| for (int i = 20; --i >= 0;) | |||
| MessageManager::getInstance()->runDispatchLoopUntil (1); | |||
| #endif | |||
| shutdownJuce_GUI(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -15900,6 +15900,11 @@ const var& ValueTree::SharedObject::getProperty (const var::identifier& name) co | |||
| return properties [name]; | |||
| } | |||
| const var ValueTree::SharedObject::getProperty (const var::identifier& name, const var& defaultReturnValue) const | |||
| { | |||
| return properties.getWithDefault (name, defaultReturnValue); | |||
| } | |||
| void ValueTree::SharedObject::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) | |||
| { | |||
| if (undoManager == 0) | |||
| @@ -16137,6 +16142,11 @@ const var& ValueTree::getProperty (const var::identifier& name) const | |||
| return object == 0 ? var::null : object->getProperty (name); | |||
| } | |||
| const var ValueTree::getProperty (const var::identifier& name, const var& defaultReturnValue) const | |||
| { | |||
| return object == 0 ? defaultReturnValue : object->getProperty (name, defaultReturnValue); | |||
| } | |||
| void ValueTree::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) | |||
| { | |||
| jassert (name.name.isNotEmpty()); | |||
| @@ -16167,10 +16177,10 @@ int ValueTree::getNumProperties() const | |||
| return object == 0 ? 0 : object->properties.size(); | |||
| } | |||
| const var::identifier ValueTree::getPropertyName (int index) const | |||
| const var::identifier ValueTree::getPropertyName (const int index) const | |||
| { | |||
| return (object == 0) ? var::identifier() | |||
| : object->properties.getName (index); | |||
| return object == 0 ? var::identifier() | |||
| : object->properties.getName (index); | |||
| } | |||
| class ValueTreePropertyValueSource : public Value::ValueSource, | |||
| @@ -41179,10 +41189,10 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||
| { | |||
| if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| { | |||
| SafePointer<Component> safePointer (this); | |||
| SafePointer<Component> nextCompPointer (nextComp); | |||
| internalModalInputAttempt(); | |||
| if (safePointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| if (nextCompPointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| return; | |||
| } | |||
| @@ -46567,7 +46577,7 @@ void Label::showEditor() | |||
| editorShown (editor); | |||
| enterModalState(); | |||
| enterModalState (false); | |||
| editor->grabKeyboardFocus(); | |||
| } | |||
| } | |||
| @@ -71032,7 +71042,7 @@ SliderPropertyComponent::SliderPropertyComponent (const String& name, | |||
| slider->addListener (this); | |||
| } | |||
| SliderPropertyComponent::SliderPropertyComponent (Value& valueToControl, | |||
| SliderPropertyComponent::SliderPropertyComponent (const Value& valueToControl, | |||
| const String& name, | |||
| const double rangeMin, | |||
| const double rangeMax, | |||
| @@ -3135,24 +3135,7 @@ private: | |||
| Atomic& operator= (const Atomic&); | |||
| }; | |||
| // If we've got gcc4.2 or later, we can use its atomic intrinsics... | |||
| #if JUCE_GCC && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) | |||
| inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } | |||
| inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } | |||
| inline void* Atomic::swapPointers (void* volatile* value1, void* value2) | |||
| { | |||
| void* currentVal = *value1; | |||
| while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } | |||
| return currentVal; | |||
| } | |||
| #elif (JUCE_MAC || JUCE_IPHONE) // Older Mac builds using gcc4.0 or earlier... | |||
| #if JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) // Older Mac builds using gcc4.1 or earlier... | |||
| inline void Atomic::increment (int32& variable) { OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| @@ -3184,9 +3167,8 @@ private: | |||
| return currentVal; | |||
| } | |||
| #elif JUCE_LINUX // Linux with compilers other than gcc4.2 or later... | |||
| #elif JUCE_LINUX && __INTEL_COMPILER // Linux with Intel compiler... | |||
| #if __INTEL_COMPILER | |||
| inline void Atomic::increment (int32& variable) { _InterlockedIncrement (&variable); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (&variable); } | |||
| inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (&variable); } | |||
| @@ -3203,9 +3185,21 @@ private: | |||
| #endif | |||
| } | |||
| #else | |||
| #error "Linux build requires gcc4.2 or later for atomic operations" | |||
| #endif | |||
| #elif JUCE_GCC // On GCC, use intrinsics... | |||
| inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } | |||
| inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } | |||
| inline void* Atomic::swapPointers (void* volatile* value1, void* value2) | |||
| { | |||
| void* currentVal = *value1; | |||
| while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } | |||
| return currentVal; | |||
| } | |||
| #elif JUCE_USE_INTRINSICS // Windows... | |||
| @@ -6726,6 +6720,8 @@ public: | |||
| const var& getProperty (const var::identifier& name) const; | |||
| const var getProperty (const var::identifier& name, const var& defaultReturnValue) const; | |||
| const var& operator[] (const var::identifier& name) const; | |||
| void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); | |||
| @@ -6825,6 +6821,7 @@ private: | |||
| void sendChildChangeMessage (ValueTree& tree); | |||
| void sendParentChangeMessage(); | |||
| const var& getProperty (const var::identifier& name) const; | |||
| const var getProperty (const var::identifier& name, const var& defaultReturnValue) const; | |||
| void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); | |||
| bool hasProperty (const var::identifier& name) const; | |||
| void removeProperty (const var::identifier& name, UndoManager* const undoManager); | |||
| @@ -26101,7 +26098,7 @@ protected: | |||
| public: | |||
| SliderPropertyComponent (Value& valueToControl, | |||
| SliderPropertyComponent (const Value& valueToControl, | |||
| const String& propertyName, | |||
| double rangeMin, | |||
| double rangeMax, | |||
| @@ -232,6 +232,11 @@ const var& ValueTree::SharedObject::getProperty (const var::identifier& name) co | |||
| return properties [name]; | |||
| } | |||
| const var ValueTree::SharedObject::getProperty (const var::identifier& name, const var& defaultReturnValue) const | |||
| { | |||
| return properties.getWithDefault (name, defaultReturnValue); | |||
| } | |||
| void ValueTree::SharedObject::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) | |||
| { | |||
| if (undoManager == 0) | |||
| @@ -471,6 +476,11 @@ const var& ValueTree::getProperty (const var::identifier& name) const | |||
| return object == 0 ? var::null : object->getProperty (name); | |||
| } | |||
| const var ValueTree::getProperty (const var::identifier& name, const var& defaultReturnValue) const | |||
| { | |||
| return object == 0 ? defaultReturnValue : object->getProperty (name, defaultReturnValue); | |||
| } | |||
| void ValueTree::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) | |||
| { | |||
| jassert (name.name.isNotEmpty()); | |||
| @@ -501,10 +511,10 @@ int ValueTree::getNumProperties() const | |||
| return object == 0 ? 0 : object->properties.size(); | |||
| } | |||
| const var::identifier ValueTree::getPropertyName (int index) const | |||
| const var::identifier ValueTree::getPropertyName (const int index) const | |||
| { | |||
| return (object == 0) ? var::identifier() | |||
| : object->properties.getName (index); | |||
| return object == 0 ? var::identifier() | |||
| : object->properties.getName (index); | |||
| } | |||
| //============================================================================== | |||
| @@ -130,6 +130,13 @@ public: | |||
| */ | |||
| const var& getProperty (const var::identifier& name) const; | |||
| /** Returns the value of a named property, or a user-specified default if the property doesn't exist. | |||
| If no such property has been set, this will return the value of defaultReturnValue. | |||
| You can also use operator[] and getProperty to get a property. | |||
| @see var, getProperty, setProperty, hasProperty | |||
| */ | |||
| const var getProperty (const var::identifier& name, const var& defaultReturnValue) const; | |||
| /** Returns the value of a named property. | |||
| If no such property has been set, this will return a void variant. This is the same as | |||
| calling getProperty(). | |||
| @@ -406,6 +413,7 @@ private: | |||
| void sendChildChangeMessage (ValueTree& tree); | |||
| void sendParentChangeMessage(); | |||
| const var& getProperty (const var::identifier& name) const; | |||
| const var getProperty (const var::identifier& name, const var& defaultReturnValue) const; | |||
| void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); | |||
| bool hasProperty (const var::identifier& name) const; | |||
| void removeProperty (const var::identifier& name, UndoManager* const undoManager); | |||
| @@ -62,24 +62,7 @@ private: | |||
| //============================================================================== | |||
| // If we've got gcc4.2 or later, we can use its atomic intrinsics... | |||
| #if JUCE_GCC && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) | |||
| inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } | |||
| inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } | |||
| inline void* Atomic::swapPointers (void* volatile* value1, void* value2) | |||
| { | |||
| void* currentVal = *value1; | |||
| while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } | |||
| return currentVal; | |||
| } | |||
| #elif (JUCE_MAC || JUCE_IPHONE) // Older Mac builds using gcc4.0 or earlier... | |||
| #if JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) // Older Mac builds using gcc4.1 or earlier... | |||
| inline void Atomic::increment (int32& variable) { OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| @@ -112,9 +95,8 @@ private: | |||
| } | |||
| //============================================================================== | |||
| #elif JUCE_LINUX // Linux with compilers other than gcc4.2 or later... | |||
| #elif JUCE_LINUX && __INTEL_COMPILER // Linux with Intel compiler... | |||
| #if __INTEL_COMPILER | |||
| inline void Atomic::increment (int32& variable) { _InterlockedIncrement (&variable); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (&variable); } | |||
| inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (&variable); } | |||
| @@ -131,9 +113,22 @@ private: | |||
| #endif | |||
| } | |||
| #else | |||
| #error "Linux build requires gcc4.2 or later for atomic operations" | |||
| #endif | |||
| //============================================================================== | |||
| #elif JUCE_GCC // On GCC, use intrinsics... | |||
| inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } | |||
| inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } | |||
| inline void* Atomic::swapPointers (void* volatile* value1, void* value2) | |||
| { | |||
| void* currentVal = *value1; | |||
| while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } | |||
| return currentVal; | |||
| } | |||
| //============================================================================== | |||
| #elif JUCE_USE_INTRINSICS // Windows... | |||
| @@ -218,7 +218,7 @@ void Label::showEditor() | |||
| editorShown (editor); | |||
| enterModalState(); | |||
| enterModalState (false); | |||
| editor->grabKeyboardFocus(); | |||
| } | |||
| } | |||
| @@ -3072,10 +3072,10 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) | |||
| { | |||
| if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| { | |||
| SafePointer<Component> safePointer (this); | |||
| SafePointer<Component> nextCompPointer (nextComp); | |||
| internalModalInputAttempt(); | |||
| if (safePointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| if (nextCompPointer == 0 || nextComp->isCurrentlyBlockedByAnotherModalComponent()) | |||
| return; | |||
| } | |||
| @@ -47,7 +47,7 @@ SliderPropertyComponent::SliderPropertyComponent (const String& name, | |||
| slider->addListener (this); | |||
| } | |||
| SliderPropertyComponent::SliderPropertyComponent (Value& valueToControl, | |||
| SliderPropertyComponent::SliderPropertyComponent (const Value& valueToControl, | |||
| const String& name, | |||
| const double rangeMin, | |||
| const double rangeMax, | |||
| @@ -63,7 +63,7 @@ public: | |||
| If you need to customise the slider in other ways, your constructor can | |||
| access the slider member variable and change it directly. | |||
| */ | |||
| SliderPropertyComponent (Value& valueToControl, | |||
| SliderPropertyComponent (const Value& valueToControl, | |||
| const String& propertyName, | |||
| double rangeMin, | |||
| double rangeMax, | |||