It is currently Fri Jan 24, 2020 3:47 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Re: Changing a SpinGadget value by mouse wheel
PostPosted: Wed Jan 06, 2016 9:41 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1678
Location: Germany
I have modified my example from above to work without any change in both Gtk2 and Gtk3 in PB 5.3x and PB 5.4x in both ASCII and Unicode mode. Unfortunately the look and design of the GtkSpinButton was changed from GTK2 to GTK3:
Image
Image
PureBasic is using a custom Gadget (a GtkHBox containing other Gadgets as stated in PB's blog) for its SpinGadget thus resulting in the same look in GTK2 and GTK3.
Code:
EnableExplicit

ImportC ""
  gtk_spin_button_new_with_range(Minimum.D, Maximum.D, StepIncrement.D)
EndImport

Procedure.I GetFixedBox(WindowID.I)
  Protected Child.I
  Protected ChildrenList.I
  Protected *Name
  Protected Widget.I = WindowID(WindowID)

  Child = gtk_bin_get_child_(Widget)

  Repeat
    ChildrenList = gtk_container_get_children_(Widget)
    Child = g_list_nth_data_(ChildrenList, 0)

    If Child = 0
      Break
    Else
      *Name = gtk_widget_get_name_(Child)
      Widget = Child
    EndIf
  Until PeekS(*Name, -1, #PB_UTF8) = "GtkFixed"

  ProcedureReturn Child
EndProcedure

Define FixedBox.I
Define SpinButton.I
Define Subsystem.S
Define x.I

CompilerIf #PB_Compiler_Version > 531
  CompilerIf Subsystem("gtk2")
    Subsystem = "Gtk2"
    x = 100
  CompilerElse
    Subsystem = "Gtk3"
    x = 80
  CompilerEndIf
CompilerElse
  CompilerIf Subsystem("gtk3")
    Subsystem = "Gtk3"
    x = 80
  CompilerElse
    Subsystem = "Gtk2"
    x = 100
  CompilerEndIf
CompilerEndIf

OpenWindow(0, 200, 100, 270, 60, "GtkSpinButton - " + Subsystem)
FixedBox = GetFixedBox(0)
SpinButton = gtk_spin_button_new_with_range(1, 100, 1)
gtk_fixed_put_(FixedBox, SpinButton, x, 20)
gtk_widget_show_all_(WindowID(0))

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow


Top
 Profile  
Reply with quote  
 Post subject: Re: Changing a SpinGadget value by mouse wheel
PostPosted: Sun Jan 24, 2016 10:43 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1678
Location: Germany
For those who prefer PB's SpinGadget to the API GtkSpinButton I have found a workaround for Gtk2 and Gtk3 to detect mouse wheel events in a SpinGadget and react accordingly.

Unfortunately the Gtk3 code is more complicated because of design changes from Gtk2 to Gtk3:
In Gtk3 the widgets don't possess anymore an own GdkWindow. In Gtk2 it's easy to detect whether the mouse wheel scroll event was fired by the GtkEntry widget contained in the SpinGadget by simply comparing the GdkWindow of the event with that of the GtkEntry. In Gtk3 it's necessary to compare the coordinates of the event with those of the GtkEntry and taking also into account the padding inside the GtkEntry (to work equally well with different desktop managers and themes)...

I have tested the following code examples successfully with PB 5.41 x64 in ASCII and Unicode mode on Ubuntu 14.04 x64 with these different desktop managers:
- Enlightenment E17
- KDE
- Unity

Gtk2 (subsystem "gtk2"):
Code:
EnableExplicit

#SpinGadget = 0

Define *Entry.GtkWidget

Procedure.I GetChildContainer(Widget.I, ContainerName.S)
  Protected Child.I
  Protected ChildrenList.I
  Protected i.I
  Protected *Name
 
  ChildrenList = gtk_container_get_children_(Widget)
 
  If ChildrenList
    For i = 0 To g_list_length_(ChildrenList)
      Child = g_list_nth_data_(ChildrenList, i)
     
      If Child
        *Name = gtk_widget_get_name_(Child)
       
        If PeekS(*Name, -1, #PB_UTF8) = ContainerName
          Widget = Child
          Break
        EndIf
      EndIf
    Next i
  EndIf
  ProcedureReturn Child
EndProcedure

ProcedureC MouseWheelCallback(*Event.GdkEventScroll, *UserData)
  Shared *Entry.GtkWidget

  If *Event\type = #GDK_SCROLL
    If *Entry\window = gdk_window_get_parent_(*Event\window)
      Select *Event\direction
        Case #GDK_SCROLL_UP
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) + 1)
        Case #GDK_SCROLL_DOWN
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) - 1)
      EndSelect
    EndIf
  EndIf
 
  gtk_main_do_event_(*Event)
EndProcedure

