Hi Grisu,
I started hacking one into
MaxGUI.ProxyGadgets (back in the days when I had some free time :P), but it isn't quite finished yet.
Still, if you want to have a play, copy and paste this into a new file and import it into your project.
WARNING: ALPHA CODE (NOT TESTED, FEATURE COMPLETE OR BUG FREE)
Strict
Import MaxGUI.MaxGUI
Rem
bbdoc: Creates a panel that can automatically show/hide scrollbars so that gadgets outside the initial visible region can be reached.
about: There are two main parts of a scroll-panel.
The TScrollPanel instance itself represents the entire scroll-panel, which can be manipulated (e.g. resized/shown/hidden) using the
standard MaxGUI commands.
Perhaps more importantly, the client-area is the panel to which all your child gadgets should be added. Then client-area panel instance
can be retrieved using the #ScrollPanelClient command. Other than to add gadgets, this client-area panel should not be used.
Everytime a gadget is added, moved or freed from the client-area, #UpdateScrollPanel must be called to update the scroll-bars, although
the scroll-bars should be updated automatically upon window resize.
See Also: #ScrollPanelClient and #UpdateScrollPanel.
End Rem
Function CreateScrollPanel:TScrollPanel( x,y,w,h,group:TGadget,flags=0 )
Return New TScrollPanel.Create(x,y,w,h,group,flags)
EndFunction
Rem
bbdoc: Retrieves the client-area panel instance which is used to add gadgets to the scrollpanel.
about: Remember to call #UpdateScrollPanel after adding/moving/freeing child gadgets. The client-area
panel instance should only be used for adding gadgets; the TScrollPanel instance itself allows for
manipulation of the entire TScrollPanel instead.
See #CreateScrollPanel for more information.
End Rem
Function ScrollPanelClient:TGadget( scrollpanel:TScrollPanel )
Return scrollpanel.pnlClientArea
EndFunction
Rem
bbdoc: Recalculates and updates the scrollbars according to the current layout of the child gadgets.
about: See #CreateScrollPanel for more information.
End Rem
Function UpdateScrollPanel( scrollpanel:TScrollPanel )
scrollpanel.Update()
EndFunction
Type TScrollPanel Extends TProxyGadget
Field pnlEntire:TGadget
Field pnlViewport:TGadget
Field pnlClientArea:TGadget
Field scrHorizontal:TGadget
Field scrVertical:TGadget
Field oldH%, oldV%, clientW%, clientH%
Const SCROLL_WIDTH% = 18
Method Create:TScrollPanel(pX%, pY%, pWidth%, pHeight%, pParent:TGadget, pFlags% = 0)
pnlEntire = CreatePanel(pX,pY,pWidth,pHeight,pParent,pFlags);HideGadget(pnlEntire);SetProxy(pnlEntire)
pnlViewport = CreatePanel(0,0,ClientWidth(),ClientHeight(), pnlEntire)
pnlClientArea = CreatePanel(0,0,ClientWidth(),ClientHeight(), pnlViewport)
scrHorizontal = CreateSlider(0,ClientHeight()-SCROLL_WIDTH,ClientWidth()-SCROLL_WIDTH,SCROLL_WIDTH, pnlEntire, SLIDER_HORIZONTAL|SLIDER_SCROLLBAR )
scrVertical = CreateSlider(ClientWidth()-SCROLL_WIDTH,0,SCROLL_WIDTH,ClientHeight()-SCROLL_WIDTH, pnlEntire, SLIDER_VERTICAL|SLIDER_SCROLLBAR )
SetGadgetLayout(pnlViewport, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
SetGadgetLayout(pnlClientArea, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED, EDGE_CENTERED )
SetGadgetLayout(scrHorizontal, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_CENTERED, EDGE_ALIGNED )
SetGadgetLayout(scrVertical, EDGE_CENTERED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED )
HideGadget(scrHorizontal);HideGadget(scrVertical)
clientW = pnlViewport.ClientWidth();clientH = pnlViewport.ClientHeight()
ShowGadget(pnlEntire)
Return Self
EndMethod
Method New()
AddHook EmitEventHook,eventHandler,Self, 1
RemoveVerticalScroll();RemoveHorizontalScroll()
EndMethod
Method CleanUp()
RemoveHook EmitEventHook, eventHandler, Self
If pnlEntire Then HideGadget(pnlEntire);FreeGadget(pnlEntire)
EndMethod
Method eventHook:Object(pID%, pData:Object, pContext:Object)
Local tmpEvent:TEvent = TEvent(pData)
If tmpEvent = Null Then Return pData
Select tmpEvent.id
Case EVENT_WINDOWSIZE
If CheckParent(pnlEntire, TGadget(tmpEvent.source)) Then Update()
Case EVENT_GADGETACTION
Select tmpEvent.source
Case scrHorizontal;ShowRegion(SliderValue(scrHorizontal),oldV);pData = Null
Case scrVertical;ShowRegion(oldH,SliderValue(scrVertical));pData = Null
EndSelect
EndSelect
Return pData
EndMethod
Method ShowRegion(pHSlider%, pVSlider%)
Local tmpRelativeX% = oldH-pHSlider, tmpRelativeY% = oldV-pVSlider
oldH = pHSlider;oldV = pVSlider
SetGadgetShape(pnlClientArea,GadgetX(pnlClientArea)+tmpRelativeX,GadgetY(pnlClientArea)+tmpRelativeY,pnlViewport.ClientWidth()-(GadgetX(pnlClientArea)+tmpRelativeX),pnlViewport.ClientHeight()-(GadgetY(pnlClientArea)+tmpRelativeY))
EndMethod
Method SetShape(x,y,w,h)
Super.SetShape(x,y,w,h)
Update()
EndMethod
Method Update()
If Not pnlClientArea Then Return
Local tmpRelW% = (GadgetX(pnlClientArea)+GadgetWidth(pnlClientArea)-clientW)
Local tmpRelH% = (GadgetY(pnlClientArea)+GadgetHeight(pnlClientArea)-clientH)
If tmpRelW > 0 Or tmpRelW < SliderValue(scrHorizontal) Then tmpRelW = 0
If tmpRelH > 0 Or tmpRelH < SliderValue(scrVertical) Then tmpRelH = 0
ShowRegion( SliderValue(scrHorizontal)+tmpRelW, SliderValue(scrVertical)+tmpRelH )
clientW = pnlViewport.ClientWidth();clientH = pnlViewport.ClientHeight()
Local tmpLeft% = GadgetX(pnlClientArea), tmpRight%, tmpTop%=GadgetY(pnlClientArea), tmpBottom%
For Local tmpChild:TGadget = EachIn pnlClientArea.kids
'tmpLeft = Min(tmpLeft,GadgetX(tmpChild)+GadgetX(pnlClientArea))
tmpRight = Max(tmpRight,GadgetX(tmpChild)+GadgetWidth(tmpChild))
'tmpTop = Min(tmpTop,GadgetY(tmpChild)+GadgetY(pnlClientArea))
tmpBottom = Max(tmpBottom,GadgetY(tmpChild)+GadgetHeight(tmpChild))
Next
If tmpLeft < 0 Or tmpRight > pnlClientArea.ClientWidth() Then
AddHorizontalScroll(pnlClientArea.ClientWidth(),tmpLeft,tmpRight)
Else
RemoveHorizontalScroll()
EndIf
If tmpTop < 0 Or tmpBottom > pnlClientArea.ClientHeight() Then
AddVerticalScroll(pnlClientArea.ClientHeight(),tmpTop,tmpBottom)
Else
RemoveVerticalScroll()
EndIf
EndMethod
Method AddVerticalScroll(pVisible%, pTop%, pBottom%)
If scrVertical Then
SetGadgetShape(pnlViewport, 0, 0, ClientWidth() - SCROLL_WIDTH, GadgetHeight(pnlViewport))
SetGadgetShape(pnlClientArea, GadgetX(pnlClientArea), GadgetY(pnlClientArea), pnlViewport.ClientWidth() - GadgetX(pnlClientArea), pnlViewport.ClientHeight() - GadgetY(pnlClientArea))
SetGadgetShape(scrVertical, ClientWidth()-SCROLL_WIDTH, 0, SCROLL_WIDTH, GadgetHeight(pnlViewport))
SetSliderRange(scrVertical, pVisible, Max(pBottom-Min(0,pTop),pVisible));SetSliderValue(scrVertical,Max(-pTop,0));ShowGadget(scrVertical)
EndIf
EndMethod
Method RemoveVerticalScroll()
If scrVertical Then
SetGadgetShape(pnlViewport, 0, 0, ClientWidth(), GadgetHeight(pnlViewport))
SetGadgetShape(pnlClientArea, GadgetX(pnlClientArea), GadgetY(pnlClientArea), pnlViewport.ClientWidth() - GadgetX(pnlClientArea), pnlViewport.ClientHeight() - GadgetY(pnlClientArea))
HideGadget(scrVertical)
EndIf
EndMethod
Method AddHorizontalScroll(pVisible%, pLeft%, pRight%)
If scrHorizontal Then
SetGadgetShape(pnlViewport, 0, 0, GadgetWidth(pnlViewport), ClientHeight()-SCROLL_WIDTH )
SetGadgetShape(pnlClientArea, GadgetX(pnlClientArea), GadgetY(pnlClientArea), pnlViewport.ClientWidth() - GadgetX(pnlClientArea), pnlViewport.ClientHeight() - GadgetY(pnlClientArea))
SetGadgetShape(scrHorizontal, 0, ClientHeight()-SCROLL_WIDTH, GadgetWidth(pnlViewport), SCROLL_WIDTH)
SetSliderRange(scrHorizontal, pVisible, Max(pRight-Min(0,pLeft),pVisible));SetSliderValue(scrHorizontal,Max(-pLeft,0));ShowGadget(scrHorizontal)
EndIf
EndMethod
Method RemoveHorizontalScroll()
If scrHorizontal Then
SetGadgetShape(pnlViewport, 0, 0, GadgetWidth(pnlViewport), ClientHeight() )
SetGadgetShape(pnlClientArea, GadgetX(pnlClientArea), GadgetY(pnlClientArea), pnlViewport.ClientWidth() - GadgetX(pnlClientArea), pnlViewport.ClientHeight() - GadgetY(pnlClientArea))
HideGadget(scrHorizontal)
EndIf
EndMethod
Function eventHandler:Object(pID%, pData:Object, pContext:Object)
Local tmpSuperPanel:TScrollPanel = TScrollPanel(pContext)
If tmpSuperPanel Then pData = tmpSuperPanel.eventHook(pID%, pData:Object, pContext:Object)
Return pData
EndFunction
Function CheckParent%( pGadget:TGadget, pParentToCheck:TGadget )
If pGadget = pParentToCheck Then Return True
If pGadget.parent Then Return CheckParent(pGadget.parent, pParentToCheck)
EndFunction
EndType
Add gadgets to the panel returned by
ScrollPanelClient(), and call
UpdateScrollPanel() when you are finished to have the scrollbars update.
I have a nagging feeling that there is some strange behavior when resizing windows or it might have been with performance but you are welcome to have a play around and report back.
Have fun! ;-)