Hi,
Normally, on Windows (NumericSpinButton) and Linux (GtkSpinButton), you can edit a value by using the mouse wheel.
Not so with the PB SpinGaget, what would be great.
Best regards
Uwe
Changing a SpinGadget value by mouse wheel
Changing a SpinGadget value by mouse wheel
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Re: Changing a SpinGadget value by mouse wheel
Mousewheel works fine here on Win 7 64-bit with a SpinGadget.
Tested with the example in the manual after giving it the focus.
Tested with the example in the manual after giving it the focus.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
Re: Changing a SpinGadget value by mouse wheel
Mousewheel works also fine in Windows XP x86 SP3 and Windows 7 x86 SP1.PB wrote:Mousewheel works fine here on Win 7 64-bit with a SpinGadget.
Tested with the example in the manual after giving it the focus.
In Linux you may use the GtkSpinButton which supports changing values by using the mouse wheel. Simply position the cursor above the spin button and you are able to change the spin button values with your mouse wheel (tested with PB 5.11 x86 on Kubuntu 12.04 x86):
Code: Select all
ImportC ""
gtk_spin_button_new_with_range(Minimum.D, Maximum.D, StepIncrement.D)
EndImport
OpenWindow(0, 200, 100, 270, 60, "GtkSpinButton")
FixedBox = g_list_nth_data_(gtk_container_get_children_(gtk_bin_get_child_(WindowID(0))), 0)
SpinButton = gtk_spin_button_new_with_range(1, 10, 1)
gtk_fixed_put_(FixedBox, SpinButton, 100, 20)
gtk_widget_show_all_(WindowID(0))
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: Changing a SpinGadget value by mouse wheel
Thank you Shardik for the code sample! It looks promising.
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Re: Changing a SpinGadget value by mouse wheel
So in terms of multi-platform development i would like to declare it as a BUG for the linux version. Do i have to write another article in the "Linux - Bugs" section or can this one be moved?PB wrote:Mousewheel works fine here on Win 7 64-bit with a SpinGadget.
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Re: Changing a SpinGadget value by mouse wheel
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:
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.
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: Select all
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
Re: Changing a SpinGadget value by mouse wheel
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"):
Gtk3:
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):
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: Select all
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)
Code: Select all
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)
Code: Select all
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)