alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

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.

Java - Scala tags/keywords

a, a, boolean, boolean, component, event, gui, int, int, jlist, listcellrenderer, listview, listview, renderer, seq, swing, use

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:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.