There's no PasswordPropertyComponent, so I wrote one


#1

Based on TextPropertyComponent. Thanks for Jules.

Hope this class would help someone save a little time :slight_smile:

h:

/*
  ==============================================================================

    PasswordPropertyComponent.h
    Created: 12 Jan 2017 9:35:48am
    Author:  LoopFine

  ==============================================================================
*/

#ifndef PASSWORDPROPERTYCOMPONENT_H_INCLUDED
#define PASSWORDPROPERTYCOMPONENT_H_INCLUDED

//==============================================================================
/**
A PropertyComponent for display and input password. 

    - It'll display the original characters when it's been editing.
    - The max-length of the password must not more than 120.

@see PropertyComponent
*/
class PasswordPropertyComponent : public PropertyComponent
{
public:
    /** Creates a password property component.

    @param valueToControl The Value that is controlled by this object
    @param propertyName   The name of the property which will display on the left
    */
    PasswordPropertyComponent(const Value& valueToControl,
                              const String& propertyName);

    /** Destructor. */
    ~PasswordPropertyComponent();

    //==============================================================================
    /** Called when the user edits the text. */
    virtual void setText(const String& newText);

    /** Returns the text that should be shown in the text editor. */
    virtual String getText() const;

    /** Returns the text that should be shown in the text editor as a Value object. */
    Value& getValue() const;

    //==============================================================================
    /** A set of colour IDs to use to change the colour of various aspects of the component.

        These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
        methods.

    @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
    */
    enum ColourIds
    {
        backgroundColourId = 0x100e401,    /**< The colour to fill the background of the text area. */
        textColourId = 0x100e402,          /**< The colour to use for the editable text. */
        outlineColourId = 0x100e403,       /**< The colour to use to draw an outline around the text area. */
    };

    void colourChanged() override;

    //==============================================================================
    class Listener
    {
    public:
        /** Destructor. */
        virtual ~Listener() { }

        /** Called when text has finished being entered (i.e. not per keypress) has changed. */
        virtual void textPropertyComponentChanged(PasswordPropertyComponent*) = 0;
    };

    /** Registers a listener to receive events when this button's state changes.
        If the listener is already registered, this will not register it again.
    @see removeListener
    */
    void addListener(Listener* newListener);

    /** Removes a previously-registered button listener
    @see addListener
    */
    void removeListener(Listener* listener);

    //==============================================================================
    /** @internal */
    void refresh() override;
    /** @internal */
    virtual void textWasEdited();

private:
    class LabelComp;
    friend class LabelComp;

    ScopedPointer<LabelComp> textEditor;
    ListenerList<Listener> listenerList;

    void callListeners();
    void createEditor();

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PasswordPropertyComponent)
};

#endif  // PASSWORDPROPERTYCOMPONENT_H_INCLUDED

cpp:

/*
  ==============================================================================

    PasswordPropertyComponent.cpp
    Created: 12 Jan 2017 9:35:48am
    Author:  LoopFine

  ==============================================================================
*/

#include "JuceHeader.h"
#include "PasswordPropertyComponent.h"

//==============================================================================
class PasswordPropertyComponent::LabelComp : public Label
{
public:
    LabelComp(PasswordPropertyComponent& tpc)
        : Label(String(), String()),
        owner(tpc)
    {
        setEditable(true, true, false);
        updateColours();
    }

    TextEditor* createEditorComponent() override
    {
        TextEditor* const ed = Label::createEditorComponent();
        //ed->setPasswordCharacter('*');
        ed->setInputRestrictions(120);

        return ed;
    }

    void paint (Graphics& g) override
    {
        g.fillAll(findColour(Label::backgroundColourId));

        if (!isBeingEdited())
        {
            const float alpha = isEnabled() ? 1.0f : 0.5f;
            const Font f(LookAndFeel::getDefaultLookAndFeel().getLabelFont(*this));

            g.setColour(findColour(Label::textColourId).withMultipliedAlpha(alpha));
            g.setFont(f);

            Rectangle<int> textArea(getBorderSize().subtractedFrom(getLocalBounds()));

            const String passwordChars (String::repeatedString("*", getText().length()));
            g.drawFittedText(passwordChars, textArea, getJustificationType(),
                             jmax(1, (int) (textArea.getHeight() / f.getHeight())),
                             getMinimumHorizontalScale());

            g.setColour(findColour(Label::outlineColourId).withMultipliedAlpha(alpha));
        }
        else if (isEnabled())
        {
            g.setColour(findColour(Label::outlineColourId));
        }

        g.drawRect(getLocalBounds());
    }

    void textWasEdited() override
    {
        owner.textWasEdited();
    }

    void updateColours()
    {
        setColour(backgroundColourId, owner.findColour(TextPropertyComponent::backgroundColourId));
        setColour(outlineColourId, owner.findColour(TextPropertyComponent::outlineColourId));
        setColour(textColourId, owner.findColour(TextPropertyComponent::textColourId));
        repaint();
    }

private:
    PasswordPropertyComponent& owner;
};

//===============================================================================
PasswordPropertyComponent::PasswordPropertyComponent(const Value& valueToControl,
                                                     const String& name)
    : PropertyComponent(name)
{
    addAndMakeVisible(textEditor = new LabelComp(*this));
    textEditor->getTextValue().referTo(valueToControl);
}

PasswordPropertyComponent::~PasswordPropertyComponent()
{ }

void PasswordPropertyComponent::setText(const String& newText)
{
    textEditor->setText(newText, sendNotificationSync);
}

String PasswordPropertyComponent::getText() const
{
    return textEditor->getText();
}

Value& PasswordPropertyComponent::getValue() const
{
    return textEditor->getTextValue();
}

void PasswordPropertyComponent::refresh()
{
    textEditor->setText(getText(), dontSendNotification);
}

void PasswordPropertyComponent::textWasEdited()
{
    const String newText(textEditor->getText());

    if (getText() != newText)
        setText(newText);

    callListeners();
}

void PasswordPropertyComponent::addListener(PasswordPropertyComponent::Listener* const listener)
{
    listenerList.add(listener);
}

void PasswordPropertyComponent::removeListener(PasswordPropertyComponent::Listener* const listener)
{
    listenerList.remove(listener);
}

void PasswordPropertyComponent::callListeners()
{
    Component::BailOutChecker checker(this);
    listenerList.callChecked(checker, &PasswordPropertyComponent::Listener::textPropertyComponentChanged, this);
}

void PasswordPropertyComponent::colourChanged()
{
    PropertyComponent::colourChanged();
    textEditor->updateColours();
}