From 88c95982f74948551133b3633a7038e48906c450 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 17 May 2010 10:53:44 +0100 Subject: [PATCH] Changed the ChoicePropertyComponent to give it more powerful value remapping. Jucer development. --- .../The Jucer.xcodeproj/project.pbxproj | 4 +- .../Builds/VisualStudio2005/The Jucer.vcproj | 2 +- .../Builds/VisualStudio2008/The Jucer.vcproj | 2 +- extras/Jucer (experimental)/Jucer.jucer | 4 +- .../Source/jucer_Headers.h | 45 ++++- .../Types/jucer_ComponentTypeManager.cpp | 88 ++------ .../Component/Types/jucer_JucerComponent.h | 107 +++++++++- .../model/Component/Types/jucer_Label.h | 3 +- .../model/Component/Types/jucer_Slider.h | 18 +- .../model/Component/Types/jucer_TextEditor.h | 3 +- .../Component/jucer_ComponentDocument.cpp | 91 ++++----- .../model/Component/jucer_ComponentDocument.h | 8 +- .../model/Drawable/jucer_DrawableDocument.cpp | 10 +- .../Source/model/Project/jucer_Project.cpp | 164 +++++++-------- .../Source/model/Project/jucer_Project.h | 80 ++++---- .../model/Project/jucer_ProjectExport_MSVC.h | 5 +- .../model/Project/jucer_ProjectExport_XCode.h | 81 ++++---- .../Source/model/Project/jucer_ProjectSaver.h | 40 ++-- .../model/Project/jucer_ProjectWizard.cpp | 8 +- .../jucer_DrawableEditorTreeView.h | 4 +- .../ui/Editor Base/jucer_EditorCanvas.cpp | 18 +- .../jucer_ProjectInformationComponent.cpp | 16 +- .../jucer_ProjectInformationComponent.h | 2 +- .../Source/utility/jucer_Coordinate.cpp | 145 +++++++++++++ .../Source/utility/jucer_Coordinate.h | 21 +- .../Source/utility/jucer_MarkerListBase.h | 8 +- .../utility/jucer_ValueRemapperSource.h | 191 ------------------ .../Source/utility/jucer_ValueSourceHelpers.h | 68 +++++++ juce_amalgamated.cpp | 152 +++++++++----- juce_amalgamated.h | 30 +-- src/containers/juce_Array.h | 8 +- src/core/juce_StandardHeader.h | 2 +- .../juce_CPlusPlusCodeTokeniser.cpp | 28 +-- .../juce_ChoicePropertyComponent.cpp | 99 ++++++--- .../properties/juce_ChoicePropertyComponent.h | 22 +- src/text/juce_String.cpp | 2 +- src/text/juce_XmlDocument.cpp | 26 +-- 37 files changed, 923 insertions(+), 682 deletions(-) delete mode 100644 extras/Jucer (experimental)/Source/utility/jucer_ValueRemapperSource.h create mode 100644 extras/Jucer (experimental)/Source/utility/jucer_ValueSourceHelpers.h diff --git a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj index ebff4890eb..5814f11163 100644 --- a/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj +++ b/extras/Jucer (experimental)/Builds/MacOSX/The Jucer.xcodeproj/project.pbxproj @@ -152,7 +152,7 @@ 7530E3F9877E4F322CD81801 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_TickIterator.h; path = ../../Source/utility/jucer_TickIterator.h; sourceTree = SOURCE_ROOT; }; 49A1C43070A68985C25F34C7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_MiscUtilities.cpp; path = ../../Source/utility/jucer_MiscUtilities.cpp; sourceTree = SOURCE_ROOT; }; 2B2A6FCA85F56682698864EC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_MiscUtilities.h; path = ../../Source/utility/jucer_MiscUtilities.h; sourceTree = SOURCE_ROOT; }; - B8469A2CDD0FBEA6BE01B1D5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ValueRemapperSource.h; path = ../../Source/utility/jucer_ValueRemapperSource.h; sourceTree = SOURCE_ROOT; }; + C693F6EF4381328D5F5891CF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_ValueSourceHelpers.h; path = ../../Source/utility/jucer_ValueSourceHelpers.h; sourceTree = SOURCE_ROOT; }; 0CA0CCCEBFA0AC8C577FC915 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jucer_Headers.h; path = ../../Source/jucer_Headers.h; sourceTree = SOURCE_ROOT; }; 0DC331A7B856F30AD266A3E6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = jucer_Main.cpp; path = ../../Source/jucer_Main.cpp; sourceTree = SOURCE_ROOT; }; E50666EA86CAD5FB338A8756 = { isa = PBXFileReference; lastKnownFileType = image.png; name = brushed_aluminium.png; path = ../../Source/templates/brushed_aluminium.png; sourceTree = SOURCE_ROOT; }; @@ -287,7 +287,7 @@ 7530E3F9877E4F322CD81801, 49A1C43070A68985C25F34C7, 2B2A6FCA85F56682698864EC, - B8469A2CDD0FBEA6BE01B1D5 ); name = Utility; sourceTree = ""; }; + C693F6EF4381328D5F5891CF ); name = Utility; sourceTree = ""; }; FAFBE12D4C5798FC1BB3A4BA = { isa = PBXGroup; children = ( 0CA0CCCEBFA0AC8C577FC915, 0DC331A7B856F30AD266A3E6 ); name = Main; sourceTree = ""; }; diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj index ae5d7cc711..719ccd4c00 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj @@ -239,7 +239,7 @@ - + diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj index 04412dbf47..e6c291936e 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj @@ -239,7 +239,7 @@ - + diff --git a/extras/Jucer (experimental)/Jucer.jucer b/extras/Jucer (experimental)/Jucer.jucer index 74d06366e8..117a9937ff 100644 --- a/extras/Jucer (experimental)/Jucer.jucer +++ b/extras/Jucer (experimental)/Jucer.jucer @@ -225,8 +225,8 @@ file="Source/utility/jucer_MiscUtilities.cpp"/> - + & props) void ComponentTypeInstance::createCode (CodeGenerator& code) { code.addPrivateMember (getHandler()->getClassName (*this) + "*", getMemberName()); + code.memberInitialisers.add (getMemberName() + " (0)"); getHandler()->createCode (*this, code); } @@ -415,27 +376,13 @@ public: const var getValue() const { - const String fontName (Font::fromString (sourceValue.toString()).getTypefaceName()); - const int index = StoredSettings::getInstance()->getFontNames().indexOf (fontName); - - if (index >= 0) return 4 + index; - else if (fontName == Font::getDefaultSansSerifFontName()) return 1; - else if (fontName == Font::getDefaultSerifFontName()) return 2; - else if (fontName == Font::getDefaultMonospacedFontName()) return 3; - - return 1; + return Font::fromString (sourceValue.toString()).getTypefaceName(); } void setValue (const var& newValue) { Font font (Font::fromString (sourceValue.toString())); - - const int index = newValue; - if (index <= 1) font.setTypefaceName (Font::getDefaultSansSerifFontName()); - else if (index == 2) font.setTypefaceName (Font::getDefaultSerifFontName()); - else if (index == 3) font.setTypefaceName (Font::getDefaultMonospacedFontName()); - else font.setTypefaceName (StoredSettings::getInstance()->getFontNames() [index - 4]); - + font.setTypefaceName (newValue.toString()); sourceValue = font.toString(); } @@ -448,7 +395,11 @@ public: fontNames.add (String::empty); fontNames.addArray (StoredSettings::getInstance()->getFontNames()); - return new ChoicePropertyComponent (Value (new FontNameValueSource (value)), title, fontNames); + Array values; + for (int i = 0; i < fontNames.size(); ++i) + values.add (fontNames[i]); + + return new ChoicePropertyComponent (Value (new FontNameValueSource (value)), title, fontNames, values); } private: @@ -525,7 +476,7 @@ public: static PropertyComponent* createProperty (const String& title, const Value& value) { - return StringListValueSource::create (title, Value (new FontStyleValueSource (value)), StringArray (getStyles())); + return new ChoicePropertyComponent (Value (new FontStyleValueSource (value)), title, StringArray (getStyles()), Array (getStyles())); } static const char* const* getStyles() @@ -549,34 +500,25 @@ void ComponentTypeInstance::addFontProperties (Array & props //============================================================================== void ComponentTypeInstance::addJustificationProperty (Array & props, const String& name, const Value& value, bool onlyHorizontal) { - ValueRemapperSource* remapper = new ValueRemapperSource (value); StringArray strings; if (onlyHorizontal) { const char* const layouts[] = { "Left", "Centred", "Right", 0 }; - const int justifications[] = { Justification::left, Justification::centred, Justification::right, 0 }; + const var justifications[] = { (int) Justification::left, (int) Justification::centred, (int) Justification::right, 0 }; - for (int i = 0; i < numElementsInArray (justifications) - 1; ++i) - remapper->addMapping (justifications[i], i + 1); - - strings = StringArray (layouts); + props.add (new ChoicePropertyComponent (value, name, StringArray (layouts), Array (justifications))); } else { const char* const layouts[] = { "Centred", "Centred-left", "Centred-right", "Centred-top", "Centred-bottom", "Top-left", "Top-right", "Bottom-left", "Bottom-right", 0 }; - const int justifications[] = { Justification::centred, Justification::centredLeft, Justification::centredRight, - Justification::centredTop, Justification::centredBottom, Justification::topLeft, - Justification::topRight, Justification::bottomLeft, Justification::bottomRight, 0 }; - - for (int i = 0; i < numElementsInArray (justifications) - 1; ++i) - remapper->addMapping (justifications[i], i + 1); + const var justifications[] = { (int) Justification::centred, (int) Justification::centredLeft, (int) Justification::centredRight, + (int) Justification::centredTop, (int) Justification::centredBottom, (int) Justification::topLeft, + (int) Justification::topRight, (int) Justification::bottomLeft, (int) Justification::bottomRight, var() }; - strings = StringArray (layouts); + props.add (new ChoicePropertyComponent (value, name, StringArray (layouts), Array (justifications))); } - - props.add (new ChoicePropertyComponent (Value (remapper), name, strings)); } //============================================================================== diff --git a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_JucerComponent.h b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_JucerComponent.h index 6537b9385d..7388750a72 100644 --- a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_JucerComponent.h +++ b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_JucerComponent.h @@ -35,22 +35,70 @@ class JucerComponent : public Component public: JucerComponent() { - addAndMakeVisible (comp = new ComponentDocument::TestComponent (0, File::nonexistent)); + } + + void paint (Graphics& g) + { + if (comp == 0) + drawComponentPlaceholder (g, getWidth(), getHeight(), "(Not a valid Jucer component)"); } void resized() { - comp->setBounds (getLocalBounds()); + if (comp != 0) + comp->setBounds (getLocalBounds()); } - void setJucerComp (ComponentDocument& document, const File& cppFile) + void setJucerComp (ComponentTypeInstance& item, const String& newProjectId) { - addAndMakeVisible (comp = new ComponentDocument::TestComponent (document.getProject(), cppFile)); - resized(); + if (projectId != newProjectId) + { + projectId = newProjectId; + comp = 0; + document = 0; + + if (newProjectId.isNotEmpty()) + { + const File file (getDocumentFile (item, projectId)); + + if (file.exists()) + { + ComponentDocument doc (item.getDocument().getProject(), file); + + if (doc.reload()) + { + addAndMakeVisible (comp = new ComponentDocument::TestComponent (doc)); + resized(); + } + } + } + } } private: + String projectId; + ScopedPointer document; ScopedPointer comp; + + const File getDocumentFile (ComponentTypeInstance& item, const String projectItemId) + { + const String projectId (projectItemId); + + if (projectId.isNotEmpty()) + { + Project* project = item.getDocument().getProject(); + + if (project != 0) + { + Project::Item item (project->getMainGroup().findItemWithID (projectId)); + + if (item.isValid()) + return item.getFile(); + } + } + + return File::nonexistent; + } }; //============================================================================== @@ -70,10 +118,35 @@ public: void update (ComponentTypeInstance& item, JucerComponent* comp) { + comp->setJucerComp (item, item [Ids::source].toString()); } void createProperties (ComponentTypeInstance& item, Array & props) { + StringArray names; + Array ids; + + names.add (""); + ids.add (var::null); + names.add (String::empty); + ids.add (var::null); + + { + Array comps; + findAllComponentDocumentsInProject (item, comps); + + for (int i = 0; i < comps.size(); ++i) + { + if (comps.getReference(i).getFile() != item.getDocument().getCppFile()) + { + names.add (comps.getReference(i).getName().toString()); + ids.add (comps.getReference(i).getID()); + } + } + } + + props.add (new ChoicePropertyComponent (item.getValue (Ids::source), "Source", names, ids)); + item.addFocusOrderProperty (props); } const String getClassName (ComponentTypeInstance& item) const @@ -85,6 +158,30 @@ public: { code.constructorCode << item.createConstructorStatement (String::empty); } + + //============================================================================== + static void findAllComponentDocumentsInProject (ComponentTypeInstance& item, Array & comps) + { + Project* project = item.getDocument().getProject(); + + if (project != 0) + findAllComponentDocumentsInProjectItem (project->getMainGroup(), comps); + } + + static void findAllComponentDocumentsInProjectItem (const Project::Item& item, Array & comps) + { + if (item.isGroup()) + { + const int num = item.getNumChildren(); + for (int i = 0; i < num; ++i) + findAllComponentDocumentsInProjectItem (item.getChild (i), comps); + } + else if (item.isFile()) + { + if (ComponentDocument::isComponentFile (item.getFile())) + comps.add (item); + } + } }; #endif diff --git a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h index bf0c1df98f..e845c7c327 100644 --- a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h +++ b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h @@ -74,7 +74,8 @@ public: item.addJustificationProperty (props, "Layout", item.getValue ("justification"), false); const char* const editModes[] = { "Read-only", "Edit on Single-Click", "Edit on Double-Click", 0 }; - props.add (new ChoicePropertyComponent (item.getValue (Ids::editMode), "Edit Mode", StringArray (editModes))); + const int values[] = { 1, 2, 3, 0 }; + props.add (new ChoicePropertyComponent (item.getValue (Ids::editMode), "Edit Mode", StringArray (editModes), Array (values))); item.addFontProperties (props, Ids::font); diff --git a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h index 4b32a078a9..2b51f32b38 100644 --- a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h +++ b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h @@ -54,10 +54,10 @@ public: void initialiseNew (ComponentTypeInstance& item) { + item.set (Ids::type, Slider::LinearHorizontal); item.set (Ids::min, 0); item.set (Ids::max, 100); item.set (Ids::interval, 1); - item.set (Ids::type, 1 + Slider::LinearHorizontal); item.set (Ids::textBoxPos, 2); item.set (Ids::editable, true); item.set (Ids::textBoxWidth, 80); @@ -68,8 +68,8 @@ public: void update (ComponentTypeInstance& item, Slider* comp) { comp->setRange ((double) item [Ids::min], (double) item [Ids::max], (double) item [Ids::interval]); - comp->setSliderStyle ((Slider::SliderStyle) ((int) item [Ids::type] - 1)); - comp->setTextBoxStyle ((Slider::TextEntryBoxPosition) ((int) item [Ids::textBoxPos] - 1), + comp->setSliderStyle ((Slider::SliderStyle) (int) item [Ids::type]); + comp->setTextBoxStyle ((Slider::TextEntryBoxPosition) (int) item [Ids::textBoxPos], ! (bool) item [Ids::editable], (int) item [Ids::textBoxWidth], (int) item [Ids::textBoxHeight]); comp->setSkewFactor ((double) item [Ids::skew]); @@ -86,10 +86,14 @@ public: const char* const types[] = { "LinearHorizontal", "LinearVertical", "LinearBar", "Rotary", "RotaryHorizontalDrag", "RotaryVerticalDrag", "IncDecButtons", "TwoValueHorizontal", "TwoValueVertical", "ThreeValueHorizontal", "ThreeValueVertical", 0 }; - props.add (new ChoicePropertyComponent (item.getValue (Ids::type), "Type", StringArray (types))); + const int typeValues[] = { (int) Slider::LinearHorizontal, (int) Slider::LinearVertical, (int) Slider::LinearBar, (int) Slider::Rotary, + (int) Slider::RotaryHorizontalDrag, (int) Slider::RotaryVerticalDrag, (int) Slider::IncDecButtons, (int) Slider::TwoValueHorizontal, + (int) Slider::TwoValueVertical, (int) Slider::ThreeValueHorizontal, (int) Slider::ThreeValueVertical }; + props.add (new ChoicePropertyComponent (item.getValue (Ids::type), "Type", StringArray (types), Array (typeValues, numElementsInArray (typeValues)))); const char* const textBoxPositions[] = { "NoTextBox", "TextBoxLeft", "TextBoxRight", "TextBoxAbove", "TextBoxBelow", 0 }; - props.add (new ChoicePropertyComponent (item.getValue (Ids::textBoxPos), "Text Box", StringArray (textBoxPositions))); + const int positionValues[] = { (int) Slider::NoTextBox, (int) Slider::TextBoxLeft, (int) Slider::TextBoxRight, (int) Slider::TextBoxAbove, (int) Slider::TextBoxBelow }; + props.add (new ChoicePropertyComponent (item.getValue (Ids::textBoxPos), "Text Box", StringArray (textBoxPositions), Array (positionValues, numElementsInArray (positionValues)))); props.add (new BooleanPropertyComponent (item.getValue (Ids::editable), "Editable", "Value can be edited")); props.add (new TextPropertyComponent (Value (new NumericValueSource (item.getValue ("textBoxWidth"))), "Text Box Width", 8, false)); @@ -143,8 +147,8 @@ public: << ", " << CodeHelpers::doubleLiteral (item [Ids::max]) << ", " << CodeHelpers::doubleLiteral (item [Ids::interval]) << ");" << newLine - << item.getMemberName() << "->setSliderStyle (Slider::" << sliderTypeString ((int) item [Ids::type] - 1) << ");" << newLine - << item.getMemberName() << "->setTextBoxStyle (Slider::" << sliderTextBoxString ((int) item [Ids::type] - 1) + << item.getMemberName() << "->setSliderStyle (Slider::" << sliderTypeString ((int) item [Ids::type]) << ");" << newLine + << item.getMemberName() << "->setTextBoxStyle (Slider::" << sliderTextBoxString ((int) item [Ids::type]) << ", " << CodeHelpers::boolLiteral (! (bool) item [Ids::editable]) << ", " << String ((int) item [Ids::textBoxWidth]) << ", " << String ((int) item [Ids::textBoxHeight]) diff --git a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_TextEditor.h b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_TextEditor.h index 8b6f273e95..c32acc017e 100644 --- a/extras/Jucer (experimental)/Source/model/Component/Types/jucer_TextEditor.h +++ b/extras/Jucer (experimental)/Source/model/Component/Types/jucer_TextEditor.h @@ -90,7 +90,8 @@ public: props.getLast()->setTooltip ("The editor's initial content."); const char* const modes[] = { "Single-Line", "Multi-Line (Return key starts new line)", "Multi-Line (Return key disabled)", 0 }; - props.add (new ChoicePropertyComponent (item.getValue (Ids::mode), "Mode", StringArray (modes))); + const int values[] = { 1, 2, 3, 0 }; + props.add (new ChoicePropertyComponent (item.getValue (Ids::mode), "Mode", StringArray (modes), Array (values))); props.add (new BooleanPropertyComponent (item.getValue (Ids::readOnly), "Read-Only", "Read-Only")); props.add (new BooleanPropertyComponent (item.getValue (Ids::scrollbarsShown), "Scrollbars", "Scrollbars Shown")); diff --git a/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp b/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp index 5e6f15a55f..85cca7eff6 100644 --- a/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp @@ -374,18 +374,6 @@ const ValueTree ComponentDocument::performNewComponentMenuItem (int menuResultCo return ValueTree::invalid; } -Component* ComponentDocument::findComponentForState (Component* compHolder, const ValueTree& state) -{ - for (int i = compHolder->getNumChildComponents(); --i >= 0;) - { - Component* const c = compHolder->getChildComponent (i); - if (isStateForComponent (state, c)) - return c; - } - - return 0; -} - void ComponentDocument::updateComponentsIn (Component* compHolder) { int i; @@ -426,48 +414,48 @@ void ComponentDocument::updateComponentsIn (Component* compHolder) } //============================================================================== -ComponentDocument::TestComponent::TestComponent (ComponentDocument& document_) - : document (new ComponentDocument (document_)) +ComponentDocument::TestComponent::TestComponent (ComponentDocument& document) { - setupDocument(); -} + background = Colour::fromString (document.getBackgroundColour().toString()); + layoutManager = new ComponentAutoLayoutManager (this); -ComponentDocument::TestComponent::TestComponent (Project* project, const File& cppFile) - : document (new ComponentDocument (project, cppFile)) -{ - if (document->reload()) - setupDocument(); - else - document = 0; -} + setSize (document.getCanvasWidth().getValue(), + document.getCanvasHeight().getValue()); -ComponentDocument::TestComponent::~TestComponent() -{ - deleteAllChildren(); -} + int i; + for (i = 0; i < document.getNumComponents(); ++i) + { + Component* c = document.createComponent (i); + addAndMakeVisible (c); -void ComponentDocument::TestComponent::setupDocument() -{ - document->setUsingTemporaryCanvasSize (true); + const ValueTree state (document.getComponent (i)); + layoutManager->setComponentLayout (c, state [ComponentDocument::memberNameProperty], + document.getCoordsFor (state)); + } - setSize (document->getCanvasWidth().getValue(), - document->getCanvasHeight().getValue()); -} + for (i = 0; i < document.getMarkerListX().size(); ++i) + { + const ValueTree marker (document.getMarkerListX().getMarker (i)); + layoutManager->setMarker (document.getMarkerListX().getName (marker), + document.getMarkerListX().getCoordinate (marker)); + } -void ComponentDocument::TestComponent::resized() -{ - if (document != 0) + for (i = 0; i < document.getMarkerListY().size(); ++i) { - document->getCanvasWidth() = getWidth(); - document->getCanvasHeight() = getHeight(); - document->updateComponentsIn (this); + const ValueTree marker (document.getMarkerListY().getMarker (i)); + layoutManager->setMarker (document.getMarkerListY().getName (marker), + document.getMarkerListY().getCoordinate (marker)); } } +ComponentDocument::TestComponent::~TestComponent() +{ + deleteAllChildren(); +} + void ComponentDocument::TestComponent::paint (Graphics& g) { - if (document == 0) - drawComponentPlaceholder (g, getWidth(), getHeight(), "(Not a valid Jucer component)"); + g.fillAll (background); } //============================================================================== @@ -705,14 +693,21 @@ bool ComponentDocument::containsComponent (Component* comp) const const ValueTree ComponentDocument::getComponentState (Component* comp) const { jassert (comp != 0); - const ValueTree comps (getComponentGroup()); + return getComponentGroup().getChildWithProperty (idProperty, getJucerIDFor (comp)); +} - for (int i = 0; i < comps.getNumChildren(); ++i) - if (isStateForComponent (comps.getChild(i), comp)) - return comps.getChild(i); +Component* ComponentDocument::findComponentForState (Component* compHolder, const ValueTree& state) +{ + const String compId (state [idProperty].toString()); - jassertfalse; - return ValueTree::invalid; + for (int i = compHolder->getNumChildComponents(); --i >= 0;) + { + Component* const c = compHolder->getChildComponent (i); + if (getJucerIDFor (c) == compId) + return c; + } + + return 0; } bool ComponentDocument::isStateForComponent (const ValueTree& storedState, Component* comp) const diff --git a/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h b/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h index d8f0988870..2750d4b5fe 100644 --- a/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h +++ b/extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h @@ -166,16 +166,14 @@ public: class TestComponent : public Component { public: - TestComponent (ComponentDocument& document_); - TestComponent (Project* project, const File& cppFile); + TestComponent (ComponentDocument& document); ~TestComponent(); - void resized(); void paint (Graphics& g); private: - ScopedPointer document; - void setupDocument(); + ScopedPointer layoutManager; + Colour background; }; juce_UseDebuggingNewOperator diff --git a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp index 7bccc6fd87..b84376832a 100644 --- a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp @@ -75,24 +75,24 @@ void DrawableDocument::checkRootObject() const String DrawableDocument::getIdFor (const ValueTree& object) { - return object ["id"]; + return object [Ids::id_]; } //============================================================================== void DrawableDocument::setName (const String& name) { - root.setProperty ("name", name, getUndoManager()); + root.setProperty (Ids::name, name, getUndoManager()); } const String DrawableDocument::getName() const { - return root ["name"]; + return root [Ids::name]; } void DrawableDocument::addMissingIds (ValueTree tree) const { - if (! tree.hasProperty ("id")) - tree.setProperty ("id", createAlphaNumericUID(), 0); + if (! tree.hasProperty (Ids::id_)) + tree.setProperty (Ids::id_, createAlphaNumericUID(), 0); for (int i = tree.getNumChildren(); --i >= 0;) addMissingIds (tree.getChild(i)); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp index 5e4c6fa624..eb25c6dd73 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp @@ -69,7 +69,7 @@ Project::~Project() //============================================================================== void Project::setTitle (const String& newTitle) { - projectRoot.setProperty ("name", newTitle, getUndoManagerFor (projectRoot)); + projectRoot.setProperty (Ids::name, newTitle, getUndoManagerFor (projectRoot)); getMainGroup().getName() = newTitle; } @@ -81,13 +81,13 @@ const String Project::getDocumentTitle() void Project::updateProjectSettings() { projectRoot.setProperty ("jucerVersion", ProjectInfo::versionString, 0); - projectRoot.setProperty ("name", getDocumentTitle(), 0); + projectRoot.setProperty (Ids::name, getDocumentTitle(), 0); } void Project::setMissingDefaultValues() { - if (! projectRoot.hasProperty ("id")) - projectRoot.setProperty ("id", createAlphaNumericUID(), 0); + if (! projectRoot.hasProperty (Ids::id_)) + projectRoot.setProperty (Ids::id_, createAlphaNumericUID(), 0); // Create main file group if missing if (! projectRoot.getChildWithName (Tags::projectMainGroup).isValid()) @@ -108,7 +108,7 @@ void Project::setMissingDefaultValues() getVersion() = "1.0.0"; if (! projectRoot.hasProperty ("juceLinkage")) - getJuceLinkageModeValue() = (int) useAmalgamatedJuceViaMultipleTemplates; + getJuceLinkageModeValue() = useAmalgamatedJuceViaMultipleTemplates; const String juceFolderPath (getRelativePathForFile (StoredSettings::getInstance()->getLastKnownJuceFolder())); @@ -210,7 +210,7 @@ void Project::setLastDocumentOpened (const File& file) void Project::valueTreePropertyChanged (ValueTree& tree, const Identifier& property) { if (isLibrary()) - getJuceLinkageModeValue() = (int) notLinkedToJuce; + getJuceLinkageModeValue() = notLinkedToJuce; changed(); } @@ -266,41 +266,24 @@ bool Project::shouldBeAddedToBinaryResourcesByDefault (const File& file) return ! file.hasFileExtension (sourceFileExtensions); } -Value Project::getProjectType() const -{ - static const char* mappings[] = { "guiapp", "1", "consoleapp", "2", "audioplug", "3", "library", "4", "browserplug", "5", 0 }; - return Value (new ValueRemapperSource (projectRoot.getPropertyAsValue ("projectType", getUndoManagerFor (projectRoot)), mappings)); -} - -const StringArray Project::getProjectTypes() const -{ - const char* types[] = { "Application (GUI)", - "Application (Non-GUI)", - "Audio Plug-in", - //"Browser Plug-in", - "Static Library", - 0 }; - - return StringArray (types); -} - -Value Project::getJuceLinkageModeValue() const -{ - static const char* mappings[] = { "none", "1", "static", "2", "amalg_big", "3", "amalg_template", "4", "amalg_multi", "5", 0 }; - return Value (new ValueRemapperSource (projectRoot.getPropertyAsValue ("juceLinkage", getUndoManagerFor (projectRoot)), mappings)); -} - -const StringArray Project::getJuceLinkageModes() const -{ - const char* types[] = { "Not linked to Juce", - "Linked to Juce Static Library", - "Include Juce Amalgamated Files", - "Include Juce Source Code Directly (In a single file)", - "Include Juce Source Code Directly (Split across several files)", - 0 }; - - return StringArray (types); -} +//============================================================================== +const char* const Project::application = "guiapp"; +const char* const Project::commandLineApp = "consoleapp"; +const char* const Project::audioPlugin = "audioplug"; +const char* const Project::library = "library"; +const char* const Project::browserPlugin = "browserplug"; + +bool Project::isLibrary() const { return getProjectType().toString() == library; } +bool Project::isGUIApplication() const { return getProjectType().toString() == application; } +bool Project::isCommandLineApp() const { return getProjectType().toString() == commandLineApp; } +bool Project::isAudioPlugin() const { return getProjectType().toString() == audioPlugin; } +bool Project::isBrowserPlugin() const { return getProjectType().toString() == browserPlugin; } + +const char* const Project::notLinkedToJuce = "none"; +const char* const Project::useLinkedJuce = "static"; +const char* const Project::useAmalgamatedJuce = "amalg_big"; +const char* const Project::useAmalgamatedJuceViaSingleTemplate = "amalg_template"; +const char* const Project::useAmalgamatedJuceViaMultipleTemplates = "amalg_multi"; const File Project::getLocalJuceFolder() { @@ -326,9 +309,13 @@ void Project::createPropertyEditors (Array & props) props.add (new TextPropertyComponent (getVersion(), "Project Version", 16, false)); props.getLast()->setTooltip ("The project's version number, This should be in the format major.minor.point"); - props.add (new ChoicePropertyComponent (getProjectType(), "Project Type", getProjectTypes())); + const char* projectTypes[] = { "Application (GUI)", "Application (Non-GUI)", "Audio Plug-in", "Static Library", 0 }; + const char* projectTypeValues[] = { application, commandLineApp, audioPlugin, library, 0 }; + props.add (new ChoicePropertyComponent (getProjectType(), "Project Type", StringArray (projectTypes), Array (projectTypeValues))); - props.add (new ChoicePropertyComponent (getJuceLinkageModeValue(), "Juce Linkage Method", getJuceLinkageModes())); + const char* linkageTypes[] = { "Not linked to Juce", "Linked to Juce Static Library", "Include Juce Amalgamated Files", "Include Juce Source Code Directly (In a single file)", "Include Juce Source Code Directly (Split across several files)", 0 }; + const char* linkageTypeValues[] = { notLinkedToJuce, useLinkedJuce, useAmalgamatedJuce, useAmalgamatedJuceViaSingleTemplate, useAmalgamatedJuceViaMultipleTemplates, 0 }; + props.add (new ChoicePropertyComponent (getJuceLinkageModeValue(), "Juce Linkage Method", StringArray (linkageTypes), Array (linkageTypeValues))); props.getLast()->setTooltip ("The method by which your project will be linked to Juce."); props.add (new TextPropertyComponent (getBundleIdentifier(), "Bundle Identifier", 256, false)); @@ -438,12 +425,30 @@ Project::Item::~Item() { } -const String Project::Item::getID() const { return node ["id"]; } +const String Project::Item::getID() const { return node [Ids::id_]; } bool Project::Item::isFile() const { return node.hasType (Tags::file); } bool Project::Item::isGroup() const { return node.hasType (Tags::group) || isMainGroup(); } bool Project::Item::isMainGroup() const { return node.hasType (Tags::projectMainGroup); } +Project::Item Project::Item::findItemWithID (const String& targetId) const +{ + if (node [Ids::id_] == targetId) + return *this; + + if (isGroup()) + { + for (int i = getNumChildren(); --i >= 0;) + { + Item found (getChild(i).findItemWithID (targetId)); + if (found.isValid()) + return found; + } + } + + return Item (project, ValueTree::invalid); +} + bool Project::Item::canContain (const Item& child) const { if (isFile()) @@ -484,7 +489,7 @@ Value Project::Item::getShouldAddToResourceValue() const const File Project::Item::getFile() const { if (isFile()) - return project.resolveFilename (node ["file"].toString()); + return project.resolveFilename (node [Ids::file].toString()); else return File::nonexistent; } @@ -492,8 +497,8 @@ const File Project::Item::getFile() const void Project::Item::setFile (const File& file) { jassert (isFile()); - node.setProperty ("file", project.getRelativePathForFile (file), getUndoManager()); - node.setProperty ("name", file.getFileName(), getUndoManager()); + node.setProperty (Ids::file, project.getRelativePathForFile (file), getUndoManager()); + node.setProperty (Ids::name, file.getFileName(), getUndoManager()); jassert (getFile() == file); } @@ -565,12 +570,12 @@ const File Project::Item::determineGroupFolder() const void Project::Item::initialiseNodeValues() { - if (! node.hasProperty ("id")) - node.setProperty ("id", createAlphaNumericUID(), 0); + if (! node.hasProperty (Ids::id_)) + node.setProperty (Ids::id_, createAlphaNumericUID(), 0); if (isFile()) { - node.setProperty ("name", getFile().getFileName(), 0); + node.setProperty (Ids::name, getFile().getFileName(), 0); } else if (isGroup()) { @@ -581,7 +586,7 @@ void Project::Item::initialiseNodeValues() Value Project::Item::getName() const { - return node.getPropertyAsValue ("name", getUndoManager()); + return node.getPropertyAsValue (Ids::name, getUndoManager()); } void Project::Item::addChild (const Item& newChild, int insertIndex) @@ -606,7 +611,7 @@ struct ItemSorter { static int compareElements (const ValueTree& first, const ValueTree& second) { - return first["name"].toString().compareIgnoreCase (second["name"].toString()); + return first [Ids::name].toString().compareIgnoreCase (second [Ids::name].toString()); } }; @@ -716,16 +721,17 @@ void Project::getJuceConfigFlags (OwnedArray & flags) } } +const char* const Project::configFlagDefault = "default"; +const char* const Project::configFlagEnabled = "enabled"; +const char* const Project::configFlagDisabled = "disabled"; + Value Project::getJuceConfigFlag (const String& name) { - static const char* valueRemappings[] = { "enabled", "1", "disabled", "2", "default", "3", 0 }; + const ValueTree configNode (getJuceConfigNode()); + Value v (configNode.getPropertyAsValue (name, getUndoManagerFor (configNode))); - ValueTree configNode (getJuceConfigNode()); - Value v (new ValueRemapperSource (configNode.getPropertyAsValue (name, getUndoManagerFor (configNode)), - valueRemappings)); - - if ((int) v.getValue() == 0) - v = 3; + if (v.getValue().toString().isEmpty()) + v = configFlagDefault; return v; } @@ -751,7 +757,7 @@ bool Project::hasConfigurationNamed (const String& name) const { const ValueTree configs (getConfigurations()); for (int i = configs.getNumChildren(); --i >= 0;) - if (configs.getChild(i) ["name"].toString() == name) + if (configs.getChild(i) [Ids::name].toString() == name) return true; return false; @@ -774,7 +780,7 @@ const String Project::getUniqueConfigName (String name) const void Project::addNewConfiguration (BuildConfiguration* configToCopy) { - const String configName (getUniqueConfigName (configToCopy != 0 ? configToCopy->config ["name"].toString() + const String configName (getUniqueConfigName (configToCopy != 0 ? configToCopy->config [Ids::name].toString() : "New Build Configuration")); ValueTree configs (getConfigurations()); @@ -789,7 +795,7 @@ void Project::addNewConfiguration (BuildConfiguration* configToCopy) if (configToCopy != 0) newConfig = configToCopy->config.createCopy(); - newConfig.setProperty ("name", configName, 0); + newConfig.setProperty (Ids::name, configName, 0); configs.addChild (newConfig, -1, getUndoManagerFor (configs)); } @@ -846,8 +852,10 @@ const String Project::BuildConfiguration::getGCCOptimisationFlag() const return String (level <= 1 ? "0" : (level == 2 ? "s" : "3")); } -static const char* osxSDKs[] = { "Use default", "10.4 SDK", "10.5 SDK", "10.6 SDK", 0 }; -static const char* osxSDKMappings[] = { "default", "1", "10.4 SDK", "2", "10.5 SDK", "3", "10.6 SDK", "4", "10.7 SDK", "5", 0 }; +const char* const Project::BuildConfiguration::osxVersionDefault = "default"; +const char* const Project::BuildConfiguration::osxVersion10_4 = "10.4 SDK"; +const char* const Project::BuildConfiguration::osxVersion10_5 = "10.5 SDK"; +const char* const Project::BuildConfiguration::osxVersion10_6 = "10.6 SDK"; void Project::BuildConfiguration::createPropertyEditors (Array & props) { @@ -858,7 +866,8 @@ void Project::BuildConfiguration::createPropertyEditors (Array setTooltip ("If enabled, this means that the configuration should be built with debug synbols."); const char* optimisationLevels[] = { "No optimisation", "Optimise for size and speed", "Optimise for maximum speed", 0 }; - props.add (new ChoicePropertyComponent (getOptimisationLevel(), "Optimisation", StringArray (optimisationLevels))); + const int optimisationLevelValues[] = { 1, 2, 3, 0 }; + props.add (new ChoicePropertyComponent (getOptimisationLevel(), "Optimisation", StringArray (optimisationLevels), Array (optimisationLevelValues))); props.getLast()->setTooltip ("The optimisation level for this configuration"); props.add (new TextPropertyComponent (getTargetBinaryName(), "Binary name", 256, false)); @@ -873,16 +882,19 @@ void Project::BuildConfiguration::createPropertyEditors (Array setTooltip ("Extra preprocessor definitions. Use whitespace or commas as a delimiter."); - if ((int) getMacSDKVersion().getValue() == 0) - getMacSDKVersion() = 1; + if (getMacSDKVersion().toString().isEmpty()) + getMacSDKVersion() = osxVersionDefault; + + const char* osxVersions[] = { "Use Default", osxVersion10_4, osxVersion10_5, osxVersion10_6, 0 }; + const char* osxVersionValues[] = { osxVersionDefault, osxVersion10_4, osxVersion10_5, osxVersion10_6, 0 }; - props.add (new ChoicePropertyComponent (getMacSDKVersion(), "OSX Base SDK Version", StringArray (osxSDKs))); + props.add (new ChoicePropertyComponent (getMacSDKVersion(), "OSX Base SDK Version", StringArray (osxVersions), Array (osxVersionValues))); props.getLast()->setTooltip ("The version of OSX to link against in the XCode build."); - if ((int) getMacCompatibilityVersion().getValue() == 0) - getMacCompatibilityVersion() = 1; + if (getMacCompatibilityVersion().toString().isEmpty()) + getMacCompatibilityVersion() = osxVersionDefault; - props.add (new ChoicePropertyComponent (getMacCompatibilityVersion(), "OSX Compatibility Version", StringArray (osxSDKs))); + props.add (new ChoicePropertyComponent (getMacCompatibilityVersion(), "OSX Compatibility Version", StringArray (osxVersions), Array (osxVersionValues))); props.getLast()->setTooltip ("The minimum version of OSX that the target binary will be compatible with."); for (int i = props.size(); --i >= 0;) @@ -904,16 +916,6 @@ const StringArray Project::BuildConfiguration::getHeaderSearchPaths() const return s; } -Value Project::BuildConfiguration::getMacSDKVersion() const -{ - return Value (new ValueRemapperSource (config.getPropertyAsValue ("osxSDK", getUndoManager()), osxSDKMappings)); -} - -Value Project::BuildConfiguration::getMacCompatibilityVersion() const -{ - return Value (new ValueRemapperSource (config.getPropertyAsValue ("osxCompatibility", getUndoManager()), osxSDKMappings)); -} - //============================================================================== ValueTree Project::getExporters() { diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h index 1941d74ce0..c8d84a0d92 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h @@ -52,7 +52,7 @@ public: ValueTree getProjectRoot() const { return projectRoot; } Value getProjectName() { return getMainGroup().getName(); } const String getProjectFilenameRoot() { return File::createLegalFileName (getDocumentTitle()); } - const String getProjectUID() const { return projectRoot ["id"]; } + const String getProjectUID() const { return projectRoot [Ids::id_]; } //============================================================================== bool shouldBeAddedToBinaryResourcesByDefault (const File& file); @@ -64,42 +64,35 @@ public: void createPropertyEditors (Array & properties); //============================================================================== - // project type info - enum ProjectType - { - application = 1, // must all be sequntial, starting from 1, so that combo boxes can update correctly - commandLineApp = 2, - audioPlugin = 3, - library = 4, - browserPlugin = 5 - }; + // project types + static const char* const application; + static const char* const commandLineApp; + static const char* const audioPlugin; + static const char* const library; + static const char* const browserPlugin; - const StringArray getProjectTypes() const; - Value getProjectType() const; + Value getProjectType() const { return getProjectValue ("projectType"); } - bool isLibrary() const { return (int) getProjectType().getValue() == (int) library; } - bool isGUIApplication() const { return (int) getProjectType().getValue() == (int) application; } - bool isCommandLineApp() const { return (int) getProjectType().getValue() == (int) commandLineApp; } - bool isAudioPlugin() const { return (int) getProjectType().getValue() == (int) audioPlugin; } - bool isBrowserPlugin() const { return (int) getProjectType().getValue() == (int) browserPlugin; } + bool isLibrary() const; + bool isGUIApplication() const; + bool isCommandLineApp() const; + bool isAudioPlugin() const; + bool isBrowserPlugin() const; Value getVersion() const { return getProjectValue ("version"); } Value getBundleIdentifier() const { return getProjectValue ("bundleIdentifier"); } void setBundleIdentifierToDefault() { getBundleIdentifier() = "com.yourcompany." + CodeHelpers::makeValidIdentifier (getProjectName().toString(), false, true, false); } //============================================================================== - enum JuceLinkage - { - notLinkedToJuce = 1, // must all be sequntial, starting from 1, so that combo boxes can update correctly - useLinkedJuce = 2, - useAmalgamatedJuce = 3, - useAmalgamatedJuceViaSingleTemplate = 4, - useAmalgamatedJuceViaMultipleTemplates = 5, - }; + // linkage modes.. + static const char* const notLinkedToJuce; + static const char* const useLinkedJuce; + static const char* const useAmalgamatedJuce; + static const char* const useAmalgamatedJuceViaSingleTemplate; + static const char* const useAmalgamatedJuceViaMultipleTemplates; - const StringArray getJuceLinkageModes() const; - Value getJuceLinkageModeValue() const; - JuceLinkage getJuceLinkageMode() const { return (JuceLinkage) (int) getJuceLinkageModeValue().getValue(); } + Value getJuceLinkageModeValue() const { return getProjectValue ("juceLinkage"); } + const String getJuceLinkageMode() const { return getJuceLinkageModeValue().toString(); } bool isUsingWrapperFiles() const { return isUsingFullyAmalgamatedFile() || isUsingSingleTemplateFile() || isUsingMultipleTemplateFiles(); } bool isUsingFullyAmalgamatedFile() const { return getJuceLinkageMode() == useAmalgamatedJuce; } @@ -112,7 +105,7 @@ public: Value shouldBuildVST() const { return getProjectValue ("buildVST"); } Value shouldBuildRTAS() const { return getProjectValue ("buildRTAS"); } Value shouldBuildAU() const { return getProjectValue ("buildAU"); } - bool shouldAddVSTFolderToPath() { return (isAudioPlugin() && (bool) shouldBuildVST().getValue()) || (int) getJuceConfigFlag ("JUCE_PLUGINHOST_VST").getValue() == 1; } + bool shouldAddVSTFolderToPath() { return (isAudioPlugin() && (bool) shouldBuildVST().getValue()) || getJuceConfigFlag ("JUCE_PLUGINHOST_VST").toString() == configFlagEnabled; } Value getPluginName() const { return getProjectValue ("pluginName"); } Value getPluginDesc() const { return getProjectValue ("pluginDesc"); } @@ -172,6 +165,7 @@ public: bool isMainGroup() const; const String getID() const; + Item findItemWithID (const String& targetId) const; // (recursive search) //============================================================================== Value getName() const; @@ -227,19 +221,24 @@ public: void createPropertyEditors (Array & properties); //============================================================================== - Value getName() const { return config.getPropertyAsValue ("name", getUndoManager()); } - Value isDebug() const { return config.getPropertyAsValue ("isDebug", getUndoManager()); } - Value getTargetBinaryName() const { return config.getPropertyAsValue ("targetName", getUndoManager()); } + Value getName() const { return getValue ("name"); } + Value isDebug() const { return getValue ("isDebug"); } + Value getTargetBinaryName() const { return getValue ("targetName"); } // the path relative to the build folder in which the binary should go - Value getTargetBinaryRelativePath() const { return config.getPropertyAsValue ("binaryPath", getUndoManager()); } - Value getOptimisationLevel() const { return config.getPropertyAsValue ("optimisation", getUndoManager()); } + Value getTargetBinaryRelativePath() const { return getValue ("binaryPath"); } + Value getOptimisationLevel() const { return getValue ("optimisation"); } const String getGCCOptimisationFlag() const; - Value getPreprocessorDefs() const { return config.getPropertyAsValue ("defines", getUndoManager()); } + Value getPreprocessorDefs() const { return getValue ("defines"); } const StringArray parsePreprocessorDefs() const; - Value getHeaderSearchPath() const { return config.getPropertyAsValue ("headerPath", getUndoManager()); } + Value getHeaderSearchPath() const { return getValue ("headerPath"); } const StringArray getHeaderSearchPaths() const; - Value getMacSDKVersion() const; - Value getMacCompatibilityVersion() const; + + static const char* const osxVersionDefault; + static const char* const osxVersion10_4; + static const char* const osxVersion10_5; + static const char* const osxVersion10_6; + Value getMacSDKVersion() const { return getValue ("osxSDK"); } + Value getMacCompatibilityVersion() const { return getValue ("osxCompatibility"); } //============================================================================== private: @@ -247,6 +246,7 @@ public: Project* project; ValueTree config; + Value getValue (const char* name) const { return config.getPropertyAsValue (name, getUndoManager()); } UndoManager* getUndoManager() const { return project->getUndoManagerFor (config); } BuildConfiguration (Project* project, const ValueTree& configNode); @@ -275,6 +275,10 @@ public: }; void getJuceConfigFlags (OwnedArray & flags); + + static const char* const configFlagDefault; + static const char* const configFlagEnabled; + static const char* const configFlagDisabled; Value getJuceConfigFlag (const String& name); //============================================================================== diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h index bcba4b7134..0a907b0a38 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h @@ -125,8 +125,9 @@ public: if (project.isLibrary()) { - static const char* const libTypes[] = { "Static Library (.lib)", "Dynamic Library (.dll)", 0 }; - props.add (new ChoicePropertyComponent (getLibraryType(), "Library Type", StringArray (libTypes))); + const char* const libTypes[] = { "Static Library (.lib)", "Dynamic Library (.dll)", 0 }; + const int libTypeValues[] = { 1, 2, 0 }; + props.add (new ChoicePropertyComponent (getLibraryType(), "Library Type", StringArray (libTypes), Array (libTypeValues))); props.add (new TextPropertyComponent (getSetting ("libraryName_Debug"), "Library Name (Debug)", 128, false)); props.getLast()->setTooltip ("If set, this name will override the binary name specified in the configuration settings, for a debug build. You must include the .lib or .dll suffix on this filename."); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h index 60cdeb923c..6255cdd462 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h @@ -397,16 +397,12 @@ private: if (getExtraCompilerFlags().toString().isNotEmpty()) s.add ("OTHER_CPLUSPLUSFLAGS = " + getExtraCompilerFlags().toString()); - switch ((int) project.getProjectType().getValue()) + if (project.isGUIApplication()) { - case Project::application: s.add ("INSTALL_PATH = \"$(HOME)/Applications\""); - break; - - case Project::commandLineApp: - break; - - case Project::audioPlugin: + } + else if (project.isAudioPlugin()) + { s.add ("LIBRARY_STYLE = Bundle"); s.add ("INSTALL_PATH = \"$(HOME)/Library/Audio/Plug-Ins/Components/\""); s.add ("WRAPPER_EXTENSION = " + getAudioPluginBundleExtension()); @@ -414,14 +410,14 @@ private: s.add ("OTHER_REZFLAGS = \"-d ppc_$ppc -d i386_$i386 -d ppc64_$ppc64 -d x86_64_$x86_64" " -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers" " -I \\\"$(DEVELOPER_DIR)/Extras/CoreAudio/AudioUnits/AUPublic/AUBase\\\"\""); - break; - - case Project::browserPlugin: + } + else if (project.isBrowserPlugin()) + { s.add ("LIBRARY_STYLE = Bundle"); s.add ("INSTALL_PATH = \"/Library/Internet Plug-Ins/\""); - break; - - case Project::library: + } + else if (project.isLibrary()) + { if (config.getTargetBinaryRelativePath().toString().isNotEmpty()) { RelativePath binaryPath (config.getTargetBinaryRelativePath().toString(), RelativePath::projectFolder); @@ -433,10 +429,13 @@ private: s.add ("CONFIGURATION_BUILD_DIR = \"$(BUILD_DIR)\""); s.add ("DEPLOYMENT_LOCATION = YES"); - break; - - default: - jassertfalse; break; + } + else if (project.isCommandLineApp()) + { + } + else + { + jassertfalse; } if (iPhone) @@ -445,21 +444,29 @@ private: } else { - switch ((int) config.getMacSDKVersion().getValue()) + const String sdk (config.getMacSDKVersion().toString()); + const String sdkCompat (config.getMacCompatibilityVersion().toString()); + + if (sdk == Project::BuildConfiguration::osxVersion10_4) { - case 2: s.add ("SDKROOT = macosx10.4"); s.add ("GCC_VERSION = 4.0"); break; - case 3: s.add ("SDKROOT = macosx10.5"); break; - case 4: s.add ("SDKROOT = macosx10.6"); break; - default: break; + s.add ("SDKROOT = macosx10.4"); + s.add ("GCC_VERSION = 4.0"); } - - switch ((int) config.getMacCompatibilityVersion().getValue()) + else if (sdk == Project::BuildConfiguration::osxVersion10_5) { - case 2: s.add ("MACOSX_DEPLOYMENT_TARGET = 10.4"); break; - case 3: s.add ("MACOSX_DEPLOYMENT_TARGET = 10.5"); break; - case 4: s.add ("MACOSX_DEPLOYMENT_TARGET = 10.6"); break; - default: break; + s.add ("SDKROOT = macosx10.5"); } + else if (sdk == Project::BuildConfiguration::osxVersion10_6) + { + s.add ("SDKROOT = macosx10.6"); + } + + if (sdkCompat == Project::BuildConfiguration::osxVersion10_4) + s.add ("MACOSX_DEPLOYMENT_TARGET = 10.4"); + else if (sdkCompat == Project::BuildConfiguration::osxVersion10_5) + s.add ("MACOSX_DEPLOYMENT_TARGET = 10.5"); + else if (sdkCompat == Project::BuildConfiguration::osxVersion10_6) + s.add ("MACOSX_DEPLOYMENT_TARGET = 10.6"); s.add ("MACOSX_DEPLOYMENT_TARGET_ppc = 10.4"); } @@ -534,7 +541,7 @@ private: if (isAU()) s.addTokens ("AudioUnit CoreAudioKit AudioToolbox", false); - else if ((int) project.getJuceConfigFlag ("JUCE_PLUGINHOST_AU").getValue() == 1) + else if (project.getJuceConfigFlag ("JUCE_PLUGINHOST_AU").toString() == Project::configFlagEnabled) s.addTokens ("AudioUnit CoreAudioKit", false); } @@ -617,7 +624,7 @@ private: ValueTree* v = new ValueTree (fileRefID); v->setProperty ("isa", "PBXFileReference", 0); v->setProperty ("lastKnownFileType", lastKnownFileType, 0); - v->setProperty ("name", path.getFileName(), 0); + v->setProperty (Ids::name, path.getFileName(), 0); v->setProperty ("path", sanitisePath (path.toUnixStyle()), 0); v->setProperty ("sourceTree", sourceTree, 0); pbxFileReferences.add (v); @@ -705,7 +712,7 @@ private: ValueTree* v = new ValueTree (groupID); v->setProperty ("isa", "PBXGroup", 0); v->setProperty ("children", "(" + indentList (childIDs, ",") + " )", 0); - v->setProperty ("name", groupName, 0); + v->setProperty (Ids::name, groupName, 0); v->setProperty ("sourceTree", "", 0); groups.add (v); } @@ -788,7 +795,7 @@ private: ValueTree* v = new ValueTree (createID ("targetconfigid_" + configName)); v->setProperty ("isa", "XCBuildConfiguration", 0); v->setProperty ("buildSettings", "{" + indentList (buildSettings, ";") + " }", 0); - v->setProperty ("name", configName, 0); + v->setProperty (Ids::name, configName, 0); targetConfigs.add (v); } @@ -797,7 +804,7 @@ private: ValueTree* v = new ValueTree (createID ("projectconfigid_" + configName)); v->setProperty ("isa", "XCBuildConfiguration", 0); v->setProperty ("buildSettings", "{" + indentList (buildSettings, ";") + " }", 0); - v->setProperty ("name", configName, 0); + v->setProperty (Ids::name, configName, 0); projectConfigs.add (v); } @@ -814,7 +821,7 @@ private: v->setProperty ("defaultConfigurationIsVisible", (int) 0, 0); if (configsToUse[0] != 0) - v->setProperty ("defaultConfigurationName", configsToUse[0]->getProperty ("name"), 0); + v->setProperty ("defaultConfigurationName", configsToUse[0]->getProperty (Ids::name), 0); misc.add (v); } @@ -841,7 +848,7 @@ private: v->setProperty ("buildPhases", "(" + indentList (buildPhaseIDs, ",") + " )", 0); v->setProperty ("buildRules", "( )", 0); v->setProperty ("dependencies", "( )", 0); - v->setProperty ("name", project.getDocumentTitle(), 0); + v->setProperty (Ids::name, project.getDocumentTitle(), 0); v->setProperty ("productName", project.getDocumentTitle(), 0); v->setProperty ("productReference", createID ("__productFileID"), 0); @@ -887,7 +894,7 @@ private: void addPluginShellScriptPhase() { ValueTree* v = addBuildPhase ("PBXShellScriptBuildPhase", StringArray()); - v->setProperty ("name", "Copy to the different plugin folders", 0); + v->setProperty (Ids::name, "Copy to the different plugin folders", 0); v->setProperty ("shellPath", "/bin/sh", 0); v->setProperty ("shellScript", String::fromUTF8 (BinaryData::AudioPluginXCodeScript_txt, BinaryData::AudioPluginXCodeScript_txtSize) .replace ("\\", "\\\\") diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h index b72d9fc398..8f018a44de 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h @@ -41,36 +41,36 @@ public: const File oldFile (project.getFile()); project.setFile (projectFile); - switch (project.getJuceLinkageMode()) + const String linkageMode (project.getJuceLinkageMode()); + + if (linkageMode == Project::notLinkedToJuce) { - case Project::notLinkedToJuce: hasAppHeaderFile = ! project.isLibrary(); hasAppConfigFile = false; numJuceSourceFiles = 0; - break; - - case Project::useAmalgamatedJuce: - case Project::useAmalgamatedJuceViaSingleTemplate: + } + else if (linkageMode == Project::useAmalgamatedJuce + || linkageMode == Project::useAmalgamatedJuceViaSingleTemplate) + { hasAppHeaderFile = true; hasAppConfigFile = true; numJuceSourceFiles = 1; - break; - - case Project::useAmalgamatedJuceViaMultipleTemplates: + } + else if (linkageMode == Project::useAmalgamatedJuceViaMultipleTemplates) + { hasAppHeaderFile = true; hasAppConfigFile = true; numJuceSourceFiles = project.getNumSeparateAmalgamatedFiles(); - break; - - case Project::useLinkedJuce: + } + else if (linkageMode == Project::useLinkedJuce) + { hasAppHeaderFile = true; hasAppConfigFile = true; numJuceSourceFiles = 0; - break; - - default: + } + else + { jassertfalse; - break; } hasResources = (resourceFile.getNumFiles() > 0); @@ -160,18 +160,18 @@ private: for (int i = 0; i < flags.size(); ++i) { const Project::JuceConfigFlag* const f = flags[i]; - int value = (int) f->value.getValue(); + const String value (f->value.toString()); - if (value < 1 || value > 2) + if (value != Project::configFlagEnabled && value != Project::configFlagDisabled) out << "//#define "; else out << "#define "; out << f->symbol; - if (value == 1) + if (value == Project::configFlagEnabled) out << " 1"; - else if (value == 2) + else if (value == Project::configFlagDisabled) out << " 0"; out << newLine; diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectWizard.cpp b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectWizard.cpp index effd1c47c8..47b8ec3bb9 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectWizard.cpp +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectWizard.cpp @@ -70,7 +70,7 @@ public: File mainWindowH = mainWindowCpp.withFileExtension (".h"); String windowClassName = "MainAppWindow"; - project.getProjectType() = (int) Project::application; + project.getProjectType() = Project::application; Project::Item group (project.createNewGroup()); project.getMainGroup().addChild (group, 0); @@ -175,7 +175,7 @@ public: File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp"); - project.getProjectType() = (int) Project::commandLineApp; + project.getProjectType() = Project::commandLineApp; Project::Item group (project.createNewGroup()); project.getMainGroup().addChild (group, 0); @@ -237,12 +237,12 @@ public: File editorCppFile = getSourceFilesFolder().getChildFile ("PluginEditor.cpp"); File editorHFile = editorCppFile.withFileExtension (".h"); - project.getProjectType() = (int) Project::audioPlugin; + project.getProjectType() = Project::audioPlugin; Project::Item group (project.createNewGroup()); project.getMainGroup().addChild (group, 0); group.getName() = "Source"; - project.getJuceConfigFlag ("JUCE_QUICKTIME") = 2; // disabled because it interferes with RTAS build on PC + project.getJuceConfigFlag ("JUCE_QUICKTIME") = Project::configFlagDisabled; // disabled because it interferes with RTAS build on PC for (int i = project.getNumConfigurations(); --i >= 0;) project.getConfiguration(i).getTargetBinaryName() = File::createLegalFileName (appTitle); diff --git a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h index e25f8d5495..0096418dec 100644 --- a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h +++ b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h @@ -102,8 +102,8 @@ public: const String getUniqueName() const { - jassert (node ["id"].toString().isNotEmpty()); - return node ["id"]; + jassert (node [Ids::id_].toString().isNotEmpty()); + return node [Ids::id_]; } void itemOpennessChanged (bool isNowOpen) diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp index 0070144170..449813b489 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp @@ -81,8 +81,11 @@ public: return ! getCentreArea().contains (x, y); } - void updatePosition() + bool updatePosition() { + if (! objectState.getParent().isValid()) + return false; + const Rectangle bounds (canvas->getObjectPosition (objectState)); setBoundsInTargetSpace (bounds.expanded (borderThickness, borderThickness)); @@ -91,6 +94,8 @@ public: sizeGuides.getUnchecked(i)->setVisible (isVisible()); sizeGuides.getUnchecked(i)->updatePosition (bounds); } + + return true; } const String& getTargetObjectID() const { return objectId; } @@ -527,8 +532,15 @@ public: if (index >= 0) { - resizer->updatePosition(); - requiredIds.remove (index); + if (resizer->updatePosition()) + { + requiredIds.remove (index); + } + else + { + resizers.remove (i); + canvas->getSelection().deselect (requiredIds[i]); + } } else { diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp index f42aee3d89..c0db24f7a5 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp @@ -56,16 +56,18 @@ public: project.getJuceConfigFlags (flags); StringArray possibleValues; + possibleValues.add ("(Use default from juce_Config.h)"); possibleValues.add ("Enabled"); possibleValues.add ("Disabled"); - possibleValues.add ("(Use default from juce_Config.h)"); + + Array mappings; + mappings.add (Project::configFlagDefault); + mappings.add (Project::configFlagEnabled); + mappings.add (Project::configFlagDisabled); for (int i = 0; i < flags.size(); ++i) { - if ((int) flags[i]->value.getValue() == 0) - flags[i]->value = 3; - - ChoicePropertyComponent* c = new ChoicePropertyComponent (flags[i]->value, flags[i]->symbol, possibleValues); + ChoicePropertyComponent* c = new ChoicePropertyComponent (flags[i]->value, flags[i]->symbol, possibleValues, mappings); c->setTooltip (flags[i]->description); c->setPreferredHeight (22); props.add (c); @@ -254,13 +256,13 @@ void ProjectInformationComponent::rebuildConfigTabs() } } - lastProjectType = (Project::ProjectType) (int) project.getProjectType().getValue(); + lastProjectType = project.getProjectType().getValue(); } void ProjectInformationComponent::updateConfigTabs() { if (configTabBox->getNumTabs() != project.getNumConfigurations() + project.getNumExporters() + 2 - || lastProjectType != (Project::ProjectType) (int) project.getProjectType().getValue()) + || lastProjectType != project.getProjectType().getValue()) { rebuildConfigTabs(); } diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.h b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.h index 8d00814ee7..c513b339f3 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.h +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.h @@ -64,7 +64,7 @@ private: //[UserVariables] -- You can add your own custom variables in this section. Project& project; - Project::ProjectType lastProjectType; + var lastProjectType; void updateConfigTabs(); void showConfigMenu(); void showExporterMenu(); diff --git a/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp b/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp index 9e884b911b..75d6ce95b7 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp +++ b/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp @@ -420,3 +420,148 @@ void RectangleCoordinates::renameAnchorIfUsed (const String& oldName, const Stri top.renameAnchorIfUsed (oldName, newName, markerResolver); bottom.renameAnchorIfUsed (oldName, newName, markerResolver); } + + + +//============================================================================== +ComponentAutoLayoutManager::ComponentAutoLayoutManager (Component* parentComponent) + : parent (parentComponent) +{ + parent->addComponentListener (this); +} + +ComponentAutoLayoutManager::~ComponentAutoLayoutManager() +{ + parent->removeComponentListener (this); + + for (int i = components.size(); --i >= 0;) + components.getUnchecked(i)->component->removeComponentListener (this); +} + +void ComponentAutoLayoutManager::setMarker (const String& name, const Coordinate& coord) +{ + for (int i = markers.size(); --i >= 0;) + { + MarkerPosition* m = markers.getUnchecked(i); + if (m->markerName == name) + { + m->position = coord; + applyLayout(); + return; + } + } + + markers.add (new MarkerPosition (name, coord)); + applyLayout(); +} + +void ComponentAutoLayoutManager::setComponentLayout (Component* comp, const String& name, const RectangleCoordinates& coords) +{ + jassert (comp != 0); + + // All the components that this layout manages must be inside the parent component.. + jassert (parent->isParentOf (comp)); + + for (int i = components.size(); --i >= 0;) + { + ComponentPosition* c = components.getUnchecked(i); + if (c->component == comp) + { + c->name = name; + c->coords = coords; + triggerAsyncUpdate(); + return; + } + } + + components.add (new ComponentPosition (comp, name, coords)); + comp->addComponentListener (this); + triggerAsyncUpdate(); +} + +void ComponentAutoLayoutManager::applyLayout() +{ + for (int i = components.size(); --i >= 0;) + { + ComponentPosition* c = components.getUnchecked(i); + + // All the components that this layout manages must be inside the parent component.. + jassert (parent->isParentOf (c->component)); + + c->component->setBounds (c->coords.resolve (*this)); + } +} + +const Coordinate ComponentAutoLayoutManager::findMarker (const String& name, bool isHorizontal) const +{ + if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) parent->getWidth(), isHorizontal); + if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) parent->getHeight(), isHorizontal); + + if (name.containsChar ('.')) + { + const String compName (name.upToFirstOccurrenceOf (".", false, false).trim()); + const String edge (name.fromFirstOccurrenceOf (".", false, false).trim()); + + if (compName.isNotEmpty() && edge.isNotEmpty()) + { + for (int i = components.size(); --i >= 0;) + { + ComponentPosition* c = components.getUnchecked(i); + + if (c->name == compName) + { + if (edge == "left") return c->coords.left; + if (edge == "right") return c->coords.right; + if (edge == "top") return c->coords.top; + if (edge == "bottom") return c->coords.bottom; + } + } + } + } + + for (int i = markers.size(); --i >= 0;) + { + MarkerPosition* m = markers.getUnchecked(i); + + if (m->markerName == name) + return m->position; + } + + return Coordinate (isHorizontal); +} + +void ComponentAutoLayoutManager::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized) +{ + triggerAsyncUpdate(); + + if (parent == &component) + handleUpdateNowIfNeeded(); +} + +void ComponentAutoLayoutManager::componentBeingDeleted (Component& component) +{ + for (int i = components.size(); --i >= 0;) + { + ComponentPosition* c = components.getUnchecked(i); + if (c->component == &component) + { + components.remove (i); + break; + } + } +} + +void ComponentAutoLayoutManager::handleAsyncUpdate() +{ + applyLayout(); +} + +ComponentAutoLayoutManager::MarkerPosition::MarkerPosition (const String& name, const Coordinate& coord) + : markerName (name), position (coord) +{ +} + +ComponentAutoLayoutManager::ComponentPosition::ComponentPosition (Component* component_, const String& name_, const RectangleCoordinates& coords_) + : component (component_), name (name_), coords (coords_) +{ +} diff --git a/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h b/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h index 0bbf95a22e..fdf91f18f0 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h @@ -169,7 +169,8 @@ public: //============================================================================== class ComponentAutoLayoutManager : public ComponentListener, - public Coordinate::MarkerResolver + public Coordinate::MarkerResolver, + public AsyncUpdater { public: //============================================================================== @@ -179,7 +180,7 @@ public: //============================================================================== void setMarker (const String& name, const Coordinate& coord); - void setComponentLayout (Component* comp, const RectangleCoordinates& coords); + void setComponentLayout (Component* comp, const String& name, const RectangleCoordinates& coords); void applyLayout(); @@ -188,22 +189,28 @@ public: void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); void componentBeingDeleted (Component& component); + void handleAsyncUpdate(); + private: //============================================================================== - class ComponentPosition + struct ComponentPosition { - public: + ComponentPosition (Component* component, const String& name, const RectangleCoordinates& coords); + Component* component; + String name; RectangleCoordinates coords; }; - class MarkerPosition + struct MarkerPosition { - public: - const String markerName; + MarkerPosition (const String& name, const Coordinate& coord); + + String markerName; Coordinate position; }; + Component* parent; OwnedArray components; OwnedArray markers; }; diff --git a/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h b/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h index c433ab73a8..a6ce2d737d 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h @@ -84,10 +84,10 @@ public: virtual const String getChosenMarkerMenuItem (const Coordinate& coord, int itemId) const = 0; //============================================================================== - static const char* getMarkerTag() { return "MARKER"; } - static const char* getIdProperty() { return "id"; } - static const char* getMarkerNameProperty() { return "name"; } - static const char* getMarkerPosProperty() { return "position"; } + static const Identifier getMarkerTag() { static Identifier i ("MARKER"); return i; } + static const Identifier getIdProperty() { return Ids::id_; } + static const Identifier getMarkerNameProperty() { return Ids::name; } + static const Identifier getMarkerPosProperty() { return Ids::position; } //============================================================================== class MarkerNameValueSource : public Value::ValueSource, diff --git a/extras/Jucer (experimental)/Source/utility/jucer_ValueRemapperSource.h b/extras/Jucer (experimental)/Source/utility/jucer_ValueRemapperSource.h deleted file mode 100644 index 9480b40ab8..0000000000 --- a/extras/Jucer (experimental)/Source/utility/jucer_ValueRemapperSource.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-10 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online 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.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -#ifndef __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ -#define __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ - - -//============================================================================== -/** A ValueSource that remaps specific values to new values. -*/ -class ValueRemapperSource : public Value::ValueSource, - public Value::Listener -{ -public: - ValueRemapperSource (const Value& sourceValue_) - : sourceValue (sourceValue_) - { - sourceValue.addListener (this); - } - - ValueRemapperSource (const Value& sourceValue_, const char** mappings_) - : sourceValue (sourceValue_) - { - addMappings (mappings_); - sourceValue.addListener (this); - } - - ~ValueRemapperSource() {} - - void addMappings (const char* const* values) - { - while (values[0] != 0 && values[1] != 0) - { - addMapping (values[0], values[1]); - values += 2; - } - } - - void addMapping (const var& sourceValue_, const var& remappedValue) - { - mappings.add (sourceValue_); - mappings.add (remappedValue); - } - - const var getValue() const - { - const var sourceVar (sourceValue.getValue()); - - for (int i = 0; i < mappings.size(); i += 2) - if (sourceVar == mappings.getReference(i)) - return mappings.getReference (i + 1); - - return sourceVar; - } - - void setValue (const var& newValue) - { - var remappedVal (newValue); - - for (int i = 1; i < mappings.size(); i += 2) - { - if (newValue == mappings.getReference(i)) - { - remappedVal = mappings.getReference (i - 1); - break; - } - } - - if (remappedVal != sourceValue) - sourceValue = remappedVal; - } - - void valueChanged (Value&) - { - sendChangeMessage (true); - } - - //============================================================================== - juce_UseDebuggingNewOperator - -protected: - Value sourceValue; - Array mappings; - - ValueRemapperSource (const ValueRemapperSource&); - const ValueRemapperSource& operator= (const ValueRemapperSource&); -}; - -//============================================================================== -/** A ValueSource that converts strings into an ID suitable for a combo box. -*/ -class StringListValueSource : public Value::ValueSource, - public Value::Listener -{ -public: - StringListValueSource (const Value& sourceValue_, const StringArray& strings_) - : sourceValue (sourceValue_), strings (strings_) - { - sourceValue.addListener (this); - } - - ~StringListValueSource() {} - - const var getValue() const { return jmax (0, strings.indexOf (sourceValue.toString())) + 1; } - void setValue (const var& newValue) - { - const String newVal (strings [((int) newValue) - 1]); - - if (newVal != getValue().toString()) // this test is important, because if a property is missing, it won't - sourceValue = newVal; // create it (causing an unwanted undo action) when a control sets it to empty - } - - void valueChanged (Value&) { sendChangeMessage (true); } - - static ChoicePropertyComponent* create (const String& title, const Value& value, const StringArray& strings) - { - return new ChoicePropertyComponent (Value (new StringListValueSource (value, strings)), title, strings); - } - - //============================================================================== - juce_UseDebuggingNewOperator - -protected: - Value sourceValue; - StringArray strings; - - StringListValueSource (const StringListValueSource&); - const StringListValueSource& operator= (const StringListValueSource&); -}; - -//============================================================================== -/** -*/ -template -class NumericValueSource : public Value::ValueSource, - public Value::Listener -{ -public: - NumericValueSource (const Value& sourceValue_) - : sourceValue (sourceValue_) - { - sourceValue.addListener (this); - } - - ~NumericValueSource() {} - - void valueChanged (Value&) { sendChangeMessage (true); } - const var getValue() const { return (Type) sourceValue.getValue(); } - - void setValue (const var& newValue) - { - const Type newVal = (Type) newValue; - - if (newVal != (Type) getValue()) // this test is important, because if a property is missing, it won't - sourceValue = newVal; // create it (causing an unwanted undo action) when a control sets it to 0 - } - - //============================================================================== - juce_UseDebuggingNewOperator - -protected: - Value sourceValue; - - NumericValueSource (const NumericValueSource&); - const NumericValueSource& operator= (const NumericValueSource&); -}; - - -#endif // __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ diff --git a/extras/Jucer (experimental)/Source/utility/jucer_ValueSourceHelpers.h b/extras/Jucer (experimental)/Source/utility/jucer_ValueSourceHelpers.h new file mode 100644 index 0000000000..e3e55b099c --- /dev/null +++ b/extras/Jucer (experimental)/Source/utility/jucer_ValueSourceHelpers.h @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online 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.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ +#define __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ + + +//============================================================================== +/** +*/ +template +class NumericValueSource : public Value::ValueSource, + public Value::Listener +{ +public: + NumericValueSource (const Value& sourceValue_) + : sourceValue (sourceValue_) + { + sourceValue.addListener (this); + } + + ~NumericValueSource() {} + + void valueChanged (Value&) { sendChangeMessage (true); } + const var getValue() const { return (Type) sourceValue.getValue(); } + + void setValue (const var& newValue) + { + const Type newVal = (Type) newValue; + + if (newVal != (Type) getValue()) // this test is important, because if a property is missing, it won't + sourceValue = newVal; // create it (causing an unwanted undo action) when a control sets it to 0 + } + + //============================================================================== + juce_UseDebuggingNewOperator + +protected: + Value sourceValue; + + NumericValueSource (const NumericValueSource&); + const NumericValueSource& operator= (const NumericValueSource&); +}; + + +#endif // __JUCER_VALUEREMAPPERSOURCE_JUCEHEADER__ diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 9f05e2f113..8346aa8f78 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -11999,7 +11999,7 @@ double String::getDoubleValue() const throw() return CharacterFunctions::getDoubleValue (text); } -static const juce_wchar* const hexDigits = T("0123456789abcdef"); +static const juce_wchar* const hexDigits = JUCE_T("0123456789abcdef"); const String String::toHexString (const int number) { @@ -13254,12 +13254,12 @@ int XmlDocument::findNextTokenLength() throw() void XmlDocument::skipHeader() { - const juce_wchar* const found = CharacterFunctions::find (input, T("")); + input = CharacterFunctions::find (input, JUCE_T("?>")); if (input == 0) return; @@ -13268,7 +13268,7 @@ void XmlDocument::skipHeader() } skipNextWhiteSpace(); - const juce_wchar* docType = CharacterFunctions::find (input, T("")); + const juce_wchar* const closeComment = CharacterFunctions::find (input, JUCE_T("-->")); if (closeComment == 0) { @@ -13327,7 +13327,7 @@ void XmlDocument::skipNextWhiteSpace() } else if (input[1] == '?') { - const juce_wchar* const closeBracket = CharacterFunctions::find (input, T("?>")); + const juce_wchar* const closeBracket = CharacterFunctions::find (input, JUCE_T("?>")); if (closeBracket == 0) { @@ -13402,7 +13402,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) if (outOfData) return 0; - input = CharacterFunctions::find (input, T("<")); + input = CharacterFunctions::find (input, JUCE_T("<")); if (input != 0) { @@ -13522,7 +13522,7 @@ void XmlDocument::readChildElements (XmlElement* parent) if (input[1] == '/') { // our close tag.. - input = CharacterFunctions::find (input, T(">")); + input = CharacterFunctions::find (input, JUCE_T(">")); ++input; break; } @@ -13694,27 +13694,27 @@ void XmlDocument::readEntity (String& result) // skip over the ampersand ++input; - if (CharacterFunctions::compareIgnoreCase (input, T("amp;"), 4) == 0) + if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("amp;"), 4) == 0) { input += 4; result += '&'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("quot;"), 5) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("quot;"), 5) == 0) { input += 5; result += '"'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("apos;"), 5) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("apos;"), 5) == 0) { input += 5; result += '\''; } - else if (CharacterFunctions::compareIgnoreCase (input, T("lt;"), 3) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("lt;"), 3) == 0) { input += 3; result += '<'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("gt;"), 3) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("gt;"), 3) == 0) { input += 3; result += '>'; @@ -13775,7 +13775,7 @@ void XmlDocument::readEntity (String& result) else { const juce_wchar* const entityNameStart = input; - const juce_wchar* const closingSemiColon = CharacterFunctions::find (input, T(";")); + const juce_wchar* const closingSemiColon = CharacterFunctions::find (input, JUCE_T(";")); if (closingSemiColon == 0) { @@ -45539,30 +45539,30 @@ static bool isIdentifierBody (const juce_wchar c) throw() static bool isReservedKeyword (const juce_wchar* const token, const int tokenLength) throw() { static const juce_wchar* const keywords2Char[] = - { T("if"), T("do"), T("or"), T("id"), 0 }; + { JUCE_T("if"), JUCE_T("do"), JUCE_T("or"), JUCE_T("id"), 0 }; static const juce_wchar* const keywords3Char[] = - { T("for"), T("int"), T("new"), T("try"), T("xor"), T("and"), T("asm"), T("not"), 0 }; + { JUCE_T("for"), JUCE_T("int"), JUCE_T("new"), JUCE_T("try"), JUCE_T("xor"), JUCE_T("and"), JUCE_T("asm"), JUCE_T("not"), 0 }; static const juce_wchar* const keywords4Char[] = - { T("bool"), T("void"), T("this"), T("true"), T("long"), T("else"), T("char"), - T("enum"), T("case"), T("goto"), T("auto"), 0 }; + { JUCE_T("bool"), JUCE_T("void"), JUCE_T("this"), JUCE_T("true"), JUCE_T("long"), JUCE_T("else"), JUCE_T("char"), + JUCE_T("enum"), JUCE_T("case"), JUCE_T("goto"), JUCE_T("auto"), 0 }; static const juce_wchar* const keywords5Char[] = - { T("while"), T("bitor"), T("break"), T("catch"), T("class"), T("compl"), T("const"), T("false"), - T("float"), T("short"), T("throw"), T("union"), T("using"), T("or_eq"), 0 }; + { JUCE_T("while"), JUCE_T("bitor"), JUCE_T("break"), JUCE_T("catch"), JUCE_T("class"), JUCE_T("compl"), JUCE_T("const"), JUCE_T("false"), + JUCE_T("float"), JUCE_T("short"), JUCE_T("throw"), JUCE_T("union"), JUCE_T("using"), JUCE_T("or_eq"), 0 }; static const juce_wchar* const keywords6Char[] = - { T("return"), T("struct"), T("and_eq"), T("bitand"), T("delete"), T("double"), T("extern"), - T("friend"), T("inline"), T("not_eq"), T("public"), T("sizeof"), T("static"), T("signed"), - T("switch"), T("typeid"), T("wchar_t"), T("xor_eq"), 0}; + { JUCE_T("return"), JUCE_T("struct"), JUCE_T("and_eq"), JUCE_T("bitand"), JUCE_T("delete"), JUCE_T("double"), JUCE_T("extern"), + JUCE_T("friend"), JUCE_T("inline"), JUCE_T("not_eq"), JUCE_T("public"), JUCE_T("sizeof"), JUCE_T("static"), JUCE_T("signed"), + JUCE_T("switch"), JUCE_T("typeid"), JUCE_T("wchar_t"), JUCE_T("xor_eq"), 0}; static const juce_wchar* const keywordsOther[] = - { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), - T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), - T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), - T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), - T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; + { JUCE_T("const_cast"), JUCE_T("continue"), JUCE_T("default"), JUCE_T("explicit"), JUCE_T("mutable"), JUCE_T("namespace"), + JUCE_T("operator"), JUCE_T("private"), JUCE_T("protected"), JUCE_T("register"), JUCE_T("reinterpret_cast"), JUCE_T("static_cast"), + JUCE_T("template"), JUCE_T("typedef"), JUCE_T("typename"), JUCE_T("unsigned"), JUCE_T("virtual"), JUCE_T("volatile"), + JUCE_T("@implementation"), JUCE_T("@interface"), JUCE_T("@end"), JUCE_T("@synthesize"), JUCE_T("@dynamic"), JUCE_T("@public"), + JUCE_T("@private"), JUCE_T("@property"), JUCE_T("@protected"), JUCE_T("@class"), 0 }; const juce_wchar* const* k; @@ -70838,23 +70838,70 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_ChoicePropertyComponent.cpp ***/ BEGIN_JUCE_NAMESPACE +class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource, + public Value::Listener +{ +public: + RemapperValueSource (const Value& sourceValue_, const Array& mappings_) + : sourceValue (sourceValue_), + mappings (mappings_) + { + sourceValue.addListener (this); + } + + ~RemapperValueSource() {} + + const var getValue() const + { + return mappings.indexOf (sourceValue.getValue()) + 1; + } + + void setValue (const var& newValue) + { + const var remappedVal (mappings [(int) newValue - 1]); + + if (remappedVal != sourceValue) + sourceValue = remappedVal; + } + + void valueChanged (Value&) + { + sendChangeMessage (true); + } + + juce_UseDebuggingNewOperator + +protected: + Value sourceValue; + Array mappings; + + RemapperValueSource (const RemapperValueSource&); + const RemapperValueSource& operator= (const RemapperValueSource&); +}; + ChoicePropertyComponent::ChoicePropertyComponent (const String& name) : PropertyComponent (name), - comboBox (0) + comboBox (0), + isCustomClass (true) { } ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, const String& name, const StringArray& choices_, - const Array * choiceIDs) + const Array & correspondingValues) : PropertyComponent (name), choices (choices_), - comboBox (0) + comboBox (0), + isCustomClass (false) { - createComboBox (choiceIDs); + // The array of corresponding values must contain one value for each of the items in + // the choices array! + jassert (correspondingValues.size() == choices.size()); - comboBox->getSelectedIdAsValue().referTo (valueToControl); + createComboBox(); + + comboBox->getSelectedIdAsValue().referTo (Value (new RemapperValueSource (valueToControl, correspondingValues))); } ChoicePropertyComponent::~ChoicePropertyComponent() @@ -70862,20 +70909,14 @@ ChoicePropertyComponent::~ChoicePropertyComponent() deleteAllChildren(); } -void ChoicePropertyComponent::createComboBox (const Array * choiceIDs) +void ChoicePropertyComponent::createComboBox() { - // The array of IDs must contain the same number of values as the choices list! - jassert (choiceIDs == 0 || choiceIDs->size() == choices.size()); - - addAndMakeVisible (comboBox = new ComboBox (String::empty)); - - int itemId = 0; + addAndMakeVisible (comboBox = new ComboBox()); for (int i = 0; i < choices.size(); ++i) { if (choices[i].isNotEmpty()) - comboBox->addItem (choices[i], choiceIDs == 0 ? ++itemId - : ((*choiceIDs)[i])); + comboBox->addItem (choices[i], i + 1); else comboBox->addSeparator(); } @@ -70885,12 +70926,13 @@ void ChoicePropertyComponent::createComboBox (const Array * choiceIDs) void ChoicePropertyComponent::setIndex (const int newIndex) { - comboBox->setSelectedId (comboBox->getItemId (newIndex)); + jassertfalse; // you need to override this method in your subclass! } int ChoicePropertyComponent::getIndex() const { - return comboBox->getSelectedItemIndex(); + jassertfalse; // you need to override this method in your subclass! + return -1; } const StringArray& ChoicePropertyComponent::getChoices() const @@ -70900,21 +70942,27 @@ const StringArray& ChoicePropertyComponent::getChoices() const void ChoicePropertyComponent::refresh() { - if (comboBox == 0) + if (isCustomClass) { - createComboBox (0); - comboBox->addListener (this); - } + if (comboBox == 0) + { + createComboBox(); + comboBox->addListener (this); + } - comboBox->setSelectedId (getIndex() + 1, true); + comboBox->setSelectedId (getIndex() + 1, true); + } } void ChoicePropertyComponent::comboBoxChanged (ComboBox*) { - const int newIndex = comboBox->getSelectedId() - 1; + if (isCustomClass) + { + const int newIndex = comboBox->getSelectedId() - 1; - if (newIndex != getIndex()) - setIndex (newIndex); + if (newIndex != getIndex()) + setIndex (newIndex); + } } END_JUCE_NAMESPACE diff --git a/juce_amalgamated.h b/juce_amalgamated.h index a0fc112ee8..77322805e1 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 2 +#define JUCE_BUILDNUMBER 3 /** Current Juce version number. @@ -3483,10 +3483,11 @@ public: @param values the array to copy from */ - explicit Array (const ElementType* values) + template + explicit Array (const TypeToCreateFrom* values) : numUsed (0) { - while (*values != 0) + while (*values != TypeToCreateFrom()) add (*values++); } @@ -3495,7 +3496,8 @@ public: @param values the array to copy from @param numValues the number of values in the array */ - Array (const ElementType* values, int numValues) + template + Array (const TypeToCreateFrom* values, int numValues) : numUsed (numValues) { data.setAllocatedSize (numValues); @@ -54014,20 +54016,18 @@ protected: public: /** Creates the component. - @param valueToControl the value that the combo box will read and control + @param valueToControl the value that the combo box will read and control @param propertyName the name of the property - @param choices the list of possible values that the user can choose between - @param choiceIDs if this is 0, then the value corresponding to each item in the - 'choices' StringArray is simply its index + 1. But if the - choiceIDs parameter is specified, it lets you provide a set - of IDs for each item in the choices list. If you use this - parameter, it must contain the same number of elements as - the choices list. + @param choices the list of possible values that the drop-down list will contain + @param correspondingValues a list of values corresponding to each item in the 'choices' StringArray. + These are the values that will be read and written to the + valueToControl value. This array must contain the same number of items + as the choices array */ ChoicePropertyComponent (const Value& valueToControl, const String& propertyName, const StringArray& choices, - const Array * choiceIDs = 0); + const Array & correspondingValues); /** Destructor. */ ~ChoicePropertyComponent(); @@ -54068,8 +54068,10 @@ protected: private: ComboBox* comboBox; + bool isCustomClass; - void createComboBox (const Array * choiceIDs); + class RemapperValueSource; + void createComboBox(); ChoicePropertyComponent (const ChoicePropertyComponent&); ChoicePropertyComponent& operator= (const ChoicePropertyComponent&); diff --git a/src/containers/juce_Array.h b/src/containers/juce_Array.h index 7fd16bfb98..799cc9fab2 100644 --- a/src/containers/juce_Array.h +++ b/src/containers/juce_Array.h @@ -91,10 +91,11 @@ public: @param values the array to copy from */ - explicit Array (const ElementType* values) + template + explicit Array (const TypeToCreateFrom* values) : numUsed (0) { - while (*values != 0) + while (*values != TypeToCreateFrom()) add (*values++); } @@ -103,7 +104,8 @@ public: @param values the array to copy from @param numValues the number of values in the array */ - Array (const ElementType* values, int numValues) + template + Array (const TypeToCreateFrom* values, int numValues) : numUsed (numValues) { data.setAllocatedSize (numValues); diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 801aa67d92..ec97b1d412 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 2 +#define JUCE_BUILDNUMBER 3 /** Current Juce version number. diff --git a/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp b/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp index 061d5e04af..e6440b9c85 100644 --- a/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp +++ b/src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp @@ -58,30 +58,30 @@ static bool isIdentifierBody (const juce_wchar c) throw() static bool isReservedKeyword (const juce_wchar* const token, const int tokenLength) throw() { static const juce_wchar* const keywords2Char[] = - { T("if"), T("do"), T("or"), T("id"), 0 }; + { JUCE_T("if"), JUCE_T("do"), JUCE_T("or"), JUCE_T("id"), 0 }; static const juce_wchar* const keywords3Char[] = - { T("for"), T("int"), T("new"), T("try"), T("xor"), T("and"), T("asm"), T("not"), 0 }; + { JUCE_T("for"), JUCE_T("int"), JUCE_T("new"), JUCE_T("try"), JUCE_T("xor"), JUCE_T("and"), JUCE_T("asm"), JUCE_T("not"), 0 }; static const juce_wchar* const keywords4Char[] = - { T("bool"), T("void"), T("this"), T("true"), T("long"), T("else"), T("char"), - T("enum"), T("case"), T("goto"), T("auto"), 0 }; + { JUCE_T("bool"), JUCE_T("void"), JUCE_T("this"), JUCE_T("true"), JUCE_T("long"), JUCE_T("else"), JUCE_T("char"), + JUCE_T("enum"), JUCE_T("case"), JUCE_T("goto"), JUCE_T("auto"), 0 }; static const juce_wchar* const keywords5Char[] = - { T("while"), T("bitor"), T("break"), T("catch"), T("class"), T("compl"), T("const"), T("false"), - T("float"), T("short"), T("throw"), T("union"), T("using"), T("or_eq"), 0 }; + { JUCE_T("while"), JUCE_T("bitor"), JUCE_T("break"), JUCE_T("catch"), JUCE_T("class"), JUCE_T("compl"), JUCE_T("const"), JUCE_T("false"), + JUCE_T("float"), JUCE_T("short"), JUCE_T("throw"), JUCE_T("union"), JUCE_T("using"), JUCE_T("or_eq"), 0 }; static const juce_wchar* const keywords6Char[] = - { T("return"), T("struct"), T("and_eq"), T("bitand"), T("delete"), T("double"), T("extern"), - T("friend"), T("inline"), T("not_eq"), T("public"), T("sizeof"), T("static"), T("signed"), - T("switch"), T("typeid"), T("wchar_t"), T("xor_eq"), 0}; + { JUCE_T("return"), JUCE_T("struct"), JUCE_T("and_eq"), JUCE_T("bitand"), JUCE_T("delete"), JUCE_T("double"), JUCE_T("extern"), + JUCE_T("friend"), JUCE_T("inline"), JUCE_T("not_eq"), JUCE_T("public"), JUCE_T("sizeof"), JUCE_T("static"), JUCE_T("signed"), + JUCE_T("switch"), JUCE_T("typeid"), JUCE_T("wchar_t"), JUCE_T("xor_eq"), 0}; static const juce_wchar* const keywordsOther[] = - { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), - T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), - T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), - T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), - T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; + { JUCE_T("const_cast"), JUCE_T("continue"), JUCE_T("default"), JUCE_T("explicit"), JUCE_T("mutable"), JUCE_T("namespace"), + JUCE_T("operator"), JUCE_T("private"), JUCE_T("protected"), JUCE_T("register"), JUCE_T("reinterpret_cast"), JUCE_T("static_cast"), + JUCE_T("template"), JUCE_T("typedef"), JUCE_T("typename"), JUCE_T("unsigned"), JUCE_T("virtual"), JUCE_T("volatile"), + JUCE_T("@implementation"), JUCE_T("@interface"), JUCE_T("@end"), JUCE_T("@synthesize"), JUCE_T("@dynamic"), JUCE_T("@public"), + JUCE_T("@private"), JUCE_T("@property"), JUCE_T("@protected"), JUCE_T("@class"), 0 }; const juce_wchar* const* k; diff --git a/src/gui/components/properties/juce_ChoicePropertyComponent.cpp b/src/gui/components/properties/juce_ChoicePropertyComponent.cpp index a112b467e7..01742125fc 100644 --- a/src/gui/components/properties/juce_ChoicePropertyComponent.cpp +++ b/src/gui/components/properties/juce_ChoicePropertyComponent.cpp @@ -30,24 +30,74 @@ BEGIN_JUCE_NAMESPACE #include "juce_ChoicePropertyComponent.h" +//============================================================================== +class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource, + public Value::Listener +{ +public: + RemapperValueSource (const Value& sourceValue_, const Array& mappings_) + : sourceValue (sourceValue_), + mappings (mappings_) + { + sourceValue.addListener (this); + } + + ~RemapperValueSource() {} + + const var getValue() const + { + return mappings.indexOf (sourceValue.getValue()) + 1; + } + + void setValue (const var& newValue) + { + const var remappedVal (mappings [(int) newValue - 1]); + + if (remappedVal != sourceValue) + sourceValue = remappedVal; + } + + void valueChanged (Value&) + { + sendChangeMessage (true); + } + + //============================================================================== + juce_UseDebuggingNewOperator + +protected: + Value sourceValue; + Array mappings; + + RemapperValueSource (const RemapperValueSource&); + const RemapperValueSource& operator= (const RemapperValueSource&); +}; + + //============================================================================== ChoicePropertyComponent::ChoicePropertyComponent (const String& name) : PropertyComponent (name), - comboBox (0) + comboBox (0), + isCustomClass (true) { } ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, const String& name, const StringArray& choices_, - const Array * choiceIDs) + const Array & correspondingValues) : PropertyComponent (name), choices (choices_), - comboBox (0) + comboBox (0), + isCustomClass (false) { - createComboBox (choiceIDs); + // The array of corresponding values must contain one value for each of the items in + // the choices array! + jassert (correspondingValues.size() == choices.size()); + + createComboBox(); - comboBox->getSelectedIdAsValue().referTo (valueToControl); + comboBox->getSelectedIdAsValue().referTo (Value (new RemapperValueSource (valueToControl, correspondingValues))); } ChoicePropertyComponent::~ChoicePropertyComponent() @@ -56,20 +106,14 @@ ChoicePropertyComponent::~ChoicePropertyComponent() } //============================================================================== -void ChoicePropertyComponent::createComboBox (const Array * choiceIDs) +void ChoicePropertyComponent::createComboBox() { - // The array of IDs must contain the same number of values as the choices list! - jassert (choiceIDs == 0 || choiceIDs->size() == choices.size()); - - addAndMakeVisible (comboBox = new ComboBox (String::empty)); - - int itemId = 0; + addAndMakeVisible (comboBox = new ComboBox()); for (int i = 0; i < choices.size(); ++i) { if (choices[i].isNotEmpty()) - comboBox->addItem (choices[i], choiceIDs == 0 ? ++itemId - : ((*choiceIDs)[i])); + comboBox->addItem (choices[i], i + 1); else comboBox->addSeparator(); } @@ -79,12 +123,13 @@ void ChoicePropertyComponent::createComboBox (const Array * choiceIDs) void ChoicePropertyComponent::setIndex (const int newIndex) { - comboBox->setSelectedId (comboBox->getItemId (newIndex)); + jassertfalse; // you need to override this method in your subclass! } int ChoicePropertyComponent::getIndex() const { - return comboBox->getSelectedItemIndex(); + jassertfalse; // you need to override this method in your subclass! + return -1; } const StringArray& ChoicePropertyComponent::getChoices() const @@ -95,21 +140,27 @@ const StringArray& ChoicePropertyComponent::getChoices() const //============================================================================== void ChoicePropertyComponent::refresh() { - if (comboBox == 0) + if (isCustomClass) { - createComboBox (0); - comboBox->addListener (this); - } + if (comboBox == 0) + { + createComboBox(); + comboBox->addListener (this); + } - comboBox->setSelectedId (getIndex() + 1, true); + comboBox->setSelectedId (getIndex() + 1, true); + } } void ChoicePropertyComponent::comboBoxChanged (ComboBox*) { - const int newIndex = comboBox->getSelectedId() - 1; + if (isCustomClass) + { + const int newIndex = comboBox->getSelectedId() - 1; - if (newIndex != getIndex()) - setIndex (newIndex); + if (newIndex != getIndex()) + setIndex (newIndex); + } } diff --git a/src/gui/components/properties/juce_ChoicePropertyComponent.h b/src/gui/components/properties/juce_ChoicePropertyComponent.h index 5ed60d18bc..60ff13adfa 100644 --- a/src/gui/components/properties/juce_ChoicePropertyComponent.h +++ b/src/gui/components/properties/juce_ChoicePropertyComponent.h @@ -63,20 +63,18 @@ protected: public: /** Creates the component. - @param valueToControl the value that the combo box will read and control - @param propertyName the name of the property - @param choices the list of possible values that the user can choose between - @param choiceIDs if this is 0, then the value corresponding to each item in the - 'choices' StringArray is simply its index + 1. But if the - choiceIDs parameter is specified, it lets you provide a set - of IDs for each item in the choices list. If you use this - parameter, it must contain the same number of elements as - the choices list. + @param valueToControl the value that the combo box will read and control + @param propertyName the name of the property + @param choices the list of possible values that the drop-down list will contain + @param correspondingValues a list of values corresponding to each item in the 'choices' StringArray. + These are the values that will be read and written to the + valueToControl value. This array must contain the same number of items + as the choices array */ ChoicePropertyComponent (const Value& valueToControl, const String& propertyName, const StringArray& choices, - const Array * choiceIDs = 0); + const Array & correspondingValues); /** Destructor. */ ~ChoicePropertyComponent(); @@ -120,8 +118,10 @@ protected: private: ComboBox* comboBox; + bool isCustomClass; - void createComboBox (const Array * choiceIDs); + class RemapperValueSource; + void createComboBox(); ChoicePropertyComponent (const ChoicePropertyComponent&); ChoicePropertyComponent& operator= (const ChoicePropertyComponent&); diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 18945f4394..84a8cc5c86 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -1758,7 +1758,7 @@ double String::getDoubleValue() const throw() return CharacterFunctions::getDoubleValue (text); } -static const juce_wchar* const hexDigits = T("0123456789abcdef"); +static const juce_wchar* const hexDigits = JUCE_T("0123456789abcdef"); const String String::toHexString (const int number) { diff --git a/src/text/juce_XmlDocument.cpp b/src/text/juce_XmlDocument.cpp index f2f71604b9..1f2920a917 100644 --- a/src/text/juce_XmlDocument.cpp +++ b/src/text/juce_XmlDocument.cpp @@ -183,12 +183,12 @@ int XmlDocument::findNextTokenLength() throw() void XmlDocument::skipHeader() { - const juce_wchar* const found = CharacterFunctions::find (input, T("")); + input = CharacterFunctions::find (input, JUCE_T("?>")); if (input == 0) return; @@ -197,7 +197,7 @@ void XmlDocument::skipHeader() } skipNextWhiteSpace(); - const juce_wchar* docType = CharacterFunctions::find (input, T("")); + const juce_wchar* const closeComment = CharacterFunctions::find (input, JUCE_T("-->")); if (closeComment == 0) { @@ -256,7 +256,7 @@ void XmlDocument::skipNextWhiteSpace() } else if (input[1] == '?') { - const juce_wchar* const closeBracket = CharacterFunctions::find (input, T("?>")); + const juce_wchar* const closeBracket = CharacterFunctions::find (input, JUCE_T("?>")); if (closeBracket == 0) { @@ -331,7 +331,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) if (outOfData) return 0; - input = CharacterFunctions::find (input, T("<")); + input = CharacterFunctions::find (input, JUCE_T("<")); if (input != 0) { @@ -451,7 +451,7 @@ void XmlDocument::readChildElements (XmlElement* parent) if (input[1] == '/') { // our close tag.. - input = CharacterFunctions::find (input, T(">")); + input = CharacterFunctions::find (input, JUCE_T(">")); ++input; break; } @@ -623,27 +623,27 @@ void XmlDocument::readEntity (String& result) // skip over the ampersand ++input; - if (CharacterFunctions::compareIgnoreCase (input, T("amp;"), 4) == 0) + if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("amp;"), 4) == 0) { input += 4; result += '&'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("quot;"), 5) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("quot;"), 5) == 0) { input += 5; result += '"'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("apos;"), 5) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("apos;"), 5) == 0) { input += 5; result += '\''; } - else if (CharacterFunctions::compareIgnoreCase (input, T("lt;"), 3) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("lt;"), 3) == 0) { input += 3; result += '<'; } - else if (CharacterFunctions::compareIgnoreCase (input, T("gt;"), 3) == 0) + else if (CharacterFunctions::compareIgnoreCase (input, JUCE_T("gt;"), 3) == 0) { input += 3; result += '>'; @@ -704,7 +704,7 @@ void XmlDocument::readEntity (String& result) else { const juce_wchar* const entityNameStart = input; - const juce_wchar* const closingSemiColon = CharacterFunctions::find (input, T(";")); + const juce_wchar* const closingSemiColon = CharacterFunctions::find (input, JUCE_T(";")); if (closingSemiColon == 0) {