home *** CD-ROM | disk | FTP | other *** search
/ MacFormat UK 163 - Disc 1 / MF_UK_163_1.iso / pc / Files / Scenes / HOME.DIR / Internal_93_Custom Scrollbar.ls < prev    next >
Encoding:
Text File  |  2005-10-20  |  21.9 KB  |  636 lines

  1. property spriteNum, getPDLError, ourScrolledElement, myScrollRole, myActiveMember, myStandardMember, myMultiThreading, mySprite, myMember, myRect, myScrolledSprite, myScrolledMember, myActiveZone, myState, myNextUpdate, myZeroLoc, myDraggerShift, myClickV, myInterimShift, myMaxDraggerShift, myPageScroll, ourControlList, ourMaxScroll
  2.  
  3. on getBehaviorDescription me
  4.   return "CUSTOM SCROLL BAR" & RETURN & RETURN & "Create dynamic scrollbars with your own artwork. " & " Such scrollbars are not Direct-To-Stage, so other sprites can appear over the top of them." & RETURN & RETURN & "You will need to create four graphic members:" & RETURN & "+ up arrow" & RETURN & "+ down arrow" & RETURN & "+ dragger" & RETURN & "+ backing bar" & RETURN & RETURN & "You may wish to use two additional members, to indicate that the arrow buttons have been pressed:" & RETURN & "+ up arrow (pressed state)" & RETURN & "+ down arrow (pressed state)" & RETURN & RETURN & "Place the four standard members on the Stage, and drop this behavior onto each of them. " & " Choose how the current sprite is to act in the appropriate pop-up menu in the Behavior Parameters dialog." & RETURN & RETURN & "For each element you can choose whether animations should continue in the background. " & " This option will tend to slow both the animations and the scrolling process, especially if applied to the arrow buttons." & RETURN & RETURN & "The various sprites will position themselves automatically to the right of the sprite-to-be-scrolled when the movie runs. " & " They revert to their original positions when it stops. " & " To avoid flashes, it would be a good idea to position them by hand in their intended positions." & RETURN & RETURN & "If you use a border on your field members, the scrollbar will sit outside the border. " & " Field box shadows are not recommended. " & " You can always fake external borders and box shadows with shape members (this even gives you a choice of colors)." & RETURN & RETURN & "To make authoring easier, this behavior will continue to work if you change EITHER the sprite channel OR the member in the chosen channel. " & " If you change both, the behavior will no longer know what to scroll." & RETURN & RETURN & "If you do change either the sprite or the member, and then reopen the Behavior Parameters dialog for one of the elements, this will put that behavior out of synch with the others. " & " Simply reopen and close the Parameters dialogs for each of the other elements. " & " If you do not do so, you will receive multiple alerts." & RETURN & RETURN & "This behavior can be used to scroll both editable and non-editable Fields and Text members. " & " For editable members, however, it does not automatically update the dragger position when the length of the text changes, nor does it make the editable member scroll automatically when the user drags the mouse to create a selection." & RETURN & RETURN & "PERMITTED MEMBER TYPES:" & RETURN & "[#animGif, #bitmap, #filmLoop, #flash, #movie, #picture, #shape]" & RETURN & RETURN & "PARAMETERS:" & RETURN & "* Current sprite acts as (up|down arrow | dragger | bar)" & RETURN & "* Scroll the member of <sprite>: <the member of sprite>" & RETURN & "* Standard member (this should not need to be set)" & RETURN & "* Member to display when arrow buttons are pressed" & RETURN & "* Allow animations to continue" & RETURN & RETURN & "PUBLIC METHODS" & RETURN & "=> Scroll the text/field member to a given position" & RETURN & "=> Swap the text/field  member to be scrolled" & RETURN & "=> Get the behavior reference"
  5. end
  6.  
  7. on getBehaviorTooltip me
  8.   return "Use 4 graphic members (dragger, bar, up and down arrows)to create a dynamic scrollbar for Text or Field members." & RETURN & RETURN & "Drop this behavior on each sprite separately." & RETURN & RETURN & "Sprites can pass over the scrollbar and animations can continue while the user scrolls." & RETURN & RETURN & "The behavior accepts Lingo calls to:" & RETURN & "+ set the scrolltop of the scrolled member to a given value." & RETURN & "+ swap the current member of the sprite."
  9. end
  10.  
  11. on resolve prop
  12.   case prop of
  13.     myScrollRole:
  14.       choiceslist = ["upArrow", "downArrow", "dragger", "bar"]
  15.       lookup = [#upArrow, #downArrow, #dragger, #bar]
  16.     otherwise:
  17.       nothing()
  18.   end case
  19.   return lookup[findPos(choiceslist, prop)]
  20. end
  21.  
  22. on beginSprite me
  23.   myScrollRole = resolve(myScrollRole)
  24.   StartInstallation(me)
  25. end
  26.  
  27. on prepareFrame me
  28.   if not myState + 0 then
  29.     FinishInstallation(me)
  30.   end if
  31.   if myMultiThreading then
  32.     UpdateScroll(me)
  33.   end if
  34. end
  35.  
  36. on mouseDown me
  37.   StartScroll(me)
  38. end
  39.  
  40. on mouseUp me
  41.   EndScroll(me)
  42. end
  43.  
  44. on mouseUpOutSide me
  45.   EndScroll(me)
  46. end
  47.  
  48. on StartInstallation me
  49.   mySprite = sprite(me.spriteNum)
  50.   myMember = mySprite.member
  51.   memberType = myMember.type
  52.   if voidp(myScrollRole) then
  53.     ErrorAlert(me, #getPDL_Invalid)
  54.   end if
  55.   myScrolledSprite = value(ourScrolledElement)
  56.   myScrolledMember = myScrolledSprite.member
  57.   memberType = myScrolledMember.type
  58.   case memberType of
  59.     #field, #text:
  60.     otherwise:
  61.       FindSprite(me)
  62.   end case
  63.   topLeft = point(myScrolledSprite.left, myScrolledSprite.top)
  64.   myRect = myScrolledSprite.rect - rect(topLeft, topLeft)
  65.   if memberType = #field then
  66.     if myScrolledMember.border then
  67.       myRect[1] = 1
  68.     end if
  69.   end if
  70.   ourMaxScroll = []
  71.   ourControlList = [:]
  72.   sendAllSprites(#CustomScrollbar_RollCall, ourScrolledElement, ourControlList, ourMaxScroll)
  73.   myState = 0
  74. end
  75.  
  76. on FindSprite me
  77.   saveDelimiter = the itemDelimiter
  78.   the itemDelimiter = ":"
  79.   memberData = ourScrolledElement.item[2]
  80.   the itemDelimiter = saveDelimiter
  81.   delete memberData.word[1]
  82.   delete memberData.char[1]
  83.   memberData = value(memberData)
  84.   myScrolledMember = member(memberData)
  85.   scrollSprite = the lastChannel
  86.   repeat while scrollSprite
  87.     if sprite(scrollSprite).member = myScrolledMember then
  88.       myScrolledSprite = sprite(scrollSprite)
  89.       exit
  90.     end if
  91.     scrollSprite = scrollSprite - 1
  92.   end repeat
  93.   if not scrollSprite then
  94.     ErrorAlert(me, #notScrollable, myScrolledSprite.member.type)
  95.   end if
  96. end
  97.  
  98. on FinishInstallation me
  99.   CheckControlList(me)
  100.   InstallElement(me)
  101. end
  102.  
  103. on CheckControlList me
  104.   checkList = duplicate(ourControlList)
  105.   roleList = [#upArrow, #downArrow, #dragger, #bar]
  106.   i = roleList.count()
  107.   repeat while i
  108.     theRole = roleList[i]
  109.     rolePosition = checkList.findPos(theRole)
  110.     if rolePosition then
  111.       roleList.deleteAt(i)
  112.       checkList.deleteAt(rolePosition)
  113.     end if
  114.     i = i - 1
  115.   end repeat
  116.   if checkList.count() then
  117.     ErrorAlert(me, #extraControl, checkList.getPropAt(1))
  118.   end if
  119.   if roleList.count() then
  120.     ErrorAlert(me, #missingControls, roleList)
  121.   end if
  122. end
  123.  
  124. on InstallElement me
  125.   scrollRoof = myScrolledSprite.top
  126.   scrollFloor = myScrolledSprite.bottom
  127.   scrollLeft = myScrolledSprite.right
  128.   if myScrolledMember.type = #field then
  129.     scrollLeft = scrollLeft - (myScrolledMember.border <> 0)
  130.   end if
  131.   case myScrollRole of
  132.     #upArrow:
  133.       mySprite.loc = point(scrollLeft, scrollRoof) + myMember.regPoint
  134.       myActiveZone = mySprite.rect
  135.     #downArrow:
  136.       locAdjust = myMember.regPoint - [0, mySprite.height]
  137.       rectAdjust = mySprite.rect - rect(mySprite.loc, mySprite.loc)
  138.       mySprite.loc = point(scrollLeft, scrollFloor) + locAdjust
  139.       myActiveZone = rectAdjust + rect(mySprite.loc, mySprite.loc)
  140.     #bar:
  141.       barRoof = scrollRoof + call(#SpriteHeight, ourControlList.upArrow)
  142.       barRight = scrollLeft + call(#spriteWIdth, ourControlList.upArrow)
  143.       barFloor = scrollFloor - call(#SpriteHeight, ourControlList.downArrow)
  144.       mySprite.rect = rect(scrollLeft, barRoof, barRight, barFloor)
  145.     #dragger:
  146.       case myMember.type of
  147.         #vectorShape:
  148.           regOffset = (myMember.strokeWidth + 1) / 2
  149.           myMember.regPoint = point(regOffset, regOffset)
  150.         otherwise:
  151.           myMember.regPoint = point(0, 0)
  152.       end case
  153.       upHeight = call(#SpriteHeight, ourControlList.upArrow)
  154.       upWidth = call(#SpriteHeight, ourControlList.upArrow)
  155.       downHeight = call(#SpriteHeight, ourControlList.downArrow)
  156.       draggerRoof = scrollRoof + upHeight
  157.       myZeroLoc = point(scrollLeft, draggerRoof)
  158.       barRight = scrollLeft + upWidth
  159.       myActiveZone = rect(scrollLeft, scrollRoof, barRight, scrollFloor)
  160.       myActiveZone = inflate(myActiveZone, 32, 32)
  161.       arrowAdjust = upHeight + downHeight
  162.       pageHeight = myScrolledSprite.height
  163.       scrollHeight = pageHeight - arrowAdjust
  164.       draggerHeight = mySprite.height
  165.       myMaxDraggerShift = 0
  166.       if scrollHeight < 0 then
  167.         minRect = myScrolledMember.rect
  168.         minRect[4] = arrowAdjust
  169.         myScrolledMember.rect = minRect
  170.         call(#InstallElement, ourControlList.bar)
  171.       end if
  172.       if scrollHeight < draggerHeight then
  173.         mySprite.loc = point(-999, -999)
  174.       else
  175.         if myScrolledMember.type = #field then
  176.           theMargin = myScrolledMember.margin
  177.           theMargin = theMargin - (theMargin mod 2)
  178.           borderAdjust = (myScrolledMember.border * 2) + theMargin
  179.         else
  180.           borderAdjust = 0
  181.         end if
  182.         myMaxDraggerShift = scrollHeight - draggerHeight + borderAdjust
  183.       end if
  184.       ourMaxScroll[1] = GetMaxScroll(me)
  185.       SetDraggerShift(me)
  186.   end case
  187.   myState = #done
  188. end
  189.  
  190. on GetMaxScroll me
  191.   pageHeight = myScrolledSprite.height
  192.   if myScrolledMember.type = #text then
  193.     lastChar = myScrolledMember.char.count
  194.     textHeight = charPosToLoc(myScrolledMember, lastChar)[2]
  195.   else
  196.     textHeight = myScrolledMember.height
  197.   end if
  198.   maxScroll = textHeight - pageHeight
  199.   if maxScroll < 1 then
  200.     return 0
  201.   else
  202.     return maxScroll
  203.   end if
  204. end
  205.  
  206. on StartScroll me
  207.   myState = #Active
  208.   ourMaxScroll[1] = GetMaxScroll(me)
  209.   case myScrollRole of
  210.     #dragger:
  211.       myClickV = (the clickLoc)[2]
  212.       myInterimShift = 0
  213.     #upArrow, #downArrow:
  214.       mySprite.member = myActiveMember
  215.     #bar:
  216.       draggerData = call(#GetDraggerData, ourControlList.dragger)
  217.       if (the clickLoc)[2] < draggerData.top then
  218.         myActiveZone = GetBarZone(me, draggerData, #up)
  219.       else
  220.         myActiveZone = GetBarZone(me, draggerData, #down)
  221.       end if
  222.   end case
  223.   UpdateScroll(me)
  224.   if myMultiThreading then
  225.     exit
  226.   end if
  227.   repeat while the mouseDown
  228.     UpdateScroll(me)
  229.   end repeat
  230. end
  231.  
  232. on UpdateScroll me
  233.   case myState of
  234.     #Active:
  235.       if inside(the mouseLoc, myActiveZone) then
  236.         case myScrollRole of
  237.           #dragger:
  238.             MoveDragger(me)
  239.           #upArrow:
  240.             move(me, 1)
  241.           #downArrow:
  242.             move(me, 0)
  243.           #bar:
  244.             MoveBar(me)
  245.         end case
  246.       else
  247.         PauseScroll(me)
  248.       end if
  249.     #paused:
  250.       ResumeScroll(me)
  251.   end case
  252. end
  253.  
  254. on GetBarZone me, draggerData, pageScroll
  255.   if not voidp(pageScroll) then
  256.     myPageScroll = pageScroll
  257.   end if
  258.   barZone = mySprite.rect
  259.   if myPageScroll = #up then
  260.     barZone[2] = myScrolledSprite.top
  261.     barZone[4] = draggerData.top
  262.   else
  263.     barZone[2] = draggerData.bottom
  264.     barZone[4] = myScrolledSprite.bottom
  265.   end if
  266.   return barZone
  267. end
  268.  
  269. on MoveDragger me
  270.   newScroll = myDraggerShift + the mouseV - myClickV
  271.   newScroll = max(0, min(newScroll, myMaxDraggerShift))
  272.   if myInterimShift = newScroll then
  273.     exit
  274.   end if
  275.   myInterimShift = newScroll
  276.   SetTextScroll(me, myInterimShift)
  277. end
  278.  
  279. on move me, up
  280.   if the ticks < myNextUpdate then
  281.     exit
  282.   end if
  283.   if voidp(myNextUpdate) then
  284.     myNextUpdate = the ticks + 10
  285.   else
  286.     myNextUpdate = the ticks + 1
  287.   end if
  288.   if up then
  289.     if not myScrolledMember.scrollTop then
  290.       exit
  291.     end if
  292.     scrollByLine(myScrolledMember, -1)
  293.   else
  294.     maxScroll = ourMaxScroll[1]
  295.     if myScrolledMember.scrollTop = maxScroll then
  296.       exit
  297.     end if
  298.     scrollByLine(myScrolledMember, 1)
  299.     if myScrolledMember.scrollTop > maxScroll then
  300.       myScrolledMember.scrollTop = maxScroll
  301.     end if
  302.   end if
  303.   call(#SetDraggerShift, ourControlList.dragger)
  304. end
  305.  
  306. on MoveBar me, up
  307.   if the ticks < myNextUpdate then
  308.     exit
  309.   end if
  310.   myNextUpdate = the ticks + 10
  311.   if myPageScroll = #up then
  312.     scrollByPage(myScrolledMember, -1)
  313.     if myScrolledMember.scrollTop then
  314.       scrollByLine(myScrolledMember, 1)
  315.     end if
  316.   else
  317.     maxScroll = ourMaxScroll[1]
  318.     if myScrolledMember.scrollTop = maxScroll then
  319.       exit
  320.     end if
  321.     scrollByPage(myScrolledMember, 1)
  322.     scrollByLine(myScrolledMember, -1)
  323.     if myScrolledMember.scrollTop > maxScroll then
  324.       myScrolledMember.scrollTop = maxScroll
  325.     end if
  326.   end if
  327.   call(#SetDraggerShift, ourControlList.dragger)
  328.   draggerData = call(#GetDraggerData, ourControlList.dragger)
  329.   myActiveZone = GetBarZone(me, draggerData)
  330. end
  331.  
  332. on PauseScroll me
  333.   myState = #paused
  334.   case myScrollRole of
  335.     #dragger:
  336.       SetTextScroll(me, myDraggerShift)
  337.     #upArrow, #downArrow:
  338.       mySprite.member = myStandardMember
  339.       if not myMultiThreading then
  340.         updateStage()
  341.       end if
  342.   end case
  343. end
  344.  
  345. on ResumeScroll me
  346.   myState = #Active
  347.   case myScrollRole of
  348.     #upArrow, #downArrow:
  349.       mySprite.member = myActiveMember
  350.   end case
  351.   UpdateScroll(me)
  352. end
  353.  
  354. on EndScroll me
  355.   case myScrollRole of
  356.     #dragger:
  357.       if not voidp(myInterimShift) then
  358.         if ourMaxScroll[1] then
  359.           myDraggerShift = myInterimShift
  360.         else
  361.           myDraggerShift = 0
  362.           ShiftDragger(me, myDraggerShift)
  363.         end if
  364.       end if
  365.       myInterimShift = VOID
  366.     #upArrow, #downArrow:
  367.       mySprite.member = myStandardMember
  368.       myNextUpdate = VOID
  369.   end case
  370.   myState = #done
  371. end
  372.  
  373. on SetTextScroll me, draggerShift
  374.   if ourMaxScroll[1] then
  375.     textScroll = draggerShift * ourMaxScroll[1] / myMaxDraggerShift
  376.     myScrolledMember.scrollTop = textScroll
  377.   else
  378.   end if
  379.   ShiftDragger(me, draggerShift)
  380. end
  381.  
  382. on SetDraggerShift me
  383.   maxScroll = ourMaxScroll[1]
  384.   if maxScroll then
  385.     textScroll = myScrolledMember.scrollTop
  386.     myDraggerShift = textScroll * myMaxDraggerShift / maxScroll
  387.   else
  388.     myDraggerShift = 0
  389.   end if
  390.   ShiftDragger(me, myDraggerShift)
  391. end
  392.  
  393. on ShiftDragger me, draggerShift
  394.   if not myMaxDraggerShift then
  395.     exit
  396.   end if
  397.   mySprite.loc = myZeroLoc + [0, draggerShift]
  398.   updateStage()
  399. end
  400.  
  401. on CustomScrollbar_SetScroll me, theScroll
  402.   case ilk(theScroll) of
  403.     #integer:
  404.     #float:
  405.       theScroll = integer(theScroll)
  406.     otherwise:
  407.       return #invalidTypeError
  408.   end case
  409.   theScroll = max(0, min(theScroll, ourMaxScroll[1]))
  410.   myScrolledMember.scrollTop = theScroll
  411.   call(#SetDraggerShift, ourControlList.dragger, theScroll)
  412. end
  413.  
  414. on CustomScrollbar_SwapMember me, newMember, currentMemberOrSprite
  415.   case ilk(newMember) of
  416.     #member:
  417.     #integer, #string:
  418.       memberExists = the number of member newMember > 0
  419.       if memberExists then
  420.         newMember = member(newMember)
  421.       else
  422.         return #memberInexistant
  423.       end if
  424.     otherwise:
  425.       return #invalidType
  426.   end case
  427.   case newMember.type of
  428.     #text, #field:
  429.     otherwise:
  430.       return #invalidMemberType
  431.   end case
  432.   case ilk(currentMemberOrSprite) of
  433.     #sprite:
  434.       if currentMemberOrSprite <> myScrolledSprite then
  435.         exit
  436.       end if
  437.     #member:
  438.       if currentMemberOrSprite <> myScrolledMember then
  439.         exit
  440.       end if
  441.   end case
  442.   myScrolledMember = newMember
  443.   idealRect = myRect
  444.   if myScrolledMember.type = #field then
  445.     hBorder = myScrolledMember.border
  446.     vBorder = hBorder - (hBorder <> 0)
  447.     hMargin = myScrolledMember.margin
  448.     vMargin = hMargin / 2
  449.     idealRect = inflate(idealRect, -hBorder - hMargin, -hBorder - vMargin)
  450.     if myRect[1] then
  451.       if hBorder then
  452.         idealRect[1] = idealRect[1] - 1
  453.       end if
  454.     else
  455.       if hBorder then
  456.         idealRect[1] = idealRect[1] - 1
  457.       end if
  458.     end if
  459.   end if
  460.   myScrolledMember.rect = idealRect
  461.   myScrolledSprite.member = myScrolledMember
  462.   myScrolledMember.boxType = #fixed
  463.   i = ourControlList.count()
  464.   repeat while i
  465.     call(#newMember, ourControlList[i])
  466.     i = i - 1
  467.   end repeat
  468.   updateStage()
  469.   call(#InstallElement, ourControlList.dragger)
  470. end
  471.  
  472. on CustomScrollbar_GetReference me, memberOrSprite, controlOrList
  473.   case ilk(memberOrSprite) of
  474.     #sprite:
  475.       if memberOrSprite <> myScrolledSprite then
  476.         exit
  477.       end if
  478.     #member:
  479.       if memberOrSprite <> myScrolledMember then
  480.         exit
  481.       end if
  482.     otherwise:
  483.       exit
  484.   end case
  485.   if not voidp(controlOrList) then
  486.     if ilk(controlOrList) = #propList then
  487.       controlOrList.addProp(myScrollRole, me)
  488.       return controlOrList
  489.     else
  490.       if controlOrList = myScrollRole then
  491.         return me
  492.       end if
  493.     end if
  494.   else
  495.     return me
  496.   end if
  497. end
  498.  
  499. on CustomScrollbar_RollCall me, scrolledElement, controlList, maxScrollList
  500.   if scrolledElement <> ourScrolledElement then
  501.     exit
  502.   end if
  503.   ourControlList = controlList
  504.   ourControlList.addProp(myScrollRole, me)
  505.   ourMaxScroll = maxScrollList
  506. end
  507.  
  508. on SpriteHeight me
  509.   return mySprite.height
  510. end
  511.  
  512. on spriteWIdth me
  513.   return mySprite.width
  514. end
  515.  
  516. on GetDraggerData me
  517.   return [#top: mySprite.top, #bottom: mySprite.bottom]
  518. end
  519.  
  520. on newMember me
  521.   myScrolledMember = myScrolledSprite.member
  522. end
  523.  
  524. on ErrorAlert me, theError, data
  525.   case theError of
  526.     #noScrollableSprites:
  527.       alert("Error: Please place a Field or Text member on the Stage before using this behavior to create a scroll bar." & RETURN & "      " & RETURN & "Hit OK and then delete this behavior from the sprite." & RETURN & "      " & RETURN & "For more information on deleting Behaviors, see the Help system.")
  528.     otherwise:
  529.       behaviorName = string(me)
  530.       delete word 1 of behaviorName
  531.       delete char -30001 of behaviorName
  532.       delete char -30001 of behaviorName
  533.       case data.ilk of
  534.         #void:
  535.           data = "<void>"
  536.         #symbol:
  537.           data = "#" & data
  538.       end case
  539.       if theError <> #getPDL_Invalid then
  540.         memberName = myScrolledMember.name
  541.         if memberName = EMPTY then
  542.           memberName = myScrolledMember
  543.         else
  544.           memberName = QUOTE & memberName & QUOTE
  545.         end if
  546.         memberName = myScrolledMember.type && memberName
  547.       end if
  548.       case theError of
  549.         #getPDL_Invalid:
  550.           message = substituteStrings(me, "BEHAVIOR ERROR: Frame ^0, Sprite ^1" & RETURN & "          " & RETURN & "Parameters for the ^2 behavior have not been set." & RETURN & "          " & RETURN & "Please reopen the Behavior Parameters dialog and choose again.", ["^0": the frame, "^1": me.spriteNum, "^2": behaviorName])
  551.           alert(message)
  552.           halt()
  553.         #notScrollable:
  554.           message = substituteStrings(me, "BEHAVIOR ERROR: Frame ^0, Sprite ^1" & RETURN & "Behavior ^2" & RETURN & "          " & RETURN & "Sprite ^3 does not contain a Field or Text member." & RETURN & RETURN & "Choose again in the Behavior Parameters dialog." & RETURN & RETURN & "Member type = ^4", ["^0": the frame, "^1": me.spriteNum, "^2": behaviorName, "^3": myScrolledSprite.spriteNum, "^4": data])
  555.           alert(message)
  556.           halt()
  557.         #extraControl:
  558.           if the runMode = "Author" then
  559.             message = substituteStrings(me, "BEHAVIOR ERROR: Frame ^0, Sprite ^1" & RETURN & "Behavior ^2" & RETURN & "          " & RETURN & "There is more than one ^3 sprite defined for the scroll bar for sprite ^4, ^5.", ["^0": the frame, "^1": me.spriteNum, "^2": behaviorName, "^3": data, "^4": myScrolledSprite.spriteNum, "^5": memberName])
  560.             alert(message)
  561.             halt()
  562.           end if
  563.         #missingControls:
  564.           message = substituteStrings(me, "BEHAVIOR ERROR: Frame ^0, Sprite ^1" & RETURN & "Behavior ^2" & RETURN & "          " & RETURN & "The following elements of the scroll bar for sprite ^3, ^4 are missing:" & RETURN & "          " & RETURN & "^5", ["^0": the frame, "^1": me.spriteNum, "^2": behaviorName, "^3": myScrolledSprite.spriteNum, "^4": memberName, "^5": data])
  565.           alert(message)
  566.           halt()
  567.       end case
  568.   end case
  569. end
  570.  
  571. on substituteStrings me, parentString, childStringList
  572.   i = childStringList.count()
  573.   repeat while i
  574.     tempString = EMPTY
  575.     dummyString = childStringList.getPropAt(i)
  576.     replacement = childStringList[i]
  577.     lengthAdjust = dummyString.char.count - 1
  578.     repeat while 1
  579.       position = offset(dummyString, parentString)
  580.       if not position then
  581.         parentString = tempString & parentString
  582.         exit repeat
  583.         next repeat
  584.       end if
  585.       if position <> 1 then
  586.         tempString = tempString & parentString.char[1..position - 1]
  587.       end if
  588.       tempString = tempString & replacement
  589.       delete parentString.char[1..position + lengthAdjust]
  590.     end repeat
  591.     i = i - 1
  592.   end repeat
  593.   return parentString
  594. end
  595.  
  596. on isOKToAttach me, aSpriteType, aSpriteNum
  597.   case aSpriteType of
  598.     #graphic:
  599.       return getPos([#animGif, #bitmap, #filmLoop, #flash, #movie, #picture, #shape], sprite(aSpriteNum).member.type) <> 0
  600.     #script:
  601.       return 0
  602.   end case
  603. end
  604.  
  605. on getPropertyDescriptionList me
  606.   if not (the currentSpriteNum) then
  607.     exit
  608.   end if
  609.   theMember = sprite(the currentSpriteNum).member
  610.   memberType = theMember.type
  611.   scrollableList = GetScrollableSprites(me)
  612.   if not scrollableList.count then
  613.     return ErrorAlert(me, #noScrollableSprites)
  614.   end if
  615.   return [#myScrollRole: [#comment: "Current sprite acts as", #format: #string, #range: ["upArrow", "downArrow", "dragger", "bar"], #default: 1], #ourScrolledElement: [#comment: "Scroll the member of", #format: #string, #range: scrollableList, #default: scrollableList[1]], #myStandardMember: [#comment: "Standard member", #format: #graphic, #default: theMember], #myActiveMember: [#comment: "(Arrows only) mouseDown member", #format: #graphic, #default: theMember], #myMultiThreading: [#comment: "Allow animations to continue (slower)?", #format: #boolean, #default: 1]]
  616. end
  617.  
  618. on GetScrollableSprites me, permittedTypes
  619.   scrollableSprites = []
  620.   repeat with theSprite = 1 to the lastChannel
  621.     theMember = sprite(theSprite).member
  622.     case theMember.type of
  623.       #field, #text:
  624.         memberName = theMember.name
  625.         if memberName = EMPTY then
  626.           memberName = theMember
  627.         else
  628.           memberName = QUOTE & memberName & QUOTE
  629.         end if
  630.         memberName = theMember.type && memberName
  631.         scrollableSprites.append("sprite " & theSprite & ": " & memberName)
  632.     end case
  633.   end repeat
  634.   return scrollableSprites
  635. end
  636.