IncDecButton Layout: Am I overthinking this?

I would like to create the IncDec Slider that is shown in this thread Overriding IncDec Slider Draw

To get the ArrowButtons in the right orientation I did the following.

class CustomLookAndFeel : public juce::LookAndFeel_V4
{
    public:
        CustomLookAndFeel() {}


    juce::Button* createSliderButton(juce::Slider& slider, bool 
  isIncrement) override
    {
   

        if (slider.getSliderStyle() == juce::Slider::SliderStyle::IncDecButtons)
        {
            if (isIncrement)
            {
                return new juce::ArrowButton("u", 0.0f, juce::Colours::white.withAlpha(0.8f));
            
            }
            else
            {
                return = new juce::ArrowButton("d", 0.5f, juce::Colours::white.withAlpha(0.8f));
            
            }
        }
        else
        {
            return new juce::TextButton(isIncrement ? "+" : "-", juce::String());
        }

    
    }

However, I realized that even after doing this I need to lay out the buttons so that they are positioned on the left and right of the text box.

The incButton and decButton are private. Is there something simple I’m over looking that would allow me to manipulate the layout of these buttons?

This question is also addressed here: Slider::IncDecButtons Appearance, Possition

I don’t think you are. there’s a L&F function missing to achieve this. FEATURE REQUEST ALERT!!!

I recently resorted to overriding the L&F method that creates those buttons and then added a nasty helper ComponentListener that forces them back into position whenever the slider tries to mess with them. Doing it this way is as ugly as the night but I don’t loose any sleep over it because it’s hidden in a dark little corner of my L&F class :slight_smile:

1 Like

LOL!! Yes, I had a feeling it would get rather “dark”

I kept looking at the slider header file as well as the L&F headers. Trying to override slider layout, text box creation, or button creation still leaves you with missing functionality for the IncDec buttons!!

Well, time to roll up my sleeves and get to hacking! :slight_smile:

Or maybe do it properly: move the code that positions the buttons into the L&F and make a pull request?

That’s close to what I’m thinking. However, I’m going straight to the actual Slider source code.

The code to position the buttons is here: resizeIncDecButtons()
This method is not virtual. However, making it virtual won’t do much since decButton and incButton are private and I would have to do more poking than I think is needed.

I’ve added a value to a slider enum

enum TextEntryBoxPosition
{
    ...
    TextBoxCentre           /**< Horizontally centres the text box between IncDecButtons.  */
};

My intention is to update resizeIncDecButtons, and handle the TextBoxCentre enum value.

I think the most consistent way (with all the other L&F stuff that is) would be to add

virtual void positionSliderIncDecButtons(Slider& slider, Button& incButton, Button& decButton)

to Slider::LookAndFeelMethods and provide a default implementation with the existing positioning code.

I would refrain from extending the enum because this value would be only valid for the IncDec slider style and probably unhandeled or meaningless for the other styles. So you would have to check the places where the other enum values are handled and add an assert.

Doing it the way I described actually has a decent chance of being accepted so you don’t have to have a merge party when JUCE 7 is released.

Yeah, I know … critique from the guy with the sceletons in the closet :smiley:

LOL!!!

No worries. I like a good critique, especially when it’s backed up with sound reasoning.

I like your idea better. It’s safer, and ultimately cleaner.

I did get the enum idea working. It’s not done yet, but the controls are laid out close to how I’d like.

What I’ll do is move that positioning code into a single function and finish it up there.

THANKS!

image

There is a lot of room for improvement, but I thought I would post this, since others have been looking for this.

How I did this:

  1. Added a value to the enum class
    /** The position of the slider’s text-entry box.
    @see setTextBoxStyle
    /
    enum TextEntryBoxPosition
    {
    NoTextBox,
    TextBoxLeft,
    TextBoxRight,
    TextBoxAbove,
    TextBoxBelow,
    TextBoxCentered /
    The new Enum */
    };
  1. I updated resizeIncDecButtons();
    void resizeIncDecButtons()
    {
    auto buttonRect = sliderRect;

     if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight || textBoxPos == TextBoxCentered)
         buttonRect.expand (-2, 0);
     else
         buttonRect.expand (0, -2);
    
     incDecButtonsSideBySide = buttonRect.getWidth() > buttonRect.getHeight();
    
     if (incDecButtonsSideBySide)
     {
         if (textBoxPos == TextBoxCentered)            
         {
             // NEW CODE
             auto w = valueBox->getWidth();
             auto y = buttonRect.getWidth();
             auto btnWidth = (y - w) / 2;
             decButton->setBounds(buttonRect.removeFromLeft( btnWidth));
             valueBox->setBounds(buttonRect.removeFromLeft(valueBox->getWidth()));
         }
         else
         {
             decButton->setBounds(buttonRect.removeFromLeft(buttonRect.getWidth() / 2));
             decButton->setConnectedEdges(Button::ConnectedOnRight);
             incButton->setConnectedEdges(Button::ConnectedOnLeft);
         }
     }
    
  2. To get the Arrow buttons to point appropriately, you’ll need to update the “LookAndFeel”

    class  CustomLookAndFeel : public LookAndFeel_V4
    {
    
    public:
        Button* createSliderButton(Slider&, bool isIncrement) override
        {
            if (isIncrement)
                return new ArrowButton("u", 0.0f, Colours::white.withAlpha(0.8f));
        
        return new ArrowButton("d", 0.5f, Colours::white.withAlpha(0.8f)); 
        }
    };