| @@ -4223,8 +4223,6 @@ | |||
| 84A487F808A22DD800752A2B /* Debug */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; | |||
| ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; | |||
| GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; | |||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||
| MACOSX_DEPLOYMENT_TARGET = 10.4; | |||
| @@ -4235,10 +4233,7 @@ | |||
| 84A487F908A22DD800752A2B /* Release */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; | |||
| ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; | |||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||
| SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; | |||
| STRIP_STYLE = "non-global"; | |||
| }; | |||
| name = Release; | |||
| @@ -683,6 +683,7 @@ | |||
| COPY_PHASE_STRIP = NO; | |||
| DEBUG_INFORMATION_FORMAT = dwarf; | |||
| GCC_VERSION = 4.0; | |||
| GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO; | |||
| GENERATE_PKGINFO_FILE = YES; | |||
| INFOPLIST_FILE = Info.plist; | |||
| INFOPLIST_PREPROCESS = YES; | |||
| @@ -698,6 +699,7 @@ | |||
| ARCHS = "$(ARCHS_STANDARD_32_BIT)"; | |||
| GCC_C_LANGUAGE_STANDARD = c99; | |||
| GCC_VERSION = 4.0; | |||
| GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO; | |||
| GENERATE_PKGINFO_FILE = YES; | |||
| INFOPLIST_PREPROCESS = YES; | |||
| SDKROOT = macosx10.5; | |||
| @@ -72,6 +72,8 @@ | |||
| #define JUCE_USE_CAMERA 0 | |||
| #elif JUCE_MAC | |||
| #define JUCE_USE_CAMERA 1 | |||
| #else // WINDOWS | |||
| #define JUCE_USE_CAMERA 0 | |||
| #endif | |||
| //#define JUCE_CHECK_MEMORY_LEAKS 1 | |||
| @@ -36,22 +36,24 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| ComboBox::ComboBox (const String& name) | |||
| : Component (name), | |||
| items (4), | |||
| currentIndex (-1), | |||
| lastCurrentId (0), | |||
| isButtonDown (false), | |||
| separatorPending (false), | |||
| menuActive (false), | |||
| listeners (2), | |||
| label (0) | |||
| { | |||
| noChoicesMessage = TRANS("(no choices)"); | |||
| setRepaintsOnMouseActivity (true); | |||
| lookAndFeelChanged(); | |||
| currentId.addListener (this); | |||
| } | |||
| ComboBox::~ComboBox() | |||
| { | |||
| currentId.removeListener (this); | |||
| if (menuActive) | |||
| PopupMenu::dismissAllActiveMenus(); | |||
| @@ -185,10 +187,19 @@ void ComboBox::clear (const bool dontSendChangeMessage) | |||
| } | |||
| //============================================================================== | |||
| ComboBox::ItemInfo* ComboBox::getItemForId (const int itemId) const throw() | |||
| bool ComboBox::ItemInfo::isSeparator() const throw() | |||
| { | |||
| jassert (itemId != 0); | |||
| return name.isEmpty(); | |||
| } | |||
| bool ComboBox::ItemInfo::isRealItem() const throw() | |||
| { | |||
| return ! (isHeading || name.isEmpty()); | |||
| } | |||
| //============================================================================== | |||
| ComboBox::ItemInfo* ComboBox::getItemForId (const int itemId) const throw() | |||
| { | |||
| if (itemId != 0) | |||
| { | |||
| for (int i = items.size(); --i >= 0;) | |||
| @@ -208,10 +219,8 @@ ComboBox::ItemInfo* ComboBox::getItemForIndex (const int index) const throw() | |||
| ItemInfo* const item = items.getUnchecked(i); | |||
| if (item->isRealItem()) | |||
| { | |||
| if (n++ == index) | |||
| return item; | |||
| } | |||
| } | |||
| return 0; | |||
| @@ -222,19 +231,15 @@ int ComboBox::getNumItems() const throw() | |||
| int n = 0; | |||
| for (int i = items.size(); --i >= 0;) | |||
| { | |||
| ItemInfo* const item = items.getUnchecked(i); | |||
| if (item->isRealItem()) | |||
| if (items.getUnchecked(i)->isRealItem()) | |||
| ++n; | |||
| } | |||
| return n; | |||
| } | |||
| const String ComboBox::getItemText (const int index) const throw() | |||
| { | |||
| ItemInfo* const item = getItemForIndex (index); | |||
| const ItemInfo* const item = getItemForIndex (index); | |||
| if (item != 0) | |||
| return item->name; | |||
| @@ -244,90 +249,80 @@ const String ComboBox::getItemText (const int index) const throw() | |||
| int ComboBox::getItemId (const int index) const throw() | |||
| { | |||
| ItemInfo* const item = getItemForIndex (index); | |||
| const ItemInfo* const item = getItemForIndex (index); | |||
| return (item != 0) ? item->itemId : 0; | |||
| } | |||
| //============================================================================== | |||
| bool ComboBox::ItemInfo::isSeparator() const throw() | |||
| int ComboBox::indexOfItemId (const int itemId) const throw() | |||
| { | |||
| return name.isEmpty(); | |||
| } | |||
| int n = 0; | |||
| bool ComboBox::ItemInfo::isRealItem() const throw() | |||
| { | |||
| return ! (isHeading || name.isEmpty()); | |||
| for (int i = 0; i < items.size(); ++i) | |||
| { | |||
| const ItemInfo* const item = items.getUnchecked(i); | |||
| if (item->isRealItem()) | |||
| { | |||
| if (item->itemId == itemId) | |||
| return n; | |||
| ++n; | |||
| } | |||
| } | |||
| return -1; | |||
| } | |||
| //============================================================================== | |||
| int ComboBox::getSelectedItemIndex() const throw() | |||
| { | |||
| return (currentIndex >= 0 && getText() == getItemText (currentIndex)) | |||
| ? currentIndex | |||
| : -1; | |||
| } | |||
| void ComboBox::setSelectedItemIndex (const int index, | |||
| const bool dontSendChangeMessage) throw() | |||
| { | |||
| if (currentIndex != index || label->getText() != getItemText (currentIndex)) | |||
| { | |||
| if (((unsigned int) index) < (unsigned int) getNumItems()) | |||
| currentIndex = index; | |||
| else | |||
| currentIndex = -1; | |||
| int index = indexOfItemId (currentId.getValue()); | |||
| label->setText (getItemText (currentIndex), false); | |||
| if (getText() != getItemText (index)) | |||
| index = -1; | |||
| if (! dontSendChangeMessage) | |||
| triggerAsyncUpdate(); | |||
| } | |||
| return index; | |||
| } | |||
| void ComboBox::setSelectedId (const int newItemId, | |||
| const bool dontSendChangeMessage) throw() | |||
| void ComboBox::setSelectedItemIndex (const int index, | |||
| const bool dontSendChangeMessage) throw() | |||
| { | |||
| for (int i = getNumItems(); --i >= 0;) | |||
| { | |||
| if (getItemId(i) == newItemId) | |||
| { | |||
| setSelectedItemIndex (i, dontSendChangeMessage); | |||
| break; | |||
| } | |||
| } | |||
| setSelectedId (getItemId (index), dontSendChangeMessage); | |||
| } | |||
| int ComboBox::getSelectedId() const throw() | |||
| { | |||
| const ItemInfo* const item = getItemForIndex (currentIndex); | |||
| const ItemInfo* const item = getItemForId (currentId.getValue()); | |||
| return (item != 0 && getText() == item->name) | |||
| ? item->itemId | |||
| : 0; | |||
| } | |||
| //============================================================================== | |||
| void ComboBox::addListener (ComboBoxListener* const listener) throw() | |||
| void ComboBox::setSelectedId (const int newItemId, | |||
| const bool dontSendChangeMessage) throw() | |||
| { | |||
| jassert (listener != 0); | |||
| if (listener != 0) | |||
| listeners.add (listener); | |||
| } | |||
| const ItemInfo* const item = getItemForId (newItemId); | |||
| const String newItemText (item != 0 ? item->name : String::empty); | |||
| void ComboBox::removeListener (ComboBoxListener* const listener) throw() | |||
| { | |||
| listeners.removeValue (listener); | |||
| if (lastCurrentId != newItemId || label->getText() != newItemText) | |||
| { | |||
| if (! dontSendChangeMessage) | |||
| triggerAsyncUpdate(); | |||
| label->setText (newItemText, false); | |||
| lastCurrentId = newItemId; | |||
| currentId = newItemId; | |||
| repaint(); // for the benefit of the 'none selected' text | |||
| } | |||
| } | |||
| void ComboBox::handleAsyncUpdate() | |||
| void ComboBox::valueChanged (Value&) | |||
| { | |||
| for (int i = listeners.size(); --i >= 0;) | |||
| { | |||
| ((ComboBoxListener*) listeners.getUnchecked (i))->comboBoxChanged (this); | |||
| i = jmin (i, listeners.size()); | |||
| } | |||
| if (lastCurrentId != (int) currentId.getValue()) | |||
| setSelectedId (currentId.getValue(), false); | |||
| } | |||
| //============================================================================== | |||
| @@ -341,7 +336,7 @@ void ComboBox::setText (const String& newText, | |||
| { | |||
| for (int i = items.size(); --i >= 0;) | |||
| { | |||
| ItemInfo* const item = items.getUnchecked(i); | |||
| const ItemInfo* const item = items.getUnchecked(i); | |||
| if (item->isRealItem() | |||
| && item->name == newText) | |||
| @@ -351,7 +346,8 @@ void ComboBox::setText (const String& newText, | |||
| } | |||
| } | |||
| currentIndex = -1; | |||
| lastCurrentId = 0; | |||
| currentId = 0; | |||
| if (label->getText() != newText) | |||
| { | |||
| @@ -477,13 +473,13 @@ bool ComboBox::keyPressed (const KeyPress& key) | |||
| if (key.isKeyCode (KeyPress::upKey) | |||
| || key.isKeyCode (KeyPress::leftKey)) | |||
| { | |||
| setSelectedItemIndex (jmax (0, currentIndex - 1)); | |||
| setSelectedItemIndex (jmax (0, getSelectedItemIndex() - 1)); | |||
| used = true; | |||
| } | |||
| else if (key.isKeyCode (KeyPress::downKey) | |||
| || key.isKeyCode (KeyPress::rightKey)) | |||
| { | |||
| setSelectedItemIndex (jmin (currentIndex + 1, getNumItems() - 1)); | |||
| setSelectedItemIndex (jmin (getSelectedItemIndex() + 1, getNumItems() - 1)); | |||
| used = true; | |||
| } | |||
| else if (key.isKeyCode (KeyPress::returnKey)) | |||
| @@ -528,7 +524,7 @@ void ComboBox::showPopup() | |||
| { | |||
| if (! menuActive) | |||
| { | |||
| const int currentId = getSelectedId(); | |||
| const int selectedId = getSelectedId(); | |||
| ComponentDeletionWatcher deletionWatcher (this); | |||
| PopupMenu menu; | |||
| @@ -545,7 +541,7 @@ void ComboBox::showPopup() | |||
| menu.addSectionHeader (item->name); | |||
| else | |||
| menu.addItem (item->itemId, item->name, | |||
| item->isEnabled, item->itemId == currentId); | |||
| item->isEnabled, item->itemId == selectedId); | |||
| } | |||
| if (items.size() == 0) | |||
| @@ -554,7 +550,7 @@ void ComboBox::showPopup() | |||
| const int itemHeight = jlimit (12, 24, getHeight()); | |||
| menuActive = true; | |||
| const int resultId = menu.showAt (this, currentId, | |||
| const int resultId = menu.showAt (this, selectedId, | |||
| getWidth(), 1, itemHeight); | |||
| if (deletionWatcher.hasBeenDeleted()) | |||
| @@ -606,5 +602,27 @@ void ComboBox::mouseUp (const MouseEvent& e2) | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void ComboBox::addListener (ComboBoxListener* const listener) throw() | |||
| { | |||
| jassert (listener != 0); | |||
| if (listener != 0) | |||
| listeners.add (listener); | |||
| } | |||
| void ComboBox::removeListener (ComboBoxListener* const listener) throw() | |||
| { | |||
| listeners.removeValue (listener); | |||
| } | |||
| void ComboBox::handleAsyncUpdate() | |||
| { | |||
| for (int i = listeners.size(); --i >= 0;) | |||
| { | |||
| ((ComboBoxListener*) listeners.getUnchecked (i))->comboBoxChanged (this); | |||
| i = jmin (i, listeners.size()); | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -28,6 +28,7 @@ | |||
| #include "juce_Label.h" | |||
| #include "../../../text/juce_StringArray.h" | |||
| #include "../../../containers/juce_Value.h" | |||
| class ComboBox; | |||
| @@ -70,7 +71,8 @@ public: | |||
| class JUCE_API ComboBox : public Component, | |||
| public SettableTooltipClient, | |||
| private LabelListener, | |||
| private AsyncUpdater | |||
| private AsyncUpdater, | |||
| private Value::Listener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -187,6 +189,11 @@ public: | |||
| */ | |||
| int getItemId (const int index) const throw(); | |||
| /** Returns the index in the list of a particular item ID. | |||
| If no such ID is found, this will return -1. | |||
| */ | |||
| int indexOfItemId (const int itemId) const throw(); | |||
| //============================================================================== | |||
| /** Returns the ID of the item that's currently shown in the box. | |||
| @@ -198,6 +205,13 @@ public: | |||
| */ | |||
| int getSelectedId() const throw(); | |||
| /** Returns a Value object that can be used to get or set the selected item's ID. | |||
| You can call Value::referTo() on this object to make the combo box control | |||
| another Value object. | |||
| */ | |||
| Value& getSelectedIdAsValue() throw() { return currentId; } | |||
| /** Sets one of the items to be the current selection. | |||
| This will set the ComboBox's text to that of the item that matches | |||
| @@ -357,6 +371,8 @@ public: | |||
| bool keyStateChanged (const bool isKeyDown); | |||
| /** @internal */ | |||
| bool keyPressed (const KeyPress&); | |||
| /** @internal */ | |||
| void valueChanged (Value&); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| @@ -373,10 +389,9 @@ private: | |||
| }; | |||
| OwnedArray <ItemInfo> items; | |||
| int currentIndex; | |||
| bool isButtonDown; | |||
| bool separatorPending; | |||
| bool menuActive; | |||
| Value currentId; | |||
| int lastCurrentId; | |||
| bool isButtonDown, separatorPending, menuActive, textIsCustom; | |||
| SortedSet <void*> listeners; | |||
| Label* label; | |||
| String textWhenNothingSelected, noChoicesMessage; | |||
| @@ -35,7 +35,8 @@ BEGIN_JUCE_NAMESPACE | |||
| Label::Label (const String& componentName, | |||
| const String& labelText) | |||
| : Component (componentName), | |||
| text (labelText), | |||
| textValue (labelText), | |||
| lastTextValue (labelText), | |||
| font (15.0f), | |||
| justification (Justification::centredLeft), | |||
| ownerComponent (0), | |||
| @@ -49,10 +50,14 @@ Label::Label (const String& componentName, | |||
| setColour (TextEditor::textColourId, Colours::black); | |||
| setColour (TextEditor::backgroundColourId, Colours::transparentBlack); | |||
| setColour (TextEditor::outlineColourId, Colours::transparentBlack); | |||
| textValue.addListener (this); | |||
| } | |||
| Label::~Label() | |||
| { | |||
| textValue.removeListener (this); | |||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | |||
| ownerComponent->removeComponentListener (this); | |||
| @@ -65,9 +70,10 @@ void Label::setText (const String& newText, | |||
| { | |||
| hideEditor (true); | |||
| if (text != newText) | |||
| if (lastTextValue != newText) | |||
| { | |||
| text = newText; | |||
| lastTextValue = newText; | |||
| textValue = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| @@ -84,9 +90,16 @@ const String Label::getText (const bool returnActiveEditorContents) const throw( | |||
| { | |||
| return (returnActiveEditorContents && isBeingEdited()) | |||
| ? editor->getText() | |||
| : text; | |||
| : textValue.toString(); | |||
| } | |||
| void Label::valueChanged (Value&) | |||
| { | |||
| if (lastTextValue != textValue.toString()) | |||
| setText (textValue.toString(), true); | |||
| } | |||
| //============================================================================== | |||
| void Label::setFont (const Font& newFont) throw() | |||
| { | |||
| font = newFont; | |||
| @@ -152,7 +165,7 @@ void Label::componentMovedOrResized (Component& component, | |||
| { | |||
| if (leftOfOwnerComp) | |||
| { | |||
| setSize (jmin (getFont().getStringWidth (text) + 8, component.getX()), | |||
| setSize (jmin (getFont().getStringWidth (textValue.toString()) + 8, component.getX()), | |||
| component.getHeight()); | |||
| setTopRightPosition (component.getX(), component.getY()); | |||
| @@ -160,7 +173,7 @@ void Label::componentMovedOrResized (Component& component, | |||
| else | |||
| { | |||
| setSize (component.getWidth(), | |||
| 8 + roundFloatToInt (getFont().getHeight())); | |||
| 8 + roundToInt (getFont().getHeight())); | |||
| setTopLeftPosition (component.getX(), component.getY() - getHeight()); | |||
| } | |||
| @@ -194,7 +207,7 @@ void Label::showEditor() | |||
| editor->setText (getText(), false); | |||
| editor->addListener (this); | |||
| editor->grabKeyboardFocus(); | |||
| editor->setHighlightedRegion (0, text.length()); | |||
| editor->setHighlightedRegion (0, textValue.toString().length()); | |||
| editor->addListener (this); | |||
| resized(); | |||
| @@ -220,9 +233,10 @@ bool Label::updateFromTextEditorContents() | |||
| jassert (editor != 0); | |||
| const String newText (editor->getText()); | |||
| if (text != newText) | |||
| if (textValue.toString() != newText) | |||
| { | |||
| text = newText; | |||
| lastTextValue = newText; | |||
| textValue = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| @@ -441,7 +455,7 @@ void Label::textEditorEscapeKeyPressed (TextEditor& ed) | |||
| jassert (&ed == editor); | |||
| (void) ed; | |||
| editor->setText (text, false); | |||
| editor->setText (textValue.toString(), false); | |||
| hideEditor (true); | |||
| } | |||
| } | |||
| @@ -62,7 +62,8 @@ public: | |||
| class JUCE_API Label : public Component, | |||
| public SettableTooltipClient, | |||
| protected TextEditorListener, | |||
| private ComponentListener | |||
| private ComponentListener, | |||
| private Value::Listener | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -98,6 +99,12 @@ public: | |||
| */ | |||
| const String getText (const bool returnActiveEditorContents = false) const throw(); | |||
| /** Returns the text content as a Value object. | |||
| You can call Value::referTo() on this object to make the label read and control | |||
| a Value object that you supply. | |||
| */ | |||
| Value& getTextValue() { return textValue; } | |||
| //============================================================================== | |||
| /** Changes the font to use to draw the text. | |||
| @@ -256,6 +263,30 @@ public: | |||
| juce_UseDebuggingNewOperator | |||
| protected: | |||
| /** Creates the TextEditor component that will be used when the user has clicked on the label. | |||
| Subclasses can override this if they need to customise this component in some way. | |||
| */ | |||
| virtual TextEditor* createEditorComponent(); | |||
| /** Called after the user changes the text. | |||
| */ | |||
| virtual void textWasEdited(); | |||
| /** Called when the text has been altered. | |||
| */ | |||
| virtual void textWasChanged(); | |||
| /** Called when the text editor has just appeared, due to a user click or other | |||
| focus change. | |||
| */ | |||
| virtual void editorShown (TextEditor* editorComponent); | |||
| /** Called when the text editor is going to be deleted, after editing has finished. | |||
| */ | |||
| virtual void editorAboutToBeHidden (TextEditor* editorComponent); | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void paint (Graphics& g); | |||
| /** @internal */ | |||
| @@ -288,32 +319,12 @@ protected: | |||
| void textEditorFocusLost (TextEditor& editor); | |||
| /** @internal */ | |||
| void colourChanged(); | |||
| /** Creates the TextEditor component that will be used when the user has clicked on the label. | |||
| Subclasses can override this if they need to customise this component in some way. | |||
| */ | |||
| virtual TextEditor* createEditorComponent(); | |||
| /** Called after the user changes the text. | |||
| */ | |||
| virtual void textWasEdited(); | |||
| /** Called when the text has been altered. | |||
| */ | |||
| virtual void textWasChanged(); | |||
| /** Called when the text editor has just appeared, due to a user click or other | |||
| focus change. | |||
| */ | |||
| virtual void editorShown (TextEditor* editorComponent); | |||
| /** Called when the text editor is going to be deleted, after editing has finished. | |||
| */ | |||
| virtual void editorAboutToBeHidden (TextEditor* editorComponent); | |||
| /** @internal */ | |||
| void valueChanged (Value&); | |||
| private: | |||
| String text; | |||
| Value textValue; | |||
| String lastTextValue; | |||
| Font font; | |||
| Justification justification; | |||
| ScopedPointer <TextEditor> editor; | |||
| @@ -39,16 +39,42 @@ BooleanPropertyComponent::BooleanPropertyComponent (const String& name, | |||
| onText (buttonTextWhenTrue), | |||
| offText (buttonTextWhenFalse) | |||
| { | |||
| addAndMakeVisible (button = new ToggleButton (String::empty)); | |||
| button->setClickingTogglesState (false); | |||
| createButton(); | |||
| button->addButtonListener (this); | |||
| } | |||
| BooleanPropertyComponent::BooleanPropertyComponent (const Value& valueToControl, | |||
| const String& name, | |||
| const String& buttonText) | |||
| : PropertyComponent (name) | |||
| { | |||
| createButton(); | |||
| button->setButtonText (buttonText); | |||
| button->getToggleStateValue().referTo (valueToControl); | |||
| button->setClickingTogglesState (true); | |||
| } | |||
| BooleanPropertyComponent::~BooleanPropertyComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void BooleanPropertyComponent::createButton() | |||
| { | |||
| addAndMakeVisible (button = new ToggleButton (String::empty)); | |||
| button->setClickingTogglesState (false); | |||
| } | |||
| void BooleanPropertyComponent::setState (const bool newState) | |||
| { | |||
| button->setToggleState (newState, true); | |||
| } | |||
| bool BooleanPropertyComponent::getState() const | |||
| { | |||
| return button->getToggleState(); | |||
| } | |||
| void BooleanPropertyComponent::paint (Graphics& g) | |||
| { | |||
| PropertyComponent::paint (g); | |||
| @@ -42,10 +42,13 @@ | |||
| class JUCE_API BooleanPropertyComponent : public PropertyComponent, | |||
| private ButtonListener | |||
| { | |||
| public: | |||
| protected: | |||
| //============================================================================== | |||
| /** Creates a button component. | |||
| If you use this constructor, you must override the getState() and setState() | |||
| methods. | |||
| @param propertyName the property name to be passed to the PropertyComponent | |||
| @param buttonTextWhenTrue the text shown in the button when the value is true | |||
| @param buttonTextWhenFalse the text shown in the button when the value is false | |||
| @@ -54,15 +57,26 @@ public: | |||
| const String& buttonTextWhenTrue, | |||
| const String& buttonTextWhenFalse); | |||
| public: | |||
| /** Creates a button component. | |||
| @param valueToControl a Value object that this property should refer to. | |||
| @param propertyName the property name to be passed to the PropertyComponent | |||
| @param buttonText the text shown in the ToggleButton component | |||
| */ | |||
| BooleanPropertyComponent (const Value& valueToControl, | |||
| const String& propertyName, | |||
| const String& buttonText); | |||
| /** Destructor. */ | |||
| ~BooleanPropertyComponent(); | |||
| //============================================================================== | |||
| /** Called to change the state of the boolean value. */ | |||
| virtual void setState (const bool newState) = 0; | |||
| virtual void setState (const bool newState); | |||
| /** Must return the current value of the property. */ | |||
| virtual bool getState() const = 0; | |||
| virtual bool getState() const; | |||
| //============================================================================== | |||
| /** @internal */ | |||
| @@ -77,6 +91,8 @@ public: | |||
| private: | |||
| ToggleButton* button; | |||
| String onText, offText; | |||
| void createButton(); | |||
| }; | |||
| @@ -37,12 +37,49 @@ ChoicePropertyComponent::ChoicePropertyComponent (const String& name) | |||
| { | |||
| } | |||
| ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, | |||
| const String& name, | |||
| const StringArray& choices_) | |||
| : PropertyComponent (name), | |||
| choices (choices_), | |||
| comboBox (0) | |||
| { | |||
| createComboBox(); | |||
| comboBox->getSelectedIdAsValue().referTo (valueToControl); | |||
| } | |||
| ChoicePropertyComponent::~ChoicePropertyComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| //============================================================================== | |||
| void ChoicePropertyComponent::createComboBox() | |||
| { | |||
| addAndMakeVisible (comboBox = new ComboBox (String::empty)); | |||
| for (int i = 0; i < choices.size(); ++i) | |||
| { | |||
| if (choices[i].isNotEmpty()) | |||
| comboBox->addItem (choices[i], i + 1); | |||
| else | |||
| comboBox->addSeparator(); | |||
| } | |||
| comboBox->setEditableText (false); | |||
| } | |||
| void ChoicePropertyComponent::setIndex (const int newIndex) | |||
| { | |||
| comboBox->setSelectedId (comboBox->getItemId (newIndex)); | |||
| } | |||
| int ChoicePropertyComponent::getIndex() const | |||
| { | |||
| return comboBox->getSelectedItemIndex(); | |||
| } | |||
| const StringArray& ChoicePropertyComponent::getChoices() const | |||
| { | |||
| return choices; | |||
| @@ -53,17 +90,7 @@ void ChoicePropertyComponent::refresh() | |||
| { | |||
| if (comboBox == 0) | |||
| { | |||
| addAndMakeVisible (comboBox = new ComboBox (String::empty)); | |||
| for (int i = 0; i < choices.size(); ++i) | |||
| { | |||
| if (choices[i].isNotEmpty()) | |||
| comboBox->addItem (choices[i], i + 1); | |||
| else | |||
| comboBox->addSeparator(); | |||
| } | |||
| comboBox->setEditableText (false); | |||
| createComboBox(); | |||
| comboBox->addListener (this); | |||
| } | |||
| @@ -52,7 +52,7 @@ | |||
| class JUCE_API ChoicePropertyComponent : public PropertyComponent, | |||
| private ComboBoxListener | |||
| { | |||
| public: | |||
| protected: | |||
| /** Creates the component. | |||
| Your subclass's constructor must add a list of options to the choices | |||
| @@ -60,6 +60,16 @@ public: | |||
| */ | |||
| ChoicePropertyComponent (const String& propertyName); | |||
| public: | |||
| /** Creates the component. | |||
| Your subclass's constructor must add a list of options to the choices | |||
| member variable. | |||
| */ | |||
| ChoicePropertyComponent (const Value& valueToControl, | |||
| const String& propertyName, | |||
| const StringArray& choices); | |||
| /** Destructor. */ | |||
| ~ChoicePropertyComponent(); | |||
| @@ -70,14 +80,14 @@ public: | |||
| represents. The index is the index of the chosen item in the choices | |||
| StringArray. | |||
| */ | |||
| virtual void setIndex (const int newIndex) = 0; | |||
| virtual void setIndex (const int newIndex); | |||
| /** Returns the index of the item that should currently be shown. | |||
| This is the index of the item in the choices StringArray that will be | |||
| shown. | |||
| */ | |||
| virtual int getIndex() const = 0; | |||
| virtual int getIndex() const; | |||
| /** Returns the list of options. */ | |||
| const StringArray& getChoices() const; | |||
| @@ -102,6 +112,8 @@ protected: | |||
| private: | |||
| ComboBox* comboBox; | |||
| void createComboBox(); | |||
| }; | |||
| @@ -47,11 +47,37 @@ SliderPropertyComponent::SliderPropertyComponent (const String& name, | |||
| slider->addListener (this); | |||
| } | |||
| SliderPropertyComponent::SliderPropertyComponent (Value& valueToControl, | |||
| const String& name, | |||
| const double rangeMin, | |||
| const double rangeMax, | |||
| const double interval, | |||
| const double skewFactor) | |||
| : PropertyComponent (name) | |||
| { | |||
| addAndMakeVisible (slider = new Slider (name)); | |||
| slider->setRange (rangeMin, rangeMax, interval); | |||
| slider->setSkewFactor (skewFactor); | |||
| slider->setSliderStyle (Slider::LinearBar); | |||
| slider->getValueObject().referTo (valueToControl); | |||
| } | |||
| SliderPropertyComponent::~SliderPropertyComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void SliderPropertyComponent::setValue (const double newValue) | |||
| { | |||
| } | |||
| const double SliderPropertyComponent::getValue() const | |||
| { | |||
| return slider->getValue(); | |||
| } | |||
| void SliderPropertyComponent::refresh() | |||
| { | |||
| slider->setValue (getValue(), false); | |||
| @@ -39,7 +39,7 @@ | |||
| class JUCE_API SliderPropertyComponent : public PropertyComponent, | |||
| private SliderListener | |||
| { | |||
| public: | |||
| protected: | |||
| //============================================================================== | |||
| /** Creates the property component. | |||
| @@ -54,6 +54,22 @@ public: | |||
| const double interval, | |||
| const double skewFactor = 1.0); | |||
| public: | |||
| //============================================================================== | |||
| /** Creates the property component. | |||
| The ranges, interval and skew factor are passed to the Slider component. | |||
| If you need to customise the slider in other ways, your constructor can | |||
| access the slider member variable and change it directly. | |||
| */ | |||
| SliderPropertyComponent (Value& valueToControl, | |||
| const String& propertyName, | |||
| const double rangeMin, | |||
| const double rangeMax, | |||
| const double interval, | |||
| const double skewFactor = 1.0); | |||
| /** Destructor. */ | |||
| ~SliderPropertyComponent(); | |||
| @@ -64,10 +80,10 @@ public: | |||
| Your subclass must use this method to update whatever item this property | |||
| represents. | |||
| */ | |||
| virtual void setValue (const double newValue) = 0; | |||
| virtual void setValue (const double newValue); | |||
| /** Returns the value that the slider should show. */ | |||
| virtual const double getValue() const = 0; | |||
| virtual const double getValue() const; | |||
| //============================================================================== | |||
| @@ -79,9 +79,40 @@ public: | |||
| //============================================================================== | |||
| TextPropertyComponent::TextPropertyComponent (const String& name, | |||
| const int maxNumChars, | |||
| const bool isMultiLine) | |||
| const int maxNumChars, | |||
| const bool isMultiLine) | |||
| : PropertyComponent (name) | |||
| { | |||
| createEditor (maxNumChars, isMultiLine); | |||
| } | |||
| TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, | |||
| const String& name, | |||
| const int maxNumChars, | |||
| const bool isMultiLine) | |||
| : PropertyComponent (name) | |||
| { | |||
| createEditor (maxNumChars, isMultiLine); | |||
| textEditor->getTextValue().referTo (valueToControl); | |||
| } | |||
| TextPropertyComponent::~TextPropertyComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void TextPropertyComponent::setText (const String& newText) | |||
| { | |||
| textEditor->setText (newText, true); | |||
| } | |||
| const String TextPropertyComponent::getText() const | |||
| { | |||
| return textEditor->getText(); | |||
| } | |||
| void TextPropertyComponent::createEditor (const int maxNumChars, const bool isMultiLine) | |||
| { | |||
| addAndMakeVisible (textEditor = new TextPropLabel (*this, maxNumChars, isMultiLine)); | |||
| @@ -92,11 +123,6 @@ TextPropertyComponent::TextPropertyComponent (const String& name, | |||
| } | |||
| } | |||
| TextPropertyComponent::~TextPropertyComponent() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void TextPropertyComponent::refresh() | |||
| { | |||
| textEditor->setText (getText(), false); | |||
| @@ -38,7 +38,7 @@ | |||
| */ | |||
| class JUCE_API TextPropertyComponent : public PropertyComponent | |||
| { | |||
| public: | |||
| protected: | |||
| //============================================================================== | |||
| /** Creates a text property component. | |||
| @@ -51,6 +51,19 @@ public: | |||
| const int maxNumChars, | |||
| const bool isMultiLine); | |||
| public: | |||
| /** Creates a text property component. | |||
| The maxNumChars is used to set the length of string allowable, and isMultiLine | |||
| sets whether the text editor allows carriage returns. | |||
| @see TextEditor | |||
| */ | |||
| TextPropertyComponent (const Value& valueToControl, | |||
| const String& propertyName, | |||
| const int maxNumChars, | |||
| const bool isMultiLine); | |||
| /** Destructor. */ | |||
| ~TextPropertyComponent(); | |||
| @@ -60,11 +73,11 @@ public: | |||
| Your subclass must use this callback to change the value of whatever item | |||
| this property component represents. | |||
| */ | |||
| virtual void setText (const String& newText) = 0; | |||
| virtual void setText (const String& newText); | |||
| /** Returns the text that should be shown in the text editor. | |||
| */ | |||
| virtual const String getText() const = 0; | |||
| virtual const String getText() const; | |||
| //============================================================================== | |||
| @@ -77,6 +90,8 @@ public: | |||
| private: | |||
| Label* textEditor; | |||
| void createEditor (const int maxNumChars, const bool isMultiLine); | |||
| }; | |||