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
Last updated 1st of July, 2005

© 2006 MeccaMedialight. Site Powered by Wrangler 8.