How to customized scrallbar?

Mac OSX specific forum
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

How to customized scrallbar?

Post by Wolfram »

Hello,

does anyone know how to built a customized scrallbar with cocoa?

I found some links but can't translate it :-/
http://stackoverflow.com/questions/1967 ... with-cocoa
https://bitbucket.org/bwalkin/bwtoolkit ... ew-default

Code: Select all

OpenWindow( 0, 0, 0, 200, 200, "Custom Scrollbar", #PB_Window_ScreenCentered | #PB_Window_SystemMenu )

Global *MyWindow = WindowID(0)

Global Frame.NSRect
Frame\origin\x = 10
Frame\origin\y = 50
Frame\size\width = 180
Frame\size\height = 25

Global MyScroller
CocoaMessage( @MyScroller, #Null, "NSScroller alloc" )
Debug "MyScroller address: " + MyScroller

Global MyKnob
MyKnob = ImageID( CreateImage(#PB_Any, 500, 500, 32, RGB(23, 111, 165)) )

CocoaMessage( 0, MyScroller, "initWithFrame:@", @Frame )

Global Frame.NSRect
CocoaMessage( @Frame, MyScroller, "frame" )


Global p.NSPoint
p\x =0  :  p\y =0
Global Rect.NSRect
Rect\origin\x =0
Rect\origin\y =0
Rect\size\width =500
Rect\size\height =500

#NSCompositeSourceOver =2

Global delta.f =1.0

NSZeroRect.NSRect

NSZeroRect\origin\x =0
NSZeroRect\origin\y =0
NSZeroRect\size\width =0
NSZeroRect\size\height =0


CocoaMessage(0, MyKnob, "drawAtPoint:", @p, "fromRect:", @NSZeroRect, "operation:", #NSCompositeSourceOver, "fraction:", @delta)


Global View
CocoaMessage( @View, *MyWindow, "contentView" )

CocoaMessage(0, View, "addSubview:", MyScroller )


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
      
  EndSelect
ForEver
Thanks for any help
Last edited by Wolfram on Wed Jun 01, 2016 5:59 pm, edited 1 time in total.
macOS Catalina 10.15.7
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

I updated the code and get no compiler errors anymore but I can't see any effect.

Does some one has an idea?
macOS Catalina 10.15.7
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to customized scrallbar?

Post by wilbert »

What are you trying to do ?
It's easier to modify an existing slider or scrollbar.

This code from Shardik shows for example a circular slider (a modified TrackBarGadget).
http://www.forums.purebasic.com/english ... 88#p461088
Windows (x64)
Raspberry Pi OS (Arm64)
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

Hi Wilbert,

I want to override the bar of a scrollbar to have a different look.
As far as I understand some on override the knob of the srollbar in these example.
http://stackoverflow.com/questions/1967 ... with-cocoa
macOS Catalina 10.15.7
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How to customized scrallbar?

Post by Shardik »

The following example demonstrates how to modify the knob of a ScrollBarGadget. I have successfully tested it with PB 5.42 x86 and x64 on Mac OS X 10.6.8 (Snow Leopard) and 10.11.4 (El Capitan).

Code: Select all

EnableExplicit

#KnobWidth = 20

ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  objc_allocateClassPair(ModelClass.I, NewClassName.P-ASCII, ExtraBytes.I)
  objc_registerClassPair(NewClass.I)
  object_setClass(ObjectToModify.I, NewClass.I)
  sel_registerName(MethodName.P-ASCII)
EndImport

Define CustomScrollBar.I
Define CustomScrollBarClass.I
Define View.I

ProcedureC DrawKnobCallback(Object.I, Selector.I)
  Protected Delta.CGFloat = 0.7
  Protected Point.NSPoint
  Protected Rect.NSRect

  If OSVersion() <= #PB_OS_MacOSX_10_6
    Point\x = GetGadgetState(0) * (GadgetWidth(0) - #KnobWidth) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + #KnobWidth
  Else
    Point\x = GetGadgetState(0) * (GadgetWidth(0) + #KnobWidth + 6) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + 2
  EndIf

  Point\y = 1
  Rect\origin\x = 0
  Rect\size\width = #KnobWidth
  Rect\size\height = 13

  CocoaMessage(0, ImageID(0),
    "drawAtPoint:@", @Point,
    "fromRect:@", @Rect,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure

; ----- Create image for knob
CreateImage(0, #KnobWidth, 13, 32, $9370DB)

; ----- Create window
OpenWindow(0, 270, 100, 260, 70, "ScrollBar with custom knob")
SetWindowColor(0, $C4E4FF)
ScrollBarGadget(0, 10, 25, WindowWidth(0) - 20, 15, 0, 100, #KnobWidth)

; ----- Subclass ScrollBar
CustomScrollBarClass = objc_allocateClassPair(CocoaMessage(0,
  GadgetID(0), "class"), "CustomScrollBar", 0)
objc_registerClassPair(CustomScrollBarClass)
object_setClass(GadgetID(0), CustomScrollBarClass)

; ----- Set callback for drawing the knob
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnob"),
  @DrawKnobCallback(), "v@")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

Hi Shardik,

thanks!
Do you know how to replace the bar?
macOS Catalina 10.15.7
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to customized scrallbar?

Post by wilbert »

It's probably something like this (x64)

Code: Select all

EnableExplicit

#KnobWidth = 20

ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  objc_allocateClassPair(ModelClass.I, NewClassName.P-ASCII, ExtraBytes.I)
  objc_registerClassPair(NewClass.I)
  object_setClass(ObjectToModify.I, NewClass.I)
  sel_registerName(MethodName.P-ASCII)
EndImport

Define CustomScrollBar.I
Define CustomScrollBarClass.I
Define View.I

ProcedureC DrawKnobCallback(Object.I, Selector.I)
  Protected Delta.CGFloat = 0.7
  Protected Point.NSPoint
  Protected Rect.NSRect

  If OSVersion() <= #PB_OS_MacOSX_10_6
    Point\x = GetGadgetState(0) * (GadgetWidth(0) - #KnobWidth) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + #KnobWidth
  Else
    Point\x = GetGadgetState(0) * (GadgetWidth(0) + #KnobWidth + 6) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + 2
  EndIf

  Point\y = 1
  Rect\origin\x = 0
  Rect\size\width = #KnobWidth
  Rect\size\height = 13

  CocoaMessage(0, ImageID(0),
    "drawAtPoint:@", @Point,
    "fromRect:@", @Rect,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure

ProcedureC DrawTrackCallback(Object.I, Selector.I, Highlight, d1.d,d2.d,d3.d,d4.d,d5.d,d6.d,d7.d,d8.d, x.d, y.d, w.d, h.d)
  Protected Delta.CGFloat = 1.0
  Protected Point.NSPoint
  Protected.NSRect src, dst
  
  Src\size\width = ImageWidth(1)
  Src\size\height = ImageHeight(1)
  Dst\origin\x = x
  Dst\origin\y = y
  Dst\size\width = w
  Dst\size\height = h
  
  CocoaMessage(0, ImageID(1),
    "drawInRect:@", @Dst,
    "fromRect:@", @Src,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure

; ----- Create image for knob
CreateImage(0, #KnobWidth, 13, 32, $9370DB)

; ----- Create image for track
CreateImage(1, 8, 8, 32, $00e0e0)

; ----- Create window
OpenWindow(0, 270, 100, 260, 70, "ScrollBar with custom knob")
SetWindowColor(0, $C4E4FF)
ScrollBarGadget(0, 10, 25, WindowWidth(0) - 20, 15, 0, 100, #KnobWidth)

; ----- Subclass ScrollBar
CustomScrollBarClass = objc_allocateClassPair(CocoaMessage(0,
  GadgetID(0), "class"), "CustomScrollBar", 0)
objc_registerClassPair(CustomScrollBarClass)
object_setClass(GadgetID(0), CustomScrollBarClass)

; ----- Set callback for drawing the knob
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnob"),
                @DrawKnobCallback(), "v@:")

; ----- Set callback for drawing the track
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnobSlotInRect:highlight:"),
                @DrawTrackCallback(), "v@:{CGRect={CGPoint=dd}{CGSize=dd}}c")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
For x86, the callback should be like this

Code: Select all

ProcedureC DrawTrackCallback(Object.I, Selector.I, x.f, y.f, w.f, h.f, Highlight)
If you want to combine x86 and x64 in one source, it could be done like this I believe

Code: Select all

EnableExplicit

#KnobWidth = 20

ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  objc_allocateClassPair(ModelClass.I, NewClassName.P-ASCII, ExtraBytes.I)
  objc_registerClassPair(NewClass.I)
  object_setClass(ObjectToModify.I, NewClass.I)
  sel_registerName(MethodName.P-ASCII)
EndImport

Define CustomScrollBar.I
Define CustomScrollBarClass.I
Define View.I

ProcedureC DrawKnobCallback(Object.I, Selector.I)
  Protected Delta.CGFloat = 0.7
  Protected Point.NSPoint
  Protected Rect.NSRect

  If OSVersion() <= #PB_OS_MacOSX_10_6
    Point\x = GetGadgetState(0) * (GadgetWidth(0) - #KnobWidth) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + #KnobWidth
  Else
    Point\x = GetGadgetState(0) * (GadgetWidth(0) + #KnobWidth + 6) / GetGadgetAttribute(0,
      #PB_ScrollBar_Maximum) + 2
  EndIf

  Point\y = 1
  Rect\origin\x = 0
  Rect\size\width = #KnobWidth
  Rect\size\height = 13

  CocoaMessage(0, ImageID(0),
    "drawAtPoint:@", @Point,
    "fromRect:@", @Rect,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure

ProcedureC DrawTrackCallback(Object.I, Selector.I, x.f, y.f, w.f, h.f, Highlight, d1.d,d2.d,d3.d,d4.d, x_.d, y_.d, w_.d, h_.d)
  Protected Delta.CGFloat = 1.0
  Protected Point.NSPoint
  Protected.NSRect src, dst
  
  Src\size\width = ImageWidth(1)
  Src\size\height = ImageHeight(1)
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    Dst\origin\x = x_
    Dst\origin\y = y_
    Dst\size\width = w_
    Dst\size\height = h_
  CompilerElse
    Dst\origin\x = x
    Dst\origin\y = y
    Dst\size\width = w
    Dst\size\height = h  
  CompilerEndIf
  
  CocoaMessage(0, ImageID(1),
    "drawInRect:@", @Dst,
    "fromRect:@", @Src,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure

; ----- Create image for knob
CreateImage(0, #KnobWidth, 13, 32, $9370DB)

; ----- Create image for track
CreateImage(1, 8, 8, 32, $00e0e0)

; ----- Create window
OpenWindow(0, 270, 100, 260, 70, "ScrollBar with custom knob")
SetWindowColor(0, $C4E4FF)
ScrollBarGadget(0, 10, 25, WindowWidth(0) - 20, 15, 0, 100, #KnobWidth)

; ----- Subclass ScrollBar
CustomScrollBarClass = objc_allocateClassPair(CocoaMessage(0,
  GadgetID(0), "class"), "CustomScrollBar", 0)
objc_registerClassPair(CustomScrollBarClass)
object_setClass(GadgetID(0), CustomScrollBarClass)

; ----- Set callback for drawing the knob
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnob"),
                @DrawKnobCallback(), "v@:")

; ----- Set callback for drawing the track
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnobSlotInRect:highlight:"),
                @DrawTrackCallback(), "v@:{CGRect={CGPoint=dd}{CGSize=dd}}c")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Windows (x64)
Raspberry Pi OS (Arm64)
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

Thank you!
macOS Catalina 10.15.7
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to customized scrallbar?

Post by IdeasVacuum »

You could consider defining your own scroll bar gadget using CanvasGadget(). You will then have complete control over all aspects.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

If I drag the knob it moves faster as the mouse.
I mean if I click on the left side of knob and move it to the right, the mouse is 30px behind the knob.
This is not just a problem of drawing on the right position, because if the knob is on the right the gadget is on its max value.

Does only on has an idea?
macOS Catalina 10.15.7
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

Ok this was a problem of the proportion.

Code: Select all

ScrollBarGadget(0, 10, 25, WindowWidth(0) - 20, 15, 0, 100, #KnobWidth)
Define Proportion.f =0.1
CocoaMessage(0,GadgetID(0), "setKnobProportion:@", @Proportion)
macOS Catalina 10.15.7
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to customized scrallbar?

Post by Wolfram »

These version draws perfect the knob, independent of the pages of the scrollbar.

Code: Select all

EnableExplicit



;NSScrollerPart
#NSScrollerNoPart = 0
#NSScrollerDecrementPage = 1
#NSScrollerKnob = 2
#NSScrollerIncrementPage = 3
#NSScrollerDecrementLine = 4
#NSScrollerIncrementLine = 5
#NSScrollerKnobSlot = 6


ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  objc_allocateClassPair(ModelClass.I, NewClassName.P-ASCII, ExtraBytes.I)
  objc_registerClassPair(NewClass.I)
  object_setClass(ObjectToModify.I, NewClass.I)
  sel_registerName(MethodName.P-ASCII)
EndImport


Define CustomScrollBar.I
Define CustomScrollBarClass.I
Define View.I
Global KnobWidth
Global Scale


ProcedureC DrawKnobCallback(Object.I, Selector.I)
  Protected Delta.CGFloat = 1.0
  Protected Point.NSPoint
  Protected Rect.NSRect
  Protected RectPart.NSRect
  
  CocoaMessage(@RectPart, GadgetID(0), "rectForPart:", #NSScrollerKnob )
  Point\x = RectPart\origin\x +2.2
  Point\y = 1
  Rect\origin\x = 0
  Rect\size\width =KnobWidth
  Rect\size\height = 13

  CocoaMessage(0, ImageID(0),
               "drawAtPoint:@", @Point,
               "fromRect:@", @Rect,
               "operation:", #NSCompositeSourceOver,
               "fraction:@", @Delta)

  
EndProcedure


ProcedureC DrawTrackCallback(Object.I, Selector.I, x.f, y.f, w.f, h.f, Highlight, d1.d,d2.d,d3.d,d4.d, x_.d, y_.d, w_.d, h_.d)
  Protected Delta.CGFloat = 1.0
  Protected Point.NSPoint
  Protected.NSRect src, dst
  
  Src\size\width = ImageWidth(1)
  Src\size\height = ImageHeight(1)
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    Dst\origin\x = x_
    Dst\origin\y = y_
    Dst\size\width = w_
    Dst\size\height = h_
  CompilerElse
    Dst\origin\x = x
    Dst\origin\y = y
    Dst\size\width = w
    Dst\size\height = h  
  CompilerEndIf
  
  CocoaMessage(0, ImageID(1),
    "drawInRect:@", @Dst,
    "fromRect:@", @Src,
    "operation:", #NSCompositeSourceOver,
    "fraction:@", @Delta)
EndProcedure



; ----- Create window
OpenWindow(0, 450, 100, 440, 70, "ScrollBar with custom knob")
SetWindowColor(0, $3A3D3E)

Define PageSize.i =15
ScrollBarGadget(0, 20, 25, 400, 15, 0, 100, PageSize)

; ----- Calculate knob width
Scale =GadgetWidth(0) / GetGadgetAttribute(0, #PB_ScrollBar_Maximum)
KnobWidth =GetGadgetAttribute(0, #PB_ScrollBar_PageLength) * Scale -4
 
; ----- Create image for knob
CreateImage(0, KnobWidth, 13, 32, $706C68)

; ----- Create image for track
CreateImage(1, 8, 8, 32, $C5C8C9)

; ----- Subclass ScrollBar
CustomScrollBarClass = objc_allocateClassPair(CocoaMessage(0,
  GadgetID(0), "class"), "CustomScrollBar", 0)
objc_registerClassPair(CustomScrollBarClass)
object_setClass(GadgetID(0), CustomScrollBarClass)

; ----- Set callback for drawing the track
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnobSlotInRect:highlight:"),
                @DrawTrackCallback(), "v@:{CGRect={CGPoint=dd}{CGSize=dd}}c")

; ----- Set callback for drawing the knob
class_addMethod(CustomScrollBarClass, sel_registerName("drawKnob"),
                @DrawKnobCallback(), "v@:")



Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
macOS Catalina 10.15.7
Post Reply