1.di.source-code.menu.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of p5_2.11 Show documentation
Show all versions of p5_2.11 Show documentation
draw drx types in the processing.org environment
/*
Copyright 2010 Aaron J. Radke
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.drx.p5.gui
import cc.drx.p5._
import processing.core._
import processing.core.PConstants._
import processing.core.PApplet._
import cc.drx._
object Menu{
trait Item[A]{
val menu:Menu[A]
val pos:Vec
val i:Int
val isSelected:Boolean
val value:A
def isHover(mouse:Vec):Boolean
}
def apply[A](title:String, origin:Vec, w:Int, items:Seq[A]=Seq(), fieldHeight:Double=30d) = new Menu(title, origin,w,items,fieldHeight)
}
class Menu[A](val title:String, var origin:Vec, w:Int,var items:Seq[A]=Seq(), fieldHeight:Double) extends Traversable[Menu.Item[A]]{
import P5._
private var hidden = false
def isHidden = hidden
def isVisible = !hidden
def show:Menu[A] = {hidden = false; this}
def hide:Menu[A] = {hidden = true; this}
def toggle:Menu[A] = {hidden = !hidden; this} //toggle visibility
var scrollOffset:Int = 0
var selected:Set[Int] = Set()
def toggleSelection(i:Int):Unit = if(selected contains i) selected -= i else selected += i
def selectAll:Unit = selected = allIndices
private def allIndices:Set[Int] = (0 to (items.size-1)).toSet
def selectedItems:Seq[A] = selected.toSeq map {items.apply}
var hiddenIndices:Set[Int] = Set()
def visibleIndices_=(visible:Set[Int]) = hiddenIndices = allIndices -- visible
def visibleIndices:Set[Int] = allIndices -- hiddenIndices
def contains(mouse:Vec):Boolean = {
!hidden &&
origin.x < mouse.x &&
mouse.x < origin.x + w &&
origin.y < mouse.y &&
mouse.y < (origin.y + yOfIndex(items.size) - scrollOffset)
}
def valueAt(mouse:Vec):Option[A] = indexAt(mouse) map items.apply
def indexAt(mouse:Vec):Option[Int] = if(hidden) None else {
if(inXRange(mouse)){
val j = ((mouse.y- origin.y - scrollOffset)/fieldHeight).toInt
if(hiddenIndices.isEmpty) if(j < 0 || j >= items.size) None else Some(j)
else (0 until items.size) filterNot hiddenIndices lift j //really inefficient way of computing this, but it works
} else None
}
private def yOfIndex(i:Int):Double = origin.y + scrollOffset + i*fieldHeight
private def inXRange(mouse:Vec) = origin.x < mouse.x && mouse.x < origin.x + w
def foreach[U](f:Menu.Item[A]=>U):Unit = if(!hidden){
var j = 0
for((item,i) <- items.zipWithIndex if hiddenIndices doesNotContain i){
val yt = yOfIndex(j)
val pos = Vec(origin.x, yt + fieldHeight/2)
f(MenuItem(pos,i,selected(i)))
j += 1
}
}
private val thisMenu = this
case class MenuItem(pos:Vec, i:Int, isSelected:Boolean) extends Menu.Item[A]{
val value = items(i)
val menu = thisMenu
def isHover(mouse:Vec):Boolean = {
val inX = inXRange(mouse)
val f2 = fieldHeight/2
val inY = pos.y-f2 < mouse.y && mouse.y < pos.y+f2
inX && inY
}
}
@deprecated("use the more general foreach(mouse)(f:Menu.Item=>Unit)","v0.1.10")
def draw(onHover:Int=>Unit=(_:Int)=>{})(implicit pg:P5):Unit = {
pg.textAlign(LEFT,CENTER)
foreach{m =>
pg.fill(if(m isHover pg.mouse) Yellow else if(m.isSelected) Red else White)
pg.text(m.value.toString, m.pos.x, m.pos.y)
}
}
}