ContainerGadget fires #PB_EventType_LeftClick on resize

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

ContainerGadget fires #PB_EventType_LeftClick on resize

Post by uwekel »

Hi,

today i noticed that the ContainerGadget fires an #PB_EventType_LeftClick when the size will be changed programmatically. This is very helpful to reorganize embedded gadgets inside the container.

In the help file i did not find any information about that, so it would be very helpful if the supported events will be described in the PB help document.

From my opinion, the #PB_Eventtype_LeftClick is wrong, because resizing has nothing to do with mouse clicks. #PB_EventType_Change would better fit, or #PB_EventType_SizeItem, or a new event type #PB_EventType_SizeGadget.

Some code to test:

Code: Select all

Structure CustomGadgetData
  Button1.i
  Button2.i
EndStructure

Procedure CustomGadgetResize()
  g = EventGadget()
  *data.CustomGadgetData = GetGadgetData(g)
  w = GadgetWidth(g)
  h = GadgetHeight(g) / 2
  ResizeGadget(*data\Button1, #PB_Ignore, #PB_Ignore, w, h)
  ResizeGadget(*data\Button2, #PB_Ignore, h, w, h)
EndProcedure
Procedure CustomGadget(Gadget, X, Y, W, H)
  ContainerGadget(Gadget, x, y, w, h, #PB_Container_BorderLess)
  *data.CustomGadgetData = AllocateMemory(SizeOf(CustomGadgetData))
  SetGadgetData(Gadget, *data)
  h / 2
  *data\Button1 = ButtonGadget(#PB_Any, 0, 0, w, h, "1")
  *data\Button2 = ButtonGadget(#PB_Any, 0, h, w, h, "2")
  CloseGadgetList()
  BindGadgetEvent(Gadget, @CustomGadgetResize(), #PB_EventType_LeftClick)
EndProcedure

If OpenWindow(0, 0, 0, 300, 200, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  CustomGadget(0, 10, 10, 280, 180)
  Repeat
    Select WaitWindowEvent()
    Case #PB_Event_Gadget
    Case #PB_Event_SizeWindow
      ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20, WindowHeight(0) - 20)
    Case #PB_Event_CloseWindow
      Break
    EndSelect
  ForEver
EndIf
Best regards
Uwe
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by uwekel »

I just checked the code on Linux, but there is no event at all :-(
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by Fred »

There is no eventtype() support for the containergadget(), as there is only a size event. But you are right, it should be another eventtype like "#PB_EventType_Size" to avoid confusion. I will move this in feature and request.
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by NicTheQuick »

+1
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by uwekel »

Hi Fred,
any chance to get this with the next release?
But we should have it for all platforms :)
Uwe
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by uwekel »

Here is an example how it could work:

Code: Select all

;XContainerGadget which fires a Change event on resize

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  ProcedureC _XContainerSizeAllocate(*Widget, *Allocation.GtkAllocation, *UserData)
    ;we have to check real size change, otherwise we run into an endless loop
    Static oldw, oldh
    If *Allocation\width <> oldw Or *Allocation\height <> oldh
      oldw = *Allocation\width
      oldh = *Allocation\height
      ;simulate behavior as in Windows
      PostEvent(#PB_Event_Gadget, 0, *UserData, #PB_EventType_LeftClick, 0)
    EndIf
  EndProcedure
CompilerEndIf
Procedure XContainerGadget(Gadget, X, Y, W, H)
  *container = ContainerGadget(Gadget, x, y, w, h, #PB_Container_Flat)
  ;on Linux, we simulate the same behaviour as on Windows
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    g_signal_connect_(*container, "size-allocate", @_XContainerSizeAllocate(), Gadget)
  CompilerEndIf
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
  
  Procedure TestResize()
    ;here we can layout all gadgets inside our container
    box = EventGadget()
    button = GetGadgetData(box)
    w = GadgetWidth(box)
    h = GadgetHeight(box)
    ResizeGadget(button, #PB_Ignore, #PB_Ignore, w, h)
  EndProcedure
  Procedure TestGadget(Gadget, x, y, w, h)
    ;create a custom gadget with other gadgets inside (here just one button)
    XContainerGadget(Gadget, x, y, w, h)    
    button = ButtonGadget(#PB_Any, 0, 0, w, h, "Cool")
    SetGadgetData(Gadget, button)
    ;now we bind the one and only event of our container to a layout procedure
    BindGadgetEvent(Gadget, @TestResize())
    CloseGadgetList()
  EndProcedure
  
  If OpenWindow(0, 0, 0, 300, 300, "DateGadgetTest", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
    TestGadget(0, 10, 10, 280, 280)
    Repeat
      Select WaitWindowEvent()
      Case #PB_Event_SizeWindow
        ;resize custom gadget
        ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20, WindowHeight(0) - 20)
      Case #PB_Event_CloseWindow
        Break
      EndSelect
    ForEver
  EndIf
  
CompilerEndIf
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by davido »

+1
DE AA EB
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by mestnyi »

Code: Select all


;find out whether the gadget has changed: in size or in positions
;---------------------------------
Enumeration #PB_Event_FirstCustomValue
    #PB_EventType_MoveGadget
    #PB_EventType_MoveGadget_X
    #PB_EventType_MoveGadget_Y
    
    #PB_EventType_SizeGadget
    #PB_EventType_SizeGadget_Width
    #PB_EventType_SizeGadget_Height
EndEnumeration

Procedure GadgetMove(Gadget,x,y)
 Static OldX,OldY 
  If (OldX<>x And x<>#PB_Ignore) Or (OldY<>y And y<>#PB_Ignore ) 
   PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_MoveGadget)
  EndIf  
  If OldX<>x And x<>#PB_Ignore 
    PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_MoveGadget_X)
   OldX=x 
  EndIf  
  If OldY<>y And y<>#PB_Ignore 
    PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_MoveGadget_Y)
   OldY=y 
  EndIf  
  
 ResizeGadget(Gadget,x,y,#PB_Ignore,#PB_Ignore) 
EndProcedure 

Procedure GadgetSize(Gadget,Width,Height)
 Static OldWidth,OldHeight 
  If (OldWidth<>Width And Width<>#PB_Ignore) Or (OldHeight<>Height And Height<>#PB_Ignore)
   PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_SizeGadget)
  EndIf
  If OldWidth<>Width And Width<>#PB_Ignore 
   PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_SizeGadget_Width)
   OldWidth=Width 
  EndIf  
  If OldHeight<>Height And Height<>#PB_Ignore 
   PostEvent(#PB_Event_Gadget,EventWindow(),Gadget,#PB_EventType_SizeGadget_Height)
   OldHeight=Height 
  EndIf  
  
 ResizeGadget(Gadget,#PB_Ignore,#PB_Ignore,Width,Height) 
EndProcedure  

Procedure SetResizeGadget2(Gadget)
  Protected x,y,w,h
   x=GadgetX(Gadget)
   y=GadgetY(Gadget)
   w=GadgetWidth(Gadget)
   h=GadgetHeight(Gadget)
   
   GadgetMove(Gadget,x,y)
   GadgetSize(Gadget,w,h)
EndProcedure

Macro ResizeGadget(Gadget,x,y,w,h)
 GadgetMove(Gadget,x,y)
   GadgetSize(Gadget,w,h) 
EndMacro 
;---------------------------------





Procedure Event_Size_Gadget()
 ;Debug "Size - " + EventGadget()
 If EventType()=#PB_EventType_SizeGadget_Width
  Debug "Size_w - " + EventGadget() + " w= " + GadgetWidth(EventGadget())
 
 EndIf         
 If EventType()=#PB_EventType_SizeGadget_Height
  Debug "Size_h - " + EventGadget() + " h= " + GadgetHeight(EventGadget())
 
 EndIf         
EndProcedure

Procedure Event_Move_Gadget()
 ;Debug "Size - " + EventGadget()
 If EventType()=#PB_EventType_MoveGadget_X
 Debug "Move_x - " + EventGadget() + " x= " + GadgetX(EventGadget())
 
 EndIf         
 If EventType()=#PB_EventType_MoveGadget_Y
 Debug "Move_y - " + EventGadget() + " y= " + GadgetY(EventGadget())
 
 EndIf         
 EndProcedure


Global GadgetCheck,delta_x,delta_y
Global Window_0,Window_1
Global SelectGadget

 

Procedure OpenWindow_0(x = 0, y = 0, width = 330, height = 340)
    Window_0 = OpenWindow(#PB_Any, x, y, width, height, "1", #PB_Window_SystemMenu| #PB_Window_SizeGadget)

    ButtonGadget(5, 5, 5, 320, 330,"")
   
    BindGadgetEvent(5,@Event_Size_Gadget())
    BindGadgetEvent(5,@Event_Move_Gadget())
EndProcedure
     


OpenWindow_0()
    



  
Repeat
  
  Select WaitWindowEvent()
      Case #PB_Event_Gadget
          
            
       Case #PB_Event_SizeWindow
        If EventWindow()=Window_0
         ResizeGadget(5,#PB_Ignore,#PB_Ignore,WindowWidth(Window_0)-10,WindowHeight(Window_0)-10)
        EndIf
       Case #PB_Event_CloseWindow
         End
       EndSelect
    ForEver
That's the way out of the situation :) that good about it began to speak, :wink: the fact of change need any gadget :|
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by Shardik »

uwekel,

the most simple solution for your example in your first posting would be to simply call the procedure CustomGadgetResize() directly after ResizeGadget(0,...) without using BindGadgetEvent() at all. This solution is also automatically cross-platform because it doesn't use any API calls... :wink:

Code: Select all

Structure CustomGadgetData
  Button1.i
  Button2.i
EndStructure

Procedure CustomGadgetResize()
  g = EventGadget()
  *data.CustomGadgetData = GetGadgetData(g)
  w = GadgetWidth(g)
  h = GadgetHeight(g) / 2
  ResizeGadget(*data\Button1, #PB_Ignore, #PB_Ignore, w, h)
  ResizeGadget(*data\Button2, #PB_Ignore, h, w, h)
EndProcedure

Procedure CustomGadget(Gadget, X, Y, W, H)
  ContainerGadget(Gadget, x, y, w, h, #PB_Container_BorderLess)
  *data.CustomGadgetData = AllocateMemory(SizeOf(CustomGadgetData))
  SetGadgetData(Gadget, *data)
  h / 2
  *data\Button1 = ButtonGadget(#PB_Any, 0, 0, w, h, "1")
  *data\Button2 = ButtonGadget(#PB_Any, 0, h, w, h, "2")
  CloseGadgetList()
EndProcedure

If OpenWindow(0, 0, 0, 300, 200, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  CustomGadget(0, 10, 10, 280, 180)
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Debug "GadgetID = " + EventGadget()
      Case #PB_Event_SizeWindow
        ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20, WindowHeight(0) - 20)
        CustomGadgetResize()
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
EndIf
The following code is a much more complicated true cross-platform example for detecting the resizing of a ContainerGadget. It works in both ASCII and Unicode mode on all platforms. I have tested it successfully with PB 5.22 on these operating systems:
- Kubuntu 12.04 x64 with KDE
- Kubuntu 14.04 x86 with KDE
- MacOS X 10.6.8 (Snow Leopard) with PB x86 and x64
- Ubuntu 14.04 x86 with Unity
- Windows XP SP3 x86
- Windows 7 SP1 x86
- Windows 7 SP1 x64 with PB x64

The MacOS part currently doesn't do a live resizing of the Button in the ContainerGadget. The resizing happens after releasing the mouse button when resizing the window. If you need live resizing on MacOS, I can easily add that feature to my example although it would become even more complicated... :wink:

By the way: in order to work in Unicode mode the following example has to be more complicated as necessary because of workarounds for bugs in the PB versions for Linux and MacOS. I have already reported a bug in the pseudotypes P-ASCII and P-UTF8 in the MacOS bug subforum and an incorrect predefined API function g_signal_connect_data_() in the Linux bug subforum.

Code: Select all

EnableExplicit

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; --------------------------------------------------
    ProcedureC ContainerResizeCallback(*Widget.GtkWidget,
      *Allocation.GtkAllocation, *UserData)
      Static GadgetHeight.I
      Static GadgetWidth.I

      If *Allocation\width <> GadgetWidth Or *Allocation\height <> GadgetHeight
        GadgetWidth = *Allocation\width
        GadgetHeight = *Allocation\height
        ResizeGadget(1, #PB_Ignore, #PB_Ignore, GadgetWidth, GadgetHeight)
      EndIf
    EndProcedure
  CompilerCase #PB_OS_MacOS ; --------------------------------------------------
    ImportC ""
      sel_registerName(MethodName.S)
      class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
    EndImport

    Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
      "NSApplication sharedApplication"), "delegate")
    Define NotificationCenter.I = CocoaMessage(0, 0,
      "NSNotificationCenter defaultCenter")

    ProcedureC ContainerResizeCallback(Object.I, Selector.I, Sender.I)
      ResizeGadget(1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20,
        WindowHeight(0) - 20)
    EndProcedure

    Procedure.S ConvertToUTF8(String.S)
      Protected UTF8String.S = Space(StringByteLength(String))
      PokeS(@UTF8String, String, -1, #PB_UTF8)
      ProcedureReturn UTF8String
    EndProcedure
  CompilerCase #PB_OS_Windows ; ------------------------------------------------
    Procedure ContainerResizeCallback()
      ResizeGadget(1, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20,
        WindowHeight(0) - 20)
    EndProcedure
CompilerEndSelect ; ------------------------------------------------------------

OpenWindow(0, 270, 100, 120, 50, "Container resizing",
  #PB_Window_SystemMenu | #PB_Window_SizeGadget)
WindowBounds(0, 110, 50, #PB_Ignore, #PB_Ignore)
ContainerGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20)
ButtonGadget(1, 0, 0, GadgetWidth(0), GadgetHeight(0), "Test Button")

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; --------------------------------------------------
    Define SignalName.S = Space(StringByteLength("size-allocate", #PB_UTF8))

    PokeS(@SignalName, "size-allocate", -1, #PB_UTF8)
    g_signal_connect_(GadgetID(0), SignalName, @ContainerResizeCallback(), 0)
  CompilerCase #PB_OS_MacOS ; --------------------------------------------------
    class_addMethod(CocoaMessage(0, AppDelegate, ConvertToUTF8("class")),
      sel_registerName(ConvertToUTF8("ContainerResizeCallback")),
      @ContainerResizeCallback(), ConvertToUTF8("v@:@"))
    CocoaMessage(0, NotificationCenter,
      "addObserver:", AppDelegate,
      "selector:", sel_registerName(ConvertToUTF8("ContainerResizeCallback")),
      "name:$", @"NSViewFrameDidChangeNotification",
      "object:", GadgetID(0))
  CompilerCase #PB_OS_Windows ; ------------------------------------------------
    BindGadgetEvent(0, @ContainerResizeCallback(), #PB_EventType_LeftClick)
CompilerEndSelect ; ------------------------------------------------------------

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_SizeWindow
      ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0) - 20,
        WindowHeight(0) - 20)
    Case #PB_Event_CloseWindow
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
        CocoaMessage(0, NotificationCenter, "removeObserver:", AppDelegate)
      CompilerEndIf
      Break
  EndSelect
ForEver
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: ContainerGadget fires #PB_EventType_LeftClick on resize

Post by uwekel »

Shardik wrote:the most simple solution for your example in your first posting would be to simply call the procedure CustomGadgetResize() directly after ResizeGadget(0,...) without using BindGadgetEvent() at all. This solution is also automatically cross-platform because it doesn't use any API calls... :wink:
This is what i did in the past, but now i am working with an own-written table layouting gadget, and this can use the ResizeGadget() only, because any custom gadgets are not known by the table layouter.
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Post Reply