Page 1 of 1

How to customized scrallbar?

Posted: Sun May 29, 2016 2:18 pm
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

Re: How to customized scrallbar?

Posted: Wed Jun 01, 2016 5:57 pm
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?

Re: How to customized scrallbar?

Posted: Wed Jun 01, 2016 6:36 pm
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

Re: How to customized scrallbar?

Posted: Wed Jun 01, 2016 7:19 pm
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

Re: How to customized scrallbar?

Posted: Wed Jun 01, 2016 10:33 pm
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

Re: How to customized scrallbar?

Posted: Wed Jun 01, 2016 10:50 pm
by Wolfram
Hi Shardik,

thanks!
Do you know how to replace the bar?

Re: How to customized scrallbar?

Posted: Thu Jun 02, 2016 8:38 am
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

Re: How to customized scrallbar?

Posted: Thu Jun 02, 2016 10:48 am
by Wolfram
Thank you!

Re: How to customized scrallbar?

Posted: Thu Jun 02, 2016 11:46 am
by IdeasVacuum
You could consider defining your own scroll bar gadget using CanvasGadget(). You will then have complete control over all aspects.

Re: How to customized scrallbar?

Posted: Thu Jun 02, 2016 12:23 pm
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?

Re: How to customized scrallbar?

Posted: Thu Jun 02, 2016 2:26 pm
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)

Re: How to customized scrallbar?

Posted: Fri Jun 03, 2016 4:37 pm
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