Scrollbar Behavior

From Directorforum Collaboration Wiki

Jump to: navigation, search

Contents

Description

A scroll bar behavior that emulates the scroll bar object found in the discontinued OSControls Xtra.

Director MX 2004, Director 11

Example


Files

Lingo

-- AstrO Controls :: Scrollbar
-- version 1.0b8-19Jun08
-- Created by Toby De Ieso
-- Modified by Toby De Ieso
 
 
-- Release Notes (1.0b8-19Jun08):
-- * Fixed scrollbar displaying enabled state on startup when linked to a member and
--   scrollMember.height is less than scrollMember.pageHeight
 
 
-- Release Notes (1.0b7-19Jun08):
-- * Fixed value becoming a negative in certain situations (caused display issues with #field members)
-- * Fixed an execution order bug which would send an update command before setting the scrollTop value
--   of a linked field/text member
-- * Up and down functions now scroll by line when a field/text member is selected 
--   (the amount of lines scrolled can be set by pScrollAmount)
 
 
property pSprite
property pMember
property pWidth
property pHeight
property pCurrentStates
property pImageMapMember
property pImage
property pUseScrollMember
property pMinBarHeight
property pActiveMap
property pMouseDown
property pScrollAmount
property pTimer
property pClickOffset
property pBackHeight
property pBarHeight
property pBackHeightOffset
 
property pObjectList
property pSizeList
property pStateList
 
property enabled
property groupId
property maxValue
property orientation
property scrollMember
property value
property viewSize
 
property pPointItem
property pRectOffset
property pQuadPositions
property pQuadOffset
 
 
on getPropertyDescriptionList me, descriptionList
  descriptionList = [:]
  descriptionList.addProp(#enabled, [#comment:"enabled",#format:#boolean,#default:TRUE])
  descriptionList.addProp(#orientation, [#comment:"orientation",#format:#symbol,#default:#vertical,#range:[#vertical,#horizontal]])
  descriptionList.addProp(#value, [#comment:"value",#format:#integer,#default:0])
  descriptionList.addProp(#maxValue, [#comment:"maxValue",#format:#integer,#default:100])
  descriptionList.addProp(#viewSize, [#comment:"viewSize",#format:#integer,#default:50])
  descriptionList.addProp(#scrollMember, [#comment:"scrollMember",#format:#member,#default:1])
  descriptionList.addProp(#pUseScrollMember, [#comment:"Use scrollMember",#format:#boolean,#default:FALSE])
  descriptionList.addProp(#pHeight, [#comment:"Height/Width",#format:#integer,#default:150])
  descriptionList.addProp(#pImageMapMember, [#comment:"ImageMapMember",#format:#bitmap,#default:1])
  descriptionList.addProp(#pScrollAmount, [#comment:"pScrollAmount",#format:#integer,#default:1])
  return descriptionList
end
 
 
on isOKToAttach me, tSpriteType, tSpriteNum
  tReturn = FALSE
  if sprite(tSpriteNum).member.type = #bitmap then tReturn = TRUE
  return tReturn
end
 
 
on beginSprite me
  pSprite = sprite(me.spriteNum)
  pMember = pSprite.member
  pMinBarHeight = 16
  pBackHeight = 0
  pBarHeight = 0
  pBackHeightOffset = 0
  pWidth = 16
  pCurrentStates = [#up:#normal,#down:#normal,#bar:#normal,#background:#normal]
  pMouseDown = #none
  pTimer = 0
  pClickOffset = 0
 
  pPointItem = [#horizontal:1,#vertical:2]
  pQuadPositions = [[1,2],[3,2],[3,4],[1,4]]
  pRectOffset = [1,2,3,4]
  pQuadOffset = [1,2,3,4]
 
  groupId = 0
 
  pObjectList = [:]
  pObjectList.addProp(#up,rect(0, 0, 16, 16))
  pObjectList.addProp(#bar_top,rect(0, 16, 16, 20))
  pObjectList.addProp(#bar, rect(0, 20, 16, 36))
  pObjectList.addProp(#bar_bottom,rect(0, 36, 16, 40))
  pObjectList.addProp(#bar_overlay,rect(0, 40, 16, 56))
  pObjectList.addProp(#background,rect(0, 56, 16, 72))
  pObjectList.addProp(#down,rect(0, 72, 16, 88))
 
  pSizeList = [:]
  repeat with i = 1 to pObjectList.count
    pSizeList.addProp(pObjectList.getPropAt(i),rect(0,0,pObjectList[i].width,pObjectList[i].height))
  end repeat
 
  pStateList = [#normal:0,#over:0,#down:0,#disabled:0]
  repeat with i = 1 to pStateList.count
    pStateList[i] = rect(point((i - 1) * pWidth,0),point((i - 1) * pWidth,0))
  end repeat
 
  if pUseScrollMember then
    if scrollMember.height > scrollMember.pageHeight then
      scrollMember.scrollTop = value
      maxValue = scrollMember.height
      viewSize = scrollMember.pageHeight
    else
      enabled = FALSE
    end if
  end if
 
  me.resetControl()
end
 
 
on resetControl(me)
  if orientation = #vertical then
    pRectOffset = [1,2,3,4]
    pQuadOffset = [1,2,3,4]
    pImage = image(pWidth,pHeight,32)
  else
    pRectOffset = [2,1,4,3]
    pQuadOffset = [1,4,3,2]
    pImage = image(pHeight,pWidth,32)
  end if
 
  pActiveMap = [:]
  pActiveMap.addProp(#up,me.remapRect(pSizeList.up))
  pActiveMap.addProp(#down,me.remapRect(pSizeList.down + rect(0,pHeight - pSizeList.down.height,0,pHeight - pSizeList.down.height)))
  pActiveMap.addProp(#bar,rect(0,0,0,0))
  pActiveMap.addProp(#background,me.remapRect(rect(0,pSizeList.up.height,pWidth,pHeight - pSizeList.down.height)))
 
  me.updateDisplay()
end
 
 
on remapRect(me,tRect)
  tRect = rect(tRect[pRectOffset[1]],tRect[pRectOffset[2]],tRect[pRectOffset[3]],tRect[pRectOffset[4]])
  return tRect
end
 
 
on createQuad(me,tRect)
  tQuad = []
  repeat with i = 1 to 4
    tQuad.append( point(tRect[pQuadPositions[pQuadOffset[i]][1]],tRect[pQuadPositions[pQuadOffset[i]][2]]) )
  end repeat
  return tQuad
end
 
 
on updateDisplay(me)
  if enabled then
    -- Copy Background then Up and Down buttons
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.background), pObjectList.background + pStateList[pCurrentStates.background])
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.up), pObjectList.up + pStateList[pCurrentStates.up])
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.down), pObjectList.down + pStateList[pCurrentStates.down])
 
    -- Copy bar/slider
    me.calculateBar()
    tBarLoc = (pBackHeight * (value/maxValue.float)).integer + pSizeList.up.height - (pBackHeightOffset * (value/maxValue.float)).integer
    tBarLoc = rect(0,tBarLoc,0,tBarLoc)
 
    pActiveMap.bar = me.remapRect(tBarLoc + rect(0,0,pWidth,pBarHeight))
    tOverLayOffset = ((pBarHeight / 2.0) - (pSizeList.bar_overlay.height / 2.0)).integer
 
    pImage.copyPixels(pImageMapMember.image, me.createQuad(me.remapRect(tBarLoc + rect(0,pSizeList.bar_top.height,pWidth,pBarHeight - pSizeList.bar_bottom.height))), pObjectList.bar + pStateList[pCurrentStates.bar])
    pImage.copyPixels(pImageMapMember.image, me.createQuad(me.remapRect(tBarLoc + pSizeList.bar_top)),pObjectList.bar_top + pStateList[pCurrentStates.bar])
    pImage.copyPixels(pImageMapMember.image, me.createQuad(me.remapRect(tBarLoc + pSizeList.bar_bottom + rect(0,pBarHeight - pSizeList.bar_bottom.height,0,pBarHeight - pSizeList.bar_bottom.height))), pObjectList.bar_bottom + pStateList[pCurrentStates.bar])
    pImage.copyPixels(pImageMapMember.image, me.createQuad(me.remapRect(tBarLoc + rect(0,tOverLayOffset,0,tOverLayOffset) + pSizeList.bar_overlay)),pObjectList.bar_overlay + pStateList[pCurrentStates.bar])
  else
    -- Quick draw for disabled scrollbar    
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.background), pObjectList.background + pStateList.disabled)
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.up), pObjectList.up + pStateList.disabled)
    pImage.copyPixels(pImageMapMember.image, me.createQuad(pActiveMap.down), pObjectList.down + pStateList.disabled)
  end if
 
  pMember.image = pImage.duplicate()
  pMember.regPoint = point(0,0)
end
 
 
on checkMouse(me,tLoc,tIgnoreList)
  tFound = #none
  repeat with i = 1 to pActiveMap.count
    if tIgnoreList.getPos(pActiveMap.getPropAt(i)) = 0 then
      if tLoc.inside(pActiveMap[i]) then
        tFound = pActiveMap.getPropAt(i)
        exit repeat
      end if
    end if
  end repeat
  return tFound
end
 
 
on calculateBar(me)
  pBackHeight = pHeight - (pSizeList.up.height + pSizeList.down.height)
  tRealHeight = (pBackHeight * (viewSize/maxValue.float)).integer
  pBarHeight = max( pMinBarHeight, tRealHeight )
  pBackHeightOffset = pBarHeight - tRealHeight
end
 
 
on activateButton(me,tButton,tState)
  pCurrentStates = [#up:#normal,#down:#normal,#bar:#normal,#background:#normal]
  case pMouseDown of
    #up,#down,#bar: pCurrentStates[pMouseDown] = #down
    #background: nothing
    otherwise: if tButton <> #none then pCurrentStates[tButton] = tState
  end case
end
 
 
on updateValue(me,tSection)
  if voidP(tSection) then tSection = pMouseDown
  value = min(max(0,maxValue - viewSize),max(0,value.integer))
  if pUseScrollMember then
    case tSection of
      #up:
        scrollMember.scrollbyline(-pScrollAmount)
        value = scrollMember.scrollTop
      #down:
        scrollMember.scrollbyline(pScrollAmount)
        value = scrollMember.scrollTop
      otherwise:
        if scrollMember.scrollTop <> value then scrollMember.scrollTop = value
    end case
  end if
end
 
 
on runScrollButtons(me,tDelay)
  tOldValue = value
  tUpdate = #none
  case pMouseDown of
    #up:
      value = value - pScrollAmount
      tUpdate = #up
      pTimer = _system.milliseconds + tDelay
    #down:
      value = value + pScrollAmount
      tUpdate = #down
      pTimer = _system.milliseconds + tDelay
    #background:
      tLoc = _mouse.mouseLoc - pSprite.loc
      if not(tLoc.inside(pActiveMap.bar)) and tLoc.inside(pActiveMap.background) then
        tBarLoc = (pBackHeight * (value/maxValue.float)).integer + pSizeList.up.height - (pBackHeightOffset * (value/maxValue.float)).integer
        if tBarLoc > (_mouse.mouseLoc[pPointItem[orientation]] - (pSprite.loc[pPointItem[orientation]] + pSizeList.up.height)) then
          value = value - viewSize
          tUpdate = #pageUp
        else
          value = value + viewSize
          tUpdate = #pageDown
        end if
        pTimer = _system.milliseconds + tDelay
      end if
    #bar:
      me.calculateBar()
      tLocY = (_mouse.mouseLoc[pPointItem[orientation]] - pClickOffset) - (pSprite.loc[pPointItem[orientation]] + pSizeList.up.height)
      tLocY = tLocY + ((tLocY / pBackHeight.float) * pBackHeightOffset)
      value = ((tLocY / pBackHeight.float) * maxValue).integer
      tUpdate = #thumb
  end case
  me.updateValue()
  if value <> tOldValue then
    if tUpdate <> #none then _movie.sendSprite(me.spriteNum,#update,tUpdate)
  end if
end
 
 
on click(me,tSection)
  case tSection of
    #up: value = value - pScrollAmount
    #down: value = value + pScrollAmount
    #pageUp: value = value - viewSize
    #pageDown: value = value + viewSize
  end case
  me.updateValue(tSection)
  me.updateDisplay()
end
 
 
on setGroupProp(me,tProperty,tValue)
  trace("Sorry but this method is not working")
end
 
 
on showProps(me)
  trace("Sorry but this method is not working")
end
 
 
on enterFrame me
  if pUseScrollMember then
    if value <> scrollMember.scrollTop then value = scrollMember.scrollTop
    if maxValue <> scrollMember.height then maxValue = scrollMember.height
    if viewSize <> scrollMember.pageHeight then viewSize = scrollMember.pageHeight
    enabled = (maxValue > viewSize)
  end if
 
  if (_system.milliseconds > pTimer) or (pMouseDown = #bar) then me.runScrollButtons(33)
  tButton = me.checkMouse(_mouse.mouseLoc - pSprite.loc,[#background])
  me.activateButton(tButton,[#over,#down][_mouse.stillDown + 1])
  me.updateDisplay()
end
 
 
on mouseDown me
  pMouseDown =  me.checkMouse(_mouse.mouseLoc - pSprite.loc,[])
  pClickOffset = _mouse.mouseLoc[pPointItem[orientation]] - (pSprite.loc[pPointItem[orientation]] + pActiveMap.bar[pPointItem[orientation]])
  me.runScrollButtons(250)
end
 
 
on mouseUp me
  pMouseDown = #none
end
 
 
on mouseUpOutside me
  pMouseDown = #none
end
Personal tools