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