Super Slider Pro
Whilst the original slider works fine to display a strip of thumbnail images derived from cast members, it has some limitations that become apparent if you want to start interacting with the thumbnails (changing them or animating them), or using dynamically loaded images from external files.
The major difference with this next version of the Slider script is that the 'LoadImages' method now expects a list of images, not cast members. It also has methods for appending images to the slider, as well as updating existing images. These last two methods will be useful if you want to load images as they become available (such as once they have been preloaded).
You may also notice that the Slide method doesn't modify the map list-rather, it modifies a list of indexes (the property 'mySlideMap'). This means that the order that images are added to the slider doesn't change (which is useful if you want to add 'DeleteAt' or "AddAt' methods to the script).
property myCanvas -- the image object to draw into
property myDestRect -- the rect on the canvas to draw to
property myBuffer -- image used to composite the tiles
property myHeight, myWidth -- size of this image
property myMapH -- how much the view has been moved
property myMap -- list of 'tiles'
property mySlideMap -- a list of indexes to the map
property mySettings -- settings (colour, etc)
property myPixel -- utility image
on Initialise (me, aCanvas, aRectOnCanvas, settings)
myCanvas = aCanvas
myDestRect = aRectOnCanvas
me._LoadSettings(settings)
myWidth = myDestRect.width
myHeight = myDestRect.height
myBuffer = image(myWidth, myHeight, 24)
myBuffer.fill(myBuffer.rect, rgb(0,0,0))
myMapH= 0
myMap = []
mySlideMap = []
-- create a pixel image (used for hilighting etc)
myPixel = image(1,1,1)
myPixel.setPixel(0,0,1)
end
on LoadImages (me, aListOfImages)
-- clears the currrent list of images, and loads a new set
myMap = []
myTileRects = []
return me.AppendImages(aListOfImages)
end
on AppendImages (me, aListOfImages)
-- append images to the map
if aListOfImages.ilk <> #PropList then return #ParameterError
mx = aListOfImages.count
repeat with i = 1 to mx
id = aListOfImages.getPropAt(i)
img = aListOfImages[i]
tile = me._CreateTile(img, id)
-- add it to the map
myMap.append(tile)
mySlideMap.append(myMap.count)
end repeat
end
on SetImageAt (me, img, id, pos)
if (pos < 1 or pos > myMap.count) then return #IndexOutOfRange
-- inserts an image at the specified position
tile = me._CreateTile(img, id)
-- add it to the map
myMap.SetAt(pos, tile)
end
on UpdateImage (me, img, id)
repeat with i = 1 to myMap.Count
if myMap[i][#id] = id then
tile = me._CreateTile(img, id)
myMap[i][#image] = tile.image
myMap[i][#DRect] = tile.DRect
end if
end repeat
end
on GetTile (me, whichTileId)
-- returns the tile position under the point
if whichTileId.ilk = #Integer then return myMap[whichTileId]
repeat with i = 1 to myMap.Count
if myMap[i][#id] = whichTileId then return myMap[i]
end repeat
end
on GetTileIDAtPoint (me, pntOnCanvas)
-- returns the tile id under the point
rectLeft = -myMapH
repeat with i = 1 to mySlideMap.Count
aTileIdx = mySlideMap[i]
aRect = myMap[aTileIdx][#DRect].offset(rectLeft, 0)
if inside(pntOnCanvas, aRect) then
thisTile = myMap[aTileIdx][#id]
return thisTile
end if
rectLeft = rectLeft + aRect.width
if rectLeft > myWidth then exit repeat
end repeat
end
on SelectTileByID (me, whichTileId, multiSelect)
repeat with i = 1 to myMap.count
if myMap[i][#id] = whichTileId then myMap[i][#Selected] = 1
else if NOT(multiSelect) then myMap[i][#Selected] = 0
end repeat
end
on SelectTileByPos (me, whichpos, multiSelect)
repeat with i = 1 to myMap.count
if i = whichpos then myMap[i][#Selected] = 1
else if NOT(multiSelect) then myMap[i][#Selected] = 0
end repeat
end
on Slide (me, shiftAmt)
-- Shifts the display left or right by the specified amount.
-- Specify a positive amount to slide downwards
if myMap.count < 1 then exit -- no images
myMapH = myMapH + shiftAmt
if shiftAmt > 0 then
-- check whether we have moved past the left most tile
-- if so, move it from the start of the list and
-- add it to the end
aTileIdx = mySlideMap[1]
aTile = myMap[aTileIdx]
r = aTile.DRect
w = r.width
if myMapH >= w then
mySlideMap.deleteAt(1)
mySlideMap.append(aTileIdx)
myMapH = myMapH - w
end if
else if shiftAmt < 0 then
-- check whether we have moved past the right most tile
-- if it is, move it from the end to the start of the list
if myMapH <= 0 then
lastPos = myMap.count
aTileIdx = mySlideMap[lastPos]
aTile = myMap[aTileIdx]
mySlideMap.deleteAt(lastPos)
mySlideMap.addAt(1, aTileIdx)
myMapH = myMapH + aTile[#DRect].width
end if
end if
-- now draw the visible portion of the map onto the buffer image
rectLeft = -myMapH
buffer = myBuffer.duplicate()
repeat with i = 1 to mySlideMap.count
aTileIdx = mySlideMap[i]
img = myMap[aTileIdx][#Image]
destRect = myMap[aTileIdx][#DRect].offset(rectLeft, 0)
buffer.copyPixels(img, destRect, img.rect)
if myMap[aTileIdx][#selected] then
buffer.copyPixels(myPixel, destRect, myPixel.rect, [#BlendLevel: 100])
end if
rectLeft = rectLeft + destRect.width
if rectLeft > myWidth then exit repeat
end repeat
myCanvas.copyPixels(buffer, myDestRect, buffer.rect)
end
on _CreateTile (me, img, id)
if img.height > myHeight then
-- need to scale the image down
originalRect = img.rect
thescale = float(myHeight)/img.height
scaledRect = rect(0, 0, integer(img.width*thescale), myHeight)
else if img.height < myHeight then
-- need to centre the rect vertically
vOff = (myHeight-img.height)/2
scaledRect = img.rect.offset(0, vOff)
else
-- perfect fit!
scaledRect = img.rect
end if
-- create the small version of the image
tileImg = image(scaledRect.width, myHeight, 24)
tileImg.fill(tileImg.rect, mySettings.backColour)
tileImg.copyPixels(img, scaledRect, img.rect)
if mySettings.BorderSize <> 0 then
tileImg.draw(tileImg.rect, [#ShapeType: #Rect, \
#LineSize:mySettings.BorderSize, #Color: mySettings.borderColour])
end if
-- store all the information we have about this tile
tile = [#Image: tileImg, #DRect: tileImg.rect, #id: id, #Selected: 0]
return tile
end
on _LoadSettings (me, settings)
-- firstly, set the defaults
mySettings = [:]
mySettings[#backColour] = rgb("#f1f1f1")
mySettings[#borderColour] = rgb("#000000")
mySettings[#BorderSize] = 1
-- now, over-ride them
if settings.ilk = #PropList then
mx = settings.count
repeat with i = 1 to mx
thisProp = settings.getPropAt(i)
thisValue = settings.getAt(i)
mySettings.setAProp(thisProp, thisValue)
end repeat
end if
end