Dynamically dividing a rectangle with a mouse


#1

What would be the simplest way to draw a rectangle and then dividing it into 2 by double-clicking on it?


|___________________| draw a rectangle (the easy part)


|________|__________| double-click divides it into two


|__||____| another double-click divides it again


|||__________| click and drag on vertical sides can stretch or shrink the rectangles

I’d like to put some centered text into each box later on (sort of like spreadsheet). I only need to resize horizontally (fixed height).

It looked easy at first, but I’m not sure how to keep my thoughts simple.

Any suggestion would be appreciated. Thanks.


#2

depends what you are doing with the inner rectangles.

If these are just visual things, a simple component with an array of size percentages, and a suitable paint implementation are all you need.

For more complex stuff, a container component that manages a horizontal resizer, either JUCE’s or your own, and suitable double click handling. Your parent component can register itself as a listener to the children to catch double-clicks, whilst allowing all other mouse methods to be handled directly by the child components.


#3

Thanks for your help, valley.

I don’t intend to do any fancy stuff with the inner rectangles. Once I get the basic drawing routine down, I’d like to be able to type in text inside each rectangle. In fact, Jucedemo shows this behavior (i.e. resizing inner rectangles + text) I want in Demo --> Table Components example’s table header. Of course, this represents the behavior AFTER I’ve split up the rectangle into many.

Is there a way to make this table header create a new column as I double-click it? That would be really cool if I can. I think you need to predefine the columns right now. Correct? :oops:


#4

I don’t know about the table header component, because as yet I haven’t used it[1].

In theory, it should be possible to sub-class the table header, and trap for for double clicks as normal. However, if the table header manages child components for the individual cells, you’re probably out of luck.

The easy way to test is just to override mouseDoubleClick() for that class, and see whether you actually get events. If you don’t, there are child components that are eating them, and you’ll need to do your own implementation. If you do, you have everything you need in the table header class.

[1] I needed the functionality years ago, so I rolled my own, and see no gain currently in refactoring code to use the JUCE native one.


#5

I just played around with the table header in TableDemo.cpp file (Juce demo).

I’m happy to say that I’ve hacked this demo file to show only the header row. I also managed to create extra columns on the fly…BUT…not with a double-click; I couldn’t find mouse double-click event.

I modified the overloading method called sortOrderChanged because it responds to a mouse click. I wanted to at least see if the columns would get created. It works great as long as I click on the last column. Click on any other column it crashes because of duplicate column ID. Currently, I just increment newSortColumnId by 1 in the sortOrderChanged method. That explains why it’s crashing, but I can’t figure out how to pass a unique ID for the new column.

Maybe I’m just going about this whole thing in a silly way? Is there a clean solution that I’m not seeing?

Could someone kindly help me? :cry:


#6

Okay. I fixed the crashing problem by incrementing a static int value right inside the sortOrderChanged method. This value is used to create a new column on the fly. I think I’m slowly getting what I want.

Now I need to figure out how to make this work with a double-click. In the table demo, when I try to double-click it selects that header column and changes the sort order. Is there a way to make sortOrderChanged not respond to a mouse click but trigger the mouseDoubleClick event in TableHeaderComponent?

Thanks for your help.


#7

You’re missing something pretty fundamental.

TableHeader is a descendant of Component. Component has a public mouseDoubleClick() method. TableHeaderComponent might not implement that method itself, since it doesn’t need it, but it does inherit it. That means you just need to make your own subclass of TableHeader that simply adds a custom implementation of mouseDoubleClick().

I.E.:

class CustomTableHeader : public TableHeaderComponent
{
public:
  CustomTableHeader() : TableHeaderComponent() {}

  virtual ~CustomTableHeader() {}

  // -----------------------------------------------------------------------

  virtual void mouseDoubleClick(const MouseEvent& e)
  {
     // mouse event contains the x pos you need, so just add a column 
     // accordingly.
  }

};

This is basic C++ stuff, so if you’re unsure, you should probably read a good book on inheritance. Also, always remember when looking at the docs for a class to look at its ancestor classes too.

(btw, I just woke up, I’m sick, and my daughter is throwing her breakfast all over the kitchen, so don’t blindly copy the above, there may be typos)


#8

Valley, thanks a lot for giving me a wake up smack on the head. I hope you get well soon.

I knew that I wasn’t thinking clearly last night. I did previously read books and websites to improve my knowledge in OO programming. What drives me crazy is when I sit down and try to create something useful I get confused. Once again I am reminded that reading about something and actually applying that knowledge is very different. :frowning:

This morning I realized that the behavior of adding a new column is not what I had in mind. It’ll be useful later on, but that was not the original problem I wanted to solve. I was just too excited about getting any new column added. :oops:

What I need is ability to split an existing column at where the mouse is double-clicked. I think because of this I can’t use the table header approach. Unless…there is a way to INSERT a new header column…I may be able to shrink the original rectangle to where the mouse was clicked and create another rectangle starting from that position to where the original rectangle used to occupy. (just thinking out loud).

I don’t intend to give up, so please give me bits of your valuable feedback . Thanks!