Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- tableView.lua, Table View Library
- --
- -- Version 1.3
- --
- -- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
- --
- -- Permission is hereby granted, free of charge, to any person obtaining a copy of
- -- this software and associated documentation files (the "Software"), to deal in the
- -- Software without restriction, including without limitation the rights to use, copy,
- -- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- -- and to permit persons to whom the Software is furnished to do so, subject to the
- -- following conditions:
- --
- -- The above copyright notice and this permission notice shall be included in all copies
- -- or substantial portions of the Software.
- --
- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- -- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- -- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
- -- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- -- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- -- DEALINGS IN THE SOFTWARE.
- module(..., package.seeall)
- --properties
- local screenW, screenH = display.contentWidth, display.contentHeight
- local viewableScreenW, viewableScreenH = display.viewableContentWidth, display.viewableContentHeight
- local screenOffsetW, screenOffsetH = display.contentWidth - display.viewableContentWidth, display.contentHeight - display.viewableContentHeight
- local currentTarget, detailScreen, velocity, currentDefault, currentOver, prevY
- local startTime, lastTime, prevTime = 0, 0, 0
- --methods
- function showHighlight(event)
- local timePassed = system.getTimer() - startTime
- if timePassed > 100 then
- print("highlight")
- currentDefault.isVisible = false
- currentOver.isVisible = true
- Runtime:removeEventListener( "enterFrame", showHighlight )
- end
- end
- function newListItemHandler(self, event)
- local t = currentTarget --could use self.target.parent possibly
- local phase = event.phase
- print("touch: ".. phase)
- local default = self.default
- local over = self.over
- local top = self.top
- local bottom = self.bottom
- local upperLimit, bottomLimit = top, screenH - currentTarget.height - bottom
- local result = true
- if( phase == "began" ) then
- -- Subsequent touch events will target button even if they are outside the stageBounds of button
- display.getCurrentStage():setFocus( self )
- self.isFocus = true
- startPos = event.y
- prevPos = event.y
- delta, velocity = 0, 0
- if currentTarget.tween then transition.cancel(currentTarget.tween) end
- Runtime:removeEventListener("enterFrame", scrollList )
- Runtime:addEventListener("enterFrame", moveCat)
- -- Start tracking velocity
- Runtime:addEventListener("enterFrame", trackVelocity)
- if over then
- currentDefault = default
- currentOver = over
- startTime = system.getTimer()
- Runtime:addEventListener( "enterFrame", showHighlight )
- end
- elseif( self.isFocus ) then
- if( phase == "moved" ) then
- Runtime:removeEventListener( "enterFrame", showHighlight )
- if over then
- default.isVisible = true
- over.isVisible = false
- end
- delta = event.y - prevPos
- prevPos = event.y
- if ( t.y > upperLimit or t.y < bottomLimit ) then
- t.y = t.y + delta/2
- else
- t.y = t.y + delta
- end
- elseif( phase == "ended" or phase == "cancelled" ) then
- lastTime = event.time
- local dragDistance = event.y - startPos
- --velocity = delta
- Runtime:removeEventListener("enterFrame", moveCat)
- Runtime:removeEventListener("enterFrame", trackVelocity)
- Runtime:addEventListener("enterFrame", scrollList )
- local bounds = self.stageBounds
- local x, y = event.x, event.y
- local isWithinBounds = bounds.xMin <= x and bounds.xMax >= x and bounds.yMin <= y and bounds.yMax >= y
- -- Only consider this a "click", if the user lifts their finger inside button's stageBounds
- if isWithinBounds and (dragDistance < 10 and dragDistance > -10 ) then
- velocity = 0
- result = self.onRelease(event)
- end
- -- Allow touch events to be sent normally to the objects they "hit"
- display.getCurrentStage():setFocus( nil )
- self.isFocus = false
- if over then
- default.isVisible = true
- over.isVisible = false
- Runtime:removeEventListener( "enterFrame", showHighlight )
- end
- end
- end
- return result
- end
- function newListItem(params)
- local data = params.data
- local default = params.default
- local over = params.over
- local onRelease = params.onRelease
- local top = params.top
- local bottom = params.bottom
- local callback = params.callback
- local id = params.id
- local thisItem = display.newGroup()
- if params.default then
- default = display.newImage( params.default )
- thisItem:insert( default )
- default.x = default.width*.5 - screenOffsetW
- thisItem.default = default
- end
- if params.over then
- over = display.newImage( params.over )
- over.isVisible = false
- thisItem:insert( over )
- over.x = over.width*.5 - screenOffsetW
- thisItem.over = over
- end
- thisItem.id = id
- thisItem.data = data
- thisItem.onRelease = onRelease
- thisItem.top = top
- thisItem.bottom = bottom
- local t = callback(data)
- thisItem:insert( t )
- thisItem.touch = newListItemHandler
- thisItem:addEventListener( "touch", thisItem )
- return thisItem
- end
- function newList(params)
- local textSize = 16
- local data = params.data
- local default = params.default
- local over = params.over
- local onRelease = params.onRelease
- local top = params.top or 20
- local bottom = params.bottom or 48
- local cat = params.cat
- local order = params.order or {}
- local categoryBackground = params.categoryBackground
- local backgroundColor = params.backgroundColor
- local callback = params.callback or function(item)
- local t = display.newText(item, 0, 0, native.systemFontBold, textSize)
- t:setTextColor(255, 255, 255)
- t.x = math.floor(t.width/2) + 20
- t.y = 24
- return t
- end
- --setup the list view
- local listView = display.newGroup()
- local prevY, prevH = 0, 0
- if cat then
- local catTable = {}
- --get the implicit categories
- local prevCat = 0
- for i=1, #data do
- if data[i][cat] ~= prevCat then
- table.insert(catTable, data[i][cat])
- prevCat = data[i][cat]
- end
- end
- if order then
- --clean up the user provided order table by removing any empty categories
- local n = 1
- while n < #order do
- if not in_table(order[n], catTable) then
- table.remove(order, n)
- else
- n = n + 1
- end
- end
- --add any categories not specified to the user order of categories
- for i=1, #catTable do
- if not in_table(catTable[i], order) then
- table.insert(order, catTable[i])
- end
- end
- else
- order = catTable
- end
- end
- local j = 1
- local c = {}
- local offset = 12
- while true do
- local h = order[j]
- if h then
- local g = display.newGroup()
- local b
- if categoryBackground then
- b = display.newImage(categoryBackground, true)
- else
- b = display.newRect(0, 0, screenW, textSize*1.5)
- b:setFillColor(0, 0, 0, 100)
- end
- g:insert( b )
- local labelShadow = display.newText( h, 0, 0, native.systemFontBold, textSize )
- labelShadow:setTextColor( 0, 0, 0, 128 )
- g:insert( labelShadow, true )
- labelShadow.x = labelShadow.width*.5 + 1 + offset + screenOffsetW*.5
- labelShadow.y = textSize*.8 + 1
- local t = display.newText(h, 0, 0, native.systemFontBold, textSize)
- t:setTextColor(255, 255, 255)
- g:insert( t )
- t.x = t.width*.5 + offset + screenOffsetW*.5
- t.y = textSize*.8
- listView:insert( g )
- g.x = 0
- g.y = prevY + prevH
- prevY = g.y
- prevH = g.height
- table.insert(c, g)
- c[#c].yInit = g.y
- end
- --iterate over the data and add items to the list view
- for i=1, #data do
- if data[i][cat] == h then
- local thisItem = newListItem{
- data = data[i],
- default = default,
- over = over,
- onRelease = onRelease,
- top = top,
- bottom = bottom,
- callback = callback,
- id = i
- }
- listView:insert( 1, thisItem )
- thisItem.x = 0 + screenOffsetW*.5
- thisItem.y = prevY + prevH
- --save the Y and height
- prevY = thisItem.y
- prevH = thisItem.height
- end --if
- end --for
- j = j + 1
- if not order[j] then break end
- end --while
- if backgroundColor then
- local bgColor = display.newRect(0, 0, screenW, screenH)
- bgColor:setFillColor(backgroundColor[1], backgroundColor[2], backgroundColor[3])
- bgColor.width = listView.width
- bgColor.height = listView.height
- bgColor.y = bgColor.height*.5
- listView:insert(1, bgColor)
- end
- listView.y = top
- listView.top = top
- listView.bottom = bottom
- listView.c = c
- currentTarget = listView
- function listView:cleanUp()
- print("tableView cleanUp")
- Runtime:removeEventListener("enterFrame", moveCat )
- Runtime:removeEventListener("enterFrame", scrollList )
- Runtime:removeEventListener( "enterFrame", showHighlight )
- Runtime:removeEventListener("enterFrame", trackVelocity)
- local i
- for i = listView.numChildren, 1, -1 do
- --test
- listView[i]:removeEventListener("touch", newListItemHandler)
- listView:remove(i)
- listView[i] = nil
- end
- end
- return listView
- end
- function scrollList(event)
- local friction = 0.9
- local timePassed = event.time - lastTime
- lastTime = lastTime + timePassed
- --turn off scrolling if velocity is near zero
- if math.abs(velocity) < .01 then
- velocity = 0
- Runtime:removeEventListener("enterFrame", scrollList )
- end
- velocity = velocity*friction
- currentTarget.y = math.floor(currentTarget.y + velocity*timePassed)
- moveCat()
- local upperLimit = currentTarget.top
- local bottomLimit = screenH - currentTarget.height - currentTarget.bottom
- if ( currentTarget.y > upperLimit ) then
- velocity = 0
- Runtime:removeEventListener("enterFrame", scrollList )
- Runtime:addEventListener("enterFrame", moveCat )
- currentTarget.tween = transition.to(currentTarget, { time=400, y=upperLimit, transition=easing.outQuad})
- elseif ( currentTarget.y < bottomLimit and bottomLimit < 0 ) then
- velocity = 0
- Runtime:removeEventListener("enterFrame", scrollList )
- Runtime:addEventListener("enterFrame", moveCat )
- currentTarget.tween = transition.to(currentTarget, { time=400, y=bottomLimit, transition=easing.outQuad})
- elseif ( currentTarget.y < bottomLimit ) then
- velocity = 0
- Runtime:removeEventListener("enterFrame", scrollList )
- Runtime:addEventListener("enterFrame", moveCat )
- currentTarget.tween = transition.to(currentTarget, { time=400, y=upperLimit, transition=easing.outQuad})
- end
- return true
- end
- function moveCat()
- local upperLimit = currentTarget.top
- for i=1, #currentTarget.c do
- if( currentTarget.y > upperLimit - currentTarget.c[i].yInit ) then
- currentTarget.c[i].y = currentTarget.c[i].yInit
- end
- if ( currentTarget.y < upperLimit - currentTarget.c[i].yInit ) then
- currentTarget.c[i].y = upperLimit - currentTarget.y
- end
- if( i > 1 ) then
- if ( currentTarget.c[i].y < currentTarget.c[i-1].y + currentTarget.c[i].height ) then
- currentTarget.c[i-1].y = currentTarget.c[i].y - currentTarget.c[i].height
- end
- end
- end
- return true
- end
- function trackVelocity(event)
- local timePassed = event.time - prevTime
- prevTime = prevTime + timePassed
- if prevY then
- velocity = (currentTarget.y - prevY)/timePassed
- end
- prevY = currentTarget.y
- end
- --look for an item in a table
- function in_table ( e, t )
- for _,v in pairs(t) do
- if (v==e) then return true end
- end
- return false
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement