|
Scala example source code file (ListView.scala)
This example Scala source code file (ListView.scala) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
The Scala ListView.scala source code
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.swing
import event._
import javax.swing._
import javax.swing.event._
object ListView {
/**
* The supported modes of user selections.
*/
object IntervalMode extends Enumeration {
val Single = Value(ListSelectionModel.SINGLE_SELECTION)
val SingleInterval = Value(ListSelectionModel.SINGLE_INTERVAL_SELECTION)
val MultiInterval = Value(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
}
def wrap[A](c: JList) = new ListView[A] {
override lazy val peer = c
}
object Renderer {
def wrap[A](r: ListCellRenderer): Renderer[A] = new Wrapped[A](r)
/**
* Wrapper for <code>javax.swing.ListCellRenderers
*/
class Wrapped[A](override val peer: ListCellRenderer) extends Renderer[A] {
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int) = {
Component.wrap(peer.getListCellRendererComponent(list.peer, a, index, isSelected, focused).asInstanceOf[JComponent])
}
}
/**
* Returns a renderer for items of type <code>A . The given function
* converts items of type <code>A to items of type B
* for which a renderer is implicitly given. This allows chaining of
* renderers, e.g.:
*
* <code>
* case class Person(name: String, email: String)
* val persons = List(Person("John", "j.doe@a.com"), Person("Mary", "m.jane@b.com"))
* new ListView(persons) {
* renderer = ListView.Renderer(_.name)
* }
* </code>
*/
def apply[A,B](f: A => B)(implicit renderer: Renderer[B]): Renderer[A] = new Renderer[A] {
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int): Component =
renderer.componentFor(list, isSelected, focused, f(a), index)
}
}
/**
* Item renderer for a list view. This is contravariant on the type of the
* items, so a more general renderer can be used in place of a more specific
* one. For instance, an <code>Any renderer can be used for a list view
* of strings.
*
* @see javax.swing.ListCellRenderer
*/
abstract class Renderer[-A] {
def peer: ListCellRenderer = new ListCellRenderer {
def getListCellRendererComponent(list: JList, a: Any, index: Int, isSelected: Boolean, focused: Boolean) =
componentFor(ListView.wrap[A](list), isSelected, focused, a.asInstanceOf[A], index).peer
}
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int): Component
}
/**
* A default renderer that maintains a single component for item rendering
* and preconfigures it to sensible defaults. It is polymorphic on the
* component's type so clients can easily use component specific attributes
* during configuration.
*/
abstract class AbstractRenderer[-A, C<:Component](protected val component: C) extends Renderer[A] {
// The renderer component is responsible for painting selection
// backgrounds. Hence, make sure it is opaque to let it draw
// the background.
component.opaque = true
/**
* Standard preconfiguration that is commonly done for any component.
* This includes foreground and background colors, as well as colors
* of item selections.
*/
def preConfigure(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int) {
if (isSelected) {
component.background = list.selectionBackground
component.foreground = list.selectionForeground
} else {
component.background = list.background
component.foreground = list.foreground
}
}
/**
* Configuration that is specific to the component and this renderer.
*/
def configure(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int)
/**
* Configures the component before returning it.
*/
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, a: A, index: Int): Component = {
preConfigure(list, isSelected, focused, a, index)
configure(list, isSelected, focused, a, index)
component
}
}
/**
* A generic renderer that uses Swing's built-in renderers. If there is no
* specific renderer for a type, this renderer falls back to a renderer
* that renders the string returned from an item's <code>toString.
*/
implicit object GenericRenderer extends Renderer[Any] {
override lazy val peer: ListCellRenderer = new DefaultListCellRenderer
def componentFor(list: ListView[_], isSelected: Boolean, focused: Boolean, a: Any, index: Int): Component = {
val c = peer.getListCellRendererComponent(list.peer, a, index, isSelected, focused).asInstanceOf[JComponent]
Component.wrap(c)
}
}
}
/**
* A component that displays a number of elements in a list. A list view does
* not support inline editing of items. If you need it, use a table view instead.
*
* Named <code>ListView to avoid a clash with the frequently used
* <code>scala.List
*
* @see javax.swing.JList
*/
class ListView[A] extends Component {
import ListView._
override lazy val peer: JList = new JList with SuperMixin
def this(items: Seq[A]) = {
this()
listData = items
}
protected class ModelWrapper(val items: Seq[A]) extends AbstractListModel {
def getElementAt(n: Int) = items(n).asInstanceOf[AnyRef]
def getSize = items.size
}
def listData: Seq[A] = peer.getModel match {
case model: ModelWrapper => model.items
case model @ _ => new Seq[A] { selfSeq =>
def length = model.getSize
def iterator = new Iterator[A] {
var idx = 0
def next = { idx += 1; apply(idx-1) }
def hasNext = idx < selfSeq.length
}
def apply(n: Int) = model.getElementAt(n).asInstanceOf[A]
}
}
def listData_=(items: Seq[A]) {
peer.setModel(new AbstractListModel {
def getElementAt(n: Int) = items(n).asInstanceOf[AnyRef]
def getSize = items.size
})
}
/**
* The current item selection.
*/
object selection extends Publisher {
protected abstract class Indices[A](a: =>Seq[A]) extends scala.collection.mutable.Set[A] {
def -=(n: A): this.type
def +=(n: A): this.type
def contains(n: A) = a.contains(n)
override def size = a.length
def iterator = a.iterator
}
def leadIndex: Int = peer.getSelectionModel.getLeadSelectionIndex
def anchorIndex: Int = peer.getSelectionModel.getAnchorSelectionIndex
/**
* The indices of the currently selected items.
*/
object indices extends Indices(peer.getSelectedIndices) {
def -=(n: Int): this.type = { peer.removeSelectionInterval(n,n); this }
def +=(n: Int): this.type = { peer.addSelectionInterval(n,n); this }
@deprecated("Use ListView.selection.leadIndex", "2.8.0")
def leadIndex: Int = peer.getSelectionModel.getLeadSelectionIndex
@deprecated("Use ListView.selection.anchorIndex", "2.8.0")
def anchorIndex: Int = peer.getSelectionModel.getAnchorSelectionIndex
}
@deprecated("Use ListView.selectIndices", "2.8.0")
def selectIndices(ind: Int*) = peer.setSelectedIndices(ind.toArray)
/**
* The currently selected items.
*/
object items extends scala.collection.SeqProxy[A] {
def self = peer.getSelectedValues.map(_.asInstanceOf[A])
@deprecated("Use ListView.selection.leadIndex", "2.8.0")
def leadIndex: Int = peer.getSelectionModel.getLeadSelectionIndex
@deprecated("Use ListView.selection.anchorIndex", "2.8.0")
def anchorIndex: Int = peer.getSelectionModel.getAnchorSelectionIndex
}
def intervalMode: IntervalMode.Value = IntervalMode(peer.getSelectionModel.getSelectionMode)
def intervalMode_=(m: IntervalMode.Value) { peer.getSelectionModel.setSelectionMode(m.id) }
peer.getSelectionModel.addListSelectionListener(new ListSelectionListener {
def valueChanged(e: javax.swing.event.ListSelectionEvent) {
publish(new ListSelectionChanged(ListView.this, e.getFirstIndex to e.getLastIndex, e.getValueIsAdjusting))
}
})
def adjusting = peer.getSelectionModel.getValueIsAdjusting
}
def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getCellRenderer)
def renderer_=(r: ListView.Renderer[A]) { peer.setCellRenderer(r.peer) }
def fixedCellWidth = peer.getFixedCellWidth
def fixedCellWidth_=(x: Int) = peer.setFixedCellWidth(x)
def fixedCellHeight = peer.getFixedCellHeight
def fixedCellHeight_=(x: Int) = peer.setFixedCellHeight(x)
def prototypeCellValue: A = peer.getPrototypeCellValue.asInstanceOf[A]
def prototypeCellValue_=(a: A) { peer.setPrototypeCellValue(a) }
def selectionForeground: Color = peer.getSelectionForeground
def selectionForeground_=(c: Color) = peer.setSelectionForeground(c)
def selectionBackground: Color = peer.getSelectionBackground
def selectionBackground_=(c: Color) = peer.setSelectionBackground(c)
def selectIndices(ind: Int*) = peer.setSelectedIndices(ind.toArray)
peer.getModel.addListDataListener(new ListDataListener {
def contentsChanged(e: ListDataEvent) { publish(ListChanged(ListView.this)) }
def intervalRemoved(e: ListDataEvent) { publish(ListElementsRemoved(ListView.this, e.getIndex0 to e.getIndex1)) }
def intervalAdded(e: ListDataEvent) { publish(ListElementsAdded(ListView.this, e.getIndex0 to e.getIndex1)) }
})
}
Other Scala examples (source code examples)
Here is a short list of links related to this Scala ListView.scala source code file:
|