Table component similar to Kontakt table?


#1

Is there a component similar in behavior to the table element in NI Kontakt?

What I need is basically a way of controlling more parameters/UI elements clicking and dragging across several of them.
For example, if I have a series of buttons aligned in the UI, if I want to change them I have to click one by one. Instead I would like to click on the first and then drag across them to activate all of them. Or same for a series of sliders, kinda like the table element in NI Kontakt or Massive stepper.

Thanks.


#2

If you put all your button into a single parent component you can then test the position of the mouse in that parent's mouseDrag() method. If the mouse is down when the mouse is above a particular button you can toggle the state of the button. This is also easy to do for custom table components and for multi-slider type controls. 


#3

Oh great, I didn't think about that. I'll try, thanks a lot.


#4

Ok so I put a couple of buttons inside a parent component and then I used this to check the mouse position in mouseDrag:

DBG(String(this->getMouseXYRelative().getX()));

It works only if I start to drag from the parent component, but if I click on one of the button and drag over the others it doesn't work.

I tried to understand how to use addMouseListener but I'm really lost. I'm using ImageButton, what's the proper way to implement this?

Thanks.

 


#5

You can disable mouse clicks on your child components, setMouseIntercepts()?. Btw, I'm sure there are other ways of doing this, this is but the first thing I thought off :)


#6

You can also add a transparent component on top of the sliders (same dimensions as the sliders area), make it a ChangeBroadcaster with the parent component as listener, and update the sliders according to the mouse position by sending change messages in its mouseDrag method.


#7

There are a million different ways to do this (ImageButton definitely isn't one though, no idea why you'd consider using that!)

Personally, I'd probably just write a single custom component that does it, and avoid sub-components.


#8

Because I basically want two things. Something like the table ui in Kontakt and an array of buttons/sliders that I can control with a single click-drag movement.

I really don't know the best approach to this. I'll try what I can now.


#9

Like other mentioned, make a parent container component which holds your array of sliders, then you can implement its mouseDrag function. This is just some barebones code to get you going in a better direction.

class SliderTable : public Component
{
public:
  SliderTable() : Component(), numSliders(10)
  {
    for (int i=0; i<numSlider; i++){
      sliders.add(new Slider());
    }
  }
  void mouseDrag(const MouseEvent& m){
    
    int slider_index = //get mouse position and calculate which 'column' or slider to modify
    sliders[slider_index]->setValue(/*calculate slider's value based on the MouseEvent's Y position*/);
  }
private:
  Array<ScopedPointer<Slider> > sliders;
}

 

EDIT:

You could also try reimplementing the slider's mouseMove() function, where you check to see if the mouse button is held down, and if so, set that slider's value according to the MouseEvent's Y value.

 


#10

This is OT, but using Array<ScopedPointer> isn't guaranteed to work correctly. You may be lucky, but you should definitely use OwnedArray instead.

You could probably use Array<std::unique_ptr> if you have C++11, but I had to keep these classes backwards-compatible with old compilers, and it's not possible to do implement the full unique_ptr functionality without the new language features.


#11

Ok, I managed to get something working quite well. I added all my ImageButtons to a parent component, then used buttonX->addMouseListener(this,false); and did all the checkings in the parent mouseDrag.

One thing I couldn't figure out was the contains method for a component. I had to manually do something like:
if (mouseX > buttonX && mouseX < buttonWidth) ...

Not elegant but it works. If someone can exaplin how can I used the contains method with the mouse coordinates would be much better.

Thanks!


#12

Pretty sure you can use the Rectangle class's contains() method to accomplish this:

void mouseDrag(const MouseEvent& m){
  Point<int> p = m.getPosition();
  if (childComponent->getBounds().contains(p)){
    //bingo!

  }
}