OpenWindow(0, 100, 100, 180, 70, "SpinGadget")
SpinGadget(#SpinGadget, 65, 20, 60, 25, 0, 100, #PB_Spin_Numeric)
SetGadgetState(#SpinGadget, 50)
SetActiveGadget(#SpinGadget)

; ----- Get GtkEntry contained in SpinGadget
*Entry = GetChildContainer(GadgetID(#SpinGadget), "GtkEntry")

; ----- Set event handler to intercept mouse wheel scroll events
gdk_event_handler_set_(@MouseWheelCallback(), 0, 0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

gdk_event_handler_set_(0, 0, 0)


Gtk3:
Code:
EnableExplicit

#SpinGadget = 0

#GTK_STATE_FLAG_SELECTED = 1 << 2

ImportC ""
  gtk_style_context_get_padding(*Context, GtkStateFlags.I, *Border.GtkBorder)
  gtk_widget_get_style_context(*Widget.GtkWidget)
  gtk_widget_get_allocated_height(*Widget.GtkWidget)
  gtk_widget_get_allocated_width(*Widget.GtkWidget)
EndImport

Structure _GtkBorder
  left.w
  right.w
  top.w
  bottom.w
EndStructure

Define *Entry.GtkWidget
Define Padding._GtkBorder

Procedure.I GetChildContainer(Widget.I, ContainerName.S)
  Protected Child.I
  Protected ChildrenList.I
  Protected i.I
  Protected *Name
 
  ChildrenList = gtk_container_get_children_(Widget)
 
  If ChildrenList
    For i = 0 To g_list_length_(ChildrenList)
      Child = g_list_nth_data_(ChildrenList, i)
     
      If Child
        *Name = gtk_widget_get_name_(Child)
       
        If PeekS(*Name, -1, #PB_UTF8) = ContainerName
          Widget = Child
          Break
        EndIf
      EndIf
    Next i
  EndIf

  ProcedureReturn Child
EndProcedure

Procedure GetPadding(*Widget.GtkWidget)
  Shared Padding._GtkBorder

  Protected StyleContext.I

  StyleContext = gtk_widget_get_style_context(*Widget)
  gtk_style_context_get_padding(StyleContext, #GTK_STATE_FLAG_SELECTED,
    @Padding)

  Padding\top + 1
EndProcedure

ProcedureC MouseWheelCallback(*Event.GdkEventScroll, *UserData)
  Shared *Entry.GtkWidget
  Shared Padding._GtkBorder

  Protected EntryHeight.I
  Protected EntryWidth.I
  Protected Entry_x.I
  Protected Entry_y.I

  If *Event\type = #GDK_SCROLL
    Entry_x = GadgetX(#SpinGadget) + Padding\left
    Entry_y = GadgetY(#SpinGadget) + Padding\top
    EntryWidth = gtk_widget_get_allocated_width(*Entry) - (Padding\left +
      Padding\right)
    EntryHeight = gtk_widget_get_allocated_height(*Entry) - (Padding\top +
      Padding\bottom)

    If *Event\x > Entry_x And *Event\x < Entry_x + EntryWidth And
      *Event\y > Entry_y And *Event\y < Entry_y + EntryHeight
      Select *Event\direction
        Case #GDK_SCROLL_UP
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) + 1)
        Case #GDK_SCROLL_DOWN
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) - 1)
      EndSelect
    EndIf
  EndIf
 
  gtk_main_do_event_(*Event)
EndProcedure

OpenWindow(0, 100, 100, 180, 70, "SpinGadget")

SpinGadget(#SpinGadget, 65, 20, 60, 25, 0, 100, #PB_Spin_Numeric)
SetActiveGadget(#SpinGadget)
SetGadgetState(#SpinGadget, 50)

; ----- Get GtkEntry contained in SpinGadget
*Entry = GetChildContainer(GadgetID(#SpinGadget), "GtkEntry")

; ----- Set event handler to intercept mouse wheel scroll events
gdk_event_handler_set_(@MouseWheelCallback(), 0, 0)

; ----- Calculate padding of GtkEntry inside of SpinGadget
GetPadding(*Entry)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

gdk_event_handler_set_(0, 0, 0)

This is a 3rd simplified example which isn't as pixel-perfect as the Gtk3 example above (because it doesn't take internal padding into account) but which runs without any change with both Gtk3 and Gtk2 (subsystem "gtk2") and is also triggered if the cursor is above the arrows (like in Windows):
Code:
EnableExplicit

#SpinGadget = 0

Procedure.I GetChildContainer(Widget.I, ContainerName.S)
  Protected Child.I
  Protected ChildrenList.I
  Protected i.I
  Protected *Name
 
  ChildrenList = gtk_container_get_children_(Widget)
 
  If ChildrenList
    For i = 0 To g_list_length_(ChildrenList)
      Child = g_list_nth_data_(ChildrenList, i)
     
      If Child
        *Name = gtk_widget_get_name_(Child)
       
        If PeekS(*Name, -1, #PB_UTF8) = ContainerName
          Widget = Child
          Break
        EndIf
      EndIf
    Next i
  EndIf

  ProcedureReturn Child
EndProcedure

ProcedureC MouseWheelCallback(*Event.GdkEventScroll, *UserData)
  If *Event\type = #GDK_SCROLL
    If WindowMouseX(0) > GadgetX(#SpinGadget) And
      WindowMouseX(0) < GadgetX(#SpinGadget) + GadgetWidth(#SpinGadget) And
      WindowMouseY(0) > GadgetY(#SpinGadget) And
      WindowMouseY(0) < GadgetY(#SpinGadget) + GadgetHeight(#SpinGadget)
      Select *Event\direction
        Case #GDK_SCROLL_UP
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) + 1)
        Case #GDK_SCROLL_DOWN
          SetGadgetState(#SpinGadget, GetGadgetState(#SpinGadget) - 1)
      EndSelect
    EndIf
  EndIf
 
  gtk_main_do_event_(*Event)
EndProcedure

OpenWindow(0, 100, 100, 180, 70, "SpinGadget")

SpinGadget(#SpinGadget, 65, 20, 60, 25, 0, 100, #PB_Spin_Numeric)
SetActiveGadget(#SpinGadget)
SetGadgetState(#SpinGadget, 50)

; ----- Set event handler to intercept mouse wheel scroll events
gdk_event_handler_set_(@MouseWheelCallback(), 0, 0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

gdk_event_handler_set_(0, 0, 0)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye