LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Dual splitters advice

Solved!
Go to solution

Hi,

 

I'm trying to make an application that has two graphs that I would like to resize proportionally with the window.  I've done this with a single graph with splitter controls (which would normally be hidden), but the two graphs seems to be a bit of a challenge.  I've made a simple application with canvases to play around with.  It looks like this:

 

1.png

I've got the top (blue) canvas attached to the top anchor of the middle (yellow) splitter, and the bottom (red) canvas attached to the bottom anchor of the middle (yellow) splitter and attached to the top anchor of the bottom (magenta) splitter.  Both controls are also attached to the left anchor of the right (green) splitter.  In the panel callback I programmically operate these splitters using OperateSplitter(..) to reposition them to the edge (for the bottom and right splitters) and the middle for middle splitter.  When the user does a smallish resize the panel, it operates as I would expect:

2.png

However, when the user does a large resize of the panel, things don't behave as expected in regards to the horizontal splitters:

3.png

Doing a slight resize of the panel will "fix" it.

 

The issue seems to be that OperateSplitter(..) will not operate the splitter the full requested distance if it causes a control to shrink to small than the minimum size.  So what's happening is that the when the middle (yellow) splitter is operated first, it will only move so far as to not shrink the bottom (red) canvas too far, with the end result that this splitter is above the middle of the panel.  Then the bottom (magenta) splitter is operated and the bottom canvas ends up taking up the remaining space.  Using the VAL_NO_RANGE_LIMIT parameter doesn't seem to change this behaviour.

 

Now, I could change the order of the operation of the splitters, so that I operate the bottom splitter first, then the middle splitter.  This fixes the issue when the panel is resized from a small size to a large size, but introduces a similar issue when the panel is shrunk from a large size to a small size.  So it would suggest that programmically, I need to operate the splitters in a certain order depending on how the user has resized the panel.  I actually don't know how the user has resized the panel from the the EVENT_SIZE event, though I could figure it out by looking at where my splitter controls are relative to the new panel size.  I also thought about triggering off the EVENT_PANEL_SIZING event, as there shouldn't be any large resizes as the event would fire as the user drags the panel.  This mostly works for my simple example, though I'm worried about performance with graphs that have data plotted, and besides I still have the problem when the user maximizes/restores the application.  Another option that would probably work though inelegant would be to simply loop through my callback twice.

 

I'm curious if anyone else has encountered this problem before, and if there is a more "elegant" solution to get two controls to resize proportionally.  What it seems that I really need is "batch operate splitters" or similar that would operate all the splitters at once so that operations don't get clipped during the intermediate steps.  I've attached the sample application if anyone wants to play around with it.  Thanks.

 

0 Kudos
Message 1 of 5
(3,333 Views)

The true fact is that a splitter control has intrinsic limits in how it can be moved both manually and programmatically. In your example you can drag splitters with the mouse: if you try, you will see that horizontal middle splitter cannot be moved downwards up to lower panel edge: it remains a few pixels above this element, so that the lower canvas remains at least a few pixels high. OperateSplitter shares similar limits.

 

Now, coming to your example, the function that moves the splitter firstly operate on the middle splitter, and after that operates on the lower one. When you heavily change panel height, the middle splitter cannot move the full amoun the program calulates because the lower canvas has not yet moved, and that is why you see an incorrect resizing of controls.

The easiest solution is to let the system operate for the first on the lower splitter, and on the middle one after that. To achieve this you can simply edit MultSplitter_SetupSplitters () function so that hsplitter is created before hsplitter2.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 5
(3,316 Views)

Just rethinking to your question (sleeping on a problem sometimes helps Smiley Wink 😞 my solution works as expected when raising panel height, but it doesn't handle the situation correctly when decreasing it.

As far as I can understand, you must abandon your method of scanning panel controls and operating in the tab order they appear. You must save elsewhere control IDs instead, together with panel previous height and width and discriminate resizing direction, operating on the lower splitter first if raising height, on the middle splitter first if reducing it. Alternatively you may trap EVENT_PANEL_SIZING too and save the border being resized as recevied in eventData1 to be reused on EVENT_PANEL_SIZE event.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 3 of 5
(3,305 Views)
Solution
Accepted by topic author tstanley

OK, sleeping sometimes really helps: I finally read your original post entirely ( Smiley Embarassed ) where you already had described what I suggested you.

 

I found an alternative to this situation with a little change in how controls are added to splitters. That is:

 

  • The lower canvas is attached to the middle splitter so that it is moved
  • The lower splitter is attached to the middle splitter in moving fashion too
  • In resizing, the lower splitter is treated as the middle one (that is, is operated half the amount of total panel resizing)

This way, resizing is correct both in widening and shrinking, with no need to detect the direction the operator resizes the panel.

Attached is the modified source code that performs all this.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Message 4 of 5
(3,286 Views)

Thanks for looking into this.  The whole multi-splitter splitter thing gives me headaches Smiley Happy .  Your modifications work perfectly.

 

I think I understand how it works.  I knew I needed the bottom control attached to two splitters, but I was caught up with the idea of reusing my "edge splitter" idea that I use when there is only one item on the panel that I want to resize.  I knew I needed the two splitters, just didn't occur to me to try two "middle" splitters.

 

One thing though, is that it doesn't seem nessecary to attach the first middle splitter (hsplitter) to the second middle splitter (hsplitter2).  I'm not even sure what that would accomplish as both splitters are moved programically as it is.  As a matter of fact, the code right now wouldn't even do the attachment due to the 

 

if(control_id != hsplitter2 && control_id != vsplitter)

 

line that's in the while loop before the switch/case statement, unless I'm mistaken about something.

 

Now, I do have a panel where I have three controls stacked, which may need to be resizable.  I'll have to see if I can figure that one out Smiley Surprised.

0 Kudos
Message 5 of 5
(3,273 Views)