Detect SplitterGadget drag

Just starting out? Need help? Post your questions and find answers here.
wombats
Enthusiast
Enthusiast
Posts: 663
Joined: Thu Dec 29, 2011 5:03 pm

Detect SplitterGadget drag

Post by wombats »

Hi,

The SplitterGadget functions very slowly for me because I have a number of gadgets inside the ContainerGadgets that get resized. This is my problem.

I thought maybe unbinding the #PB_EventType_Resize event from the #RightTopContainer and #RightBottomContainer when the #MainSplitter is moved, but I would need to be able to detect when the user starts and finishes moving the SplitterGadget's handle. Is there a way I can do that?

It might also be helpful to be able to detect when the user begins and finishes resizing the window, but I don't know if there is a way to do that.
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: Detect SplitterGadget drag

Post by kenmo »

I'm on Windows right now so I can't see your problem in action.

But I think I understand: you resize one splitter, it fires events for other splitters, your binded procedures run, and they resize the contents unnecessarily..?

A workaround is to track the real size of your container and only resize the contents if it has actually changed.
I suggest you store a width/height variable with the problematic containers, or you can use a general-purpose but less-efficient procedure like:

Code: Select all

Procedure.i GadgetSizeChanged(Gadget.i)
  Static NewMap Size.s()
  If (FindMapElement(Size(), Hex(Gadget)))
    If ((Hex(GadgetWidth(Gadget)) = StringField(Size(), 1, ",")) And
        (Hex(GadgetHeight(Gadget)) = StringField(Size(), 2, ",")))
      ProcedureReturn (#False)
    EndIf
  EndIf
  Size(Hex(Gadget)) = Hex(GadgetWidth(Gadget)) + "," + Hex(GadgetHeight(Gadget))
  ProcedureReturn (#True)
EndProcedure
wombats
Enthusiast
Enthusiast
Posts: 663
Joined: Thu Dec 29, 2011 5:03 pm

Re: Detect SplitterGadget drag

Post by wombats »

Hi,

That doesn't seem to help, unfortunately, as the ContainerGadgets still seem to get resized when they shouldn't. That doesn't happen on Windows. However, on both macOS and Windows, all ContainerGadgets fire their resize event when the window is resized...I'm not sure if that's the expected behaviour, especially for the RightTopContainer and RightBottomContainer as they don't actually change their size.

Here is a video: https://imgur.com/a/UfMD3FT. The SplitterGadget on the right 'jumps'. This is even more pronounced in my project that contains a lot of gadgets in those two containers. It's horribly slow and laggy.

Code: Select all

EnableExplicit

Enumeration
  #RightSplitter
  #LeftSplitter
  #MiddleSplitter
  #MainSplitter
EndEnumeration

Procedure.i GadgetSizeChanged(Gadget.i)
  Static NewMap Size.s()
  If (FindMapElement(Size(), Hex(Gadget)))
    If ((Hex(GadgetWidth(Gadget)) = StringField(Size(), 1, ",")) And
        (Hex(GadgetHeight(Gadget)) = StringField(Size(), 2, ",")))
      ProcedureReturn (#False)
    EndIf
  EndIf
  Size(Hex(Gadget)) = Hex(GadgetWidth(Gadget)) + "," + Hex(GadgetHeight(Gadget))
  ProcedureReturn (#True)
EndProcedure

Procedure OnContainerResized()
  Protected gadget, child, itemCount
  gadget = EventGadget()
  child = GetGadgetData(EventGadget())
  If GadgetSizeChanged(gadget)
    ResizeGadget(child, #PB_Ignore, #PB_Ignore, GadgetWidth(gadget), GadgetHeight(gadget))
    SetGadgetText(child, Str(Random(100)))
  EndIf
EndProcedure

Procedure OnWindowSized()
  ResizeGadget(#MainSplitter, 0, 0, WindowWidth(0), WindowHeight(0))
EndProcedure

Procedure.i MakeContainer()
  Protected id, child
  id = ContainerGadget(#PB_Any, 0, 0, 0, 0, #PB_Container_Single)
  child = StringGadget(#PB_Any, 0, 0, 0, 0, "")
  SetGadgetData(id, child)
  CloseGadgetList()
  BindGadgetEvent(id, @OnContainerResized(), #PB_EventType_Resize)
  ProcedureReturn id
EndProcedure

Global RightTopContainer, RightBottomContainer, LeftTopContainer, LeftBottomContainer, MiddleContainer

OpenWindow(0, 0, 0, 640, 480, "", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)

BindEvent(#PB_Event_SizeWindow, @OnWindowSized(), 0)

LoadFont(0, "Verdana", 20)
SetGadgetFont(#PB_Default, FontID(0))

RightTopContainer = MakeContainer()
RightBottomContainer = MakeContainer()
LeftTopContainer = MakeContainer()
LeftBottomContainer = MakeContainer()
MiddleContainer = MakeContainer()

SplitterGadget(#RightSplitter, 0, 0, 100, 100, RightTopContainer, RightBottomContainer)
SplitterGadget(#LeftSplitter, 0, 0, 100, 100, LeftTopContainer, LeftBottomContainer)
SplitterGadget(#MiddleSplitter, 0, 0, 640, 480, MiddleContainer, #RightSplitter, #PB_Splitter_Vertical | #PB_Splitter_SecondFixed)
SplitterGadget(#MainSplitter, 0, 0, 640, 480, #LeftSplitter, #MiddleSplitter, #PB_Splitter_Vertical)

SetGadgetState(#MiddleSplitter, 100)
SetGadgetState(#LeftSplitter, 100)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
wombats
Enthusiast
Enthusiast
Posts: 663
Joined: Thu Dec 29, 2011 5:03 pm

Re: Detect SplitterGadget drag

Post by wombats »

I found a way to detect when the user moves the cursor over the splitter handle. I unbind the events and then rebind them when they move the cursor off the handle. Unfortunately, while this is a little better, there is still a lot of lag and undesirable visual effects. I don't know what to do about it. It is similar to the video I included above, but much more pronounced because I have several gadgets in the containers in the right-hand splitter.
Post Reply