Package

de.sciss

swingplus

Permalink

package swingplus

Visibility
  1. Public
  2. All

Type Members

  1. final class ClientProperties extends AnyVal

    Permalink

    Swing component client properties are hidden accept for put and get.

    Swing component client properties are hidden accept for put and get. Therefore it lacks any sort of iterator and we cannot implement collection.mutable.Map. This is a compromise which provides a few methods known from collection.mutable.Map

  2. sealed trait CloseOperation extends AnyRef

    Permalink
  3. class ComboBox[A] extends Component with Publisher

    Permalink

    Lets the user make a selection from a list of predefined items.

    Lets the user make a selection from a list of predefined items. Visually, this is implemented as a button-like component with a pull-down menu.

    See also

    javax.swing.JComboBox

  4. class DoClickAction extends Action

    Permalink

    A simple action that visually triggers a given button.

  5. class EditorPane extends scala.swing.EditorPane with TextComponent

    Permalink
  6. class GridPanel extends scala.swing.GridPanel

    Permalink
  7. class GroupPanel extends Panel

    Permalink

    A panel that uses javax.swing.GroupLayout to visually arrange its components.

    A panel that uses javax.swing.GroupLayout to visually arrange its components.

    Note: This is a slightly adapted variant of the original GroupPanel class by Andreas Flier and which was part of the ScalaSwingContrib project. We thought it was a bit over-engineered, and also some naming was problematic (theHorizontalLayout is ...) and involving reflection-based structural types.

    The key point to understanding this layout manager is that it separates horizontal and vertical layout. Thus, every component appears twice: once in the horizontal and once in the vertical layout. Consult the Java API documentation for GroupLayout and Sun's Java tutorials for a comprehensive explanation.

    The main advantage of using this panel instead of manually tinkering with the layout is that this panel provides a concise, declarative syntax for laying out its components. This approach should make most use cases easier. In some special cases, e.g. when re-creating layouts on-the-fly, it might be preferable to use a more imperative style, for which direct access to the underlying layout manager is provided.

    In contrast to the underlying swing layout, this panel activates the automatic creation of gaps between components by default, since this panel is intended for coding UIs "by hand", not so much for visual UI builder tools. Many features of the underlying layout are aimed at those, tough. Most of them are available through this panel for completeness' sake but it is anticipated that coders won't need to use them very much.

    Code examples

    This section contains a few simple examples to showcase the basic functionality of GroupPanels. For all examples, it is assumed that everything from the package scala.swing is imported and the code is placed inside a scala.swing.SimpleSwingApplication like this:

    import scala.swing._
    import de.sciss.swingplus._
    
    object Example extends SimpleSwingApplication {
      lazy val top = new MainFrame {
        contents = new GroupPanel {
          // example code here
        }
      }
    }

    Simple panel with 2 components

    In the first example, there's a label and a text field, which appear in a horizontal sequence but share the same vertical space.

    val label     = new Label("Label:")
    val textField = new TextField(20)
    
    horizontal    = Seq(label, textField)
    vertical      = Par(label, textField)

    It can be observed that the resize behaviour of the text field is rather strange. To get better behaviour, the components' vertical sizes can be linked together.

    linkVerticalSize(label, textField)

    Alternatively, it would have been possible to disallow the resizing of the vertical, parallel group. To achieve this, the vertical layout line should be written this way:

    vertical = Par(Leading, FixedSize)(label, textField)

    Since text fields aren't resizable when used with baseline alignment (more about that further down), the following code also prevents (vertical) resizing:

    vertical = Par(Baseline)(label, textField)

    Size and alignment

    Components can be added with custom size constraints (minimum, preferred, maximum size). The next example showcases that. The text field appears with a preferred height of 100 pixels and when the component is resized, it can be reduced to its minimum height of 50 pixels and enlarged to its maximum height of 200 pixels.

    horizontal = Seq(label, textField)
    vertical   = Par(label, Size(textField, 50, 100, 200))

    The Size object holds some useful constants: Default, Preferred and Infinite, that can be used for any of the minimum, preferred and maximum arguments.

    Instead of using these hints with Size.apply, one can also use the provided convenience methods Size.fixed and Size.fill.

    Because the default alignment in a parallel group is Leading, both components are "glued" to the top of the container (panel). To align the label's text with the text inside the text field, an explicit alignment can be specified in a preceding argument list, like this:

    horizontal = Seq(label, textField)
    vertical   = Par(Baseline)(label, Size(textField, 50, 100, 200))

    This example also shows a potential problem of baseline alignment: some components stop being resizable. More specifically, the javadoc for GroupLayout.ParallelGroup states:

    • Elements aligned to the baseline are resizable if they have have a baseline resize behavior of CONSTANT_ASCENT or CONSTANT_DESCENT.
    • Elements with a baseline resize behavior of OTHER or CENTER_OFFSET are not resizable.

    Since a text field's resizing behaviour is CENTER_OFFSET, it is not resizable when used with baseline alignment.

    Gaps

    The GroupPanel turns on automatic creation of gaps between components and along the container edges. To see the difference, try turning this feature off manually by inserting the following lines:

    autoGaps          = false
    autoContainerGaps = false

    With both types of gaps missing, the components are clamped together and to the container edges, which does not look very pleasing. Gaps can be added manually, too. The following example does this in order to get a result that looks similar to the version with automatically created gaps, albeit in a much more verbose manner.

    horizontal = Seq(
      Gap.Container(),
      label,
      Gap.Preferred(Related),
      textField,
      Gap.Container()
    )
    
    vertical = Seq(
      Gap.Container(),
      Parallel(label, textField),
      Gap.Container()
    )

    Rigid gaps with custom size or completely manual gaps (specifying minimum, preferred and maximum size) between components are created with the Gap object:

    bc.. horizontal = Seq(
      label,
      Gap(10, 20, 100),
      textField
    )
    
    vertical = Seq(
      Par(label, Gap(30), textField)
    )

    In a parallel group, such a gap can be used to specify a minimum amount of space taken by the group.

    In addition to rigid gaps in the previous example, it is also possible to specify gaps that resize. This could be done by specifying a maximum size of Infinite. However, for the most commonly used type of these, there is a bit of syntax sugar available with the Spring and ContainerSpring methods.

    bc.. horizontal = Seq(
      Gap.Container(),
      label,
      Gap.Spring(), // default is Related
      textField,
      Gap.ContainerSpring()
    )

    These create gaps that minimally are as wide as a Gap.Preferred would be - it is possible to specify whether the Related or Unrelated distance should be used - but can be resized to an arbitrary size.

    bc.. horizontal = Seq(
      Gap.Container(),
      label,
      Gap.Spring(Unrelated),
      textField,
      Gap.ContainerSpring()
    )

    The preferred size can also be specified more closely (Size.Default or Size.Infinite aka "as large as possible"):

    bc.. horizontal = Seq(
      Gap.Container(),
      label,
      Gap.Spring(Unrelated, Size.Infinite),
      textField,
      Gap.ContainerSpring(Size.Infinite)
    )

    Please note that Gap.Preferred, Spring, Gap.Container and Spring.Container may only be used inside a sequential group.

    A dialog with several components

    As a last, more sophisticated example, here's the GroupPanel version of the "Find" dialog presented as example for GroupLayout in the Java tutorials by Sun:

    val label         = new Label("Find what:")
    val textField     = new TextField
    val caseCheckBox  = new CheckBox("Match case")
    val wholeCheckBox = new CheckBox("Whole words")
    val wrapCheckBox  = new CheckBox("Wrap around")
    val backCheckBox  = new CheckBox("Search backwards")
    val findButton    = new Button("Find")
    val cancelButton  = new Button("Cancel")
    
    horizontal = Seq(
      label,
      Par(
        textField,
        Seq(
          Par(caseCheckBox, wholeCheckBox),
          Par(wrapCheckBox, backCheckBox)
        )
      ),
      Par(findButton, cancelButton)
    )
    
    linkHorizontalSize(findButton, cancelButton)
    
    vertical = Seq(
      Par(Baseline)(label, textField, findButton),
      Par(
        Seq(
          Par(Baseline)(caseCheckBox, wrapCheckBox),
          Par(Baseline)(wholeCheckBox, backCheckBox)
        ),
        cancelButton
      )
    )

    Mapping component sequences

    Often you will want to build panels from a sequence of components and arrange them in a grid. The Seq.apply and Par.apply methods take a sequence of GroupPanel.Element instances, and therefore you may have to explicitly convert them, as the implicit conversion does not kick in for collections. There are two possibilities, as demonstrated in the last example:

    class Param(val check: CheckBox, val label: Label, val slider: Slider, val index: Spinner)
    
    val p1 = new Param(
      new CheckBox,
      new Label("Foo"),
      new Slider { value = 10 },
      new Spinner(new SpinnerNumberModel(10, 0, 100, 1))
    )
    val p2 = new Param(
      new CheckBox { selected = true },
      new Label("Bar"),
      new Slider,
      new Spinner(new SpinnerNumberModel(50, 0, 100, 1))
    )
    val params = List(p1, p2)
    
    horizontal = Seq(
      Par(params.map(r => r.check: GroupPanel.Element): _*),
      Par(params.map(r => r.label: GroupPanel.Element): _*),
      new Par { params.foreach(r => contents += r.slider) },
      new Par { params.foreach(r => contents += r.index ) }
    )
    
    vertical = Seq(
      params.map { p =>
        Par(Center)(p.check, p.label, p.slider, p.index)
      }: _*
    )

    As can be seen, the Seq and Par classes can be instantiated and then populated through calls to the contents member.

    See also

    javax.swing.GroupLayout

  8. abstract class Growable[-A] extends scala.collection.generic.Growable[A]

    Permalink
  9. final case class Labeled[A](value: A)(label: String) extends Product with Serializable

    Permalink
  10. trait LazyPublisher extends Publisher

    Permalink

    A publisher that subscribes itself to an underlying event source not before the first reaction is installed.

    A publisher that subscribes itself to an underlying event source not before the first reaction is installed. Can unsubscribe itself when the last reaction is uninstalled.

  11. class ListView[A] extends Component

    Permalink

    A component that displays a number of elements in a list.

    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 ListView to avoid a clash with the frequently used scala.List

    See also

    javax.swing.JList

  12. class OverlayPanel extends Panel with Wrapper

    Permalink
  13. class PaddedIcon extends Icon

    Permalink
  14. class PopupMenu extends Component with Wrapper with Publisher

    Permalink

    A popup menu component.

    A popup menu component.

    Example usage:

    val popupMenu = new PopupMenu {
      contents += new Menu("menu 1") {
        contents += new RadioMenuItem("radio 1.1")
        contents += new RadioMenuItem("radio 1.2")
      }
      contents += new Menu("menu 2") {
        contents += new RadioMenuItem("radio 2.1")
        contents += new RadioMenuItem("radio 2.2")
      }
    }
    val button = new Button("Show Popup Menu")
    reactions += {
      case e: ButtonClicked => popupMenu.show(button, 0, button.bounds.height)
    }
    listenTo(button)

    The component publishes PopupMenuCanceled, PopupMenuWillBecomeInvisible and PopupMenuWillBecomeVisible events which can be used to determine when the menu is opened or closed.

    See also

    javax.swing.JPopupMenu

  15. class ScrollBar extends scala.swing.ScrollBar

    Permalink

    swing.ScrollBar does not fire events.

    swing.ScrollBar does not fire events. This class rectifies that.

  16. class Separator extends Component

    Permalink
  17. class Spinner extends Component

    Permalink
  18. class SpinnerComboBox[A] extends ComboBox[A]

    Permalink

    A ComboBox for editable numbers.

    A ComboBox for editable numbers. Numbers such as Int or Double are presented inside a Spinner editor component. The combo-box carries a list of preset numbers.

  19. class SpinningProgressBar extends OverlayPanel

    Permalink
  20. trait TextComponent extends scala.swing.TextComponent

    Permalink
  21. class ToolBar extends Component with Wrapper

    Permalink

Value Members

  1. object CloseOperation

    Permalink
  2. object ComboBox

    Permalink
  3. object DoClickAction

    Permalink
  4. object DropMode

    Permalink
  5. object GroupPanel

    Permalink
  6. object Implicits

    Permalink

    Contains various extension methods for existing Swing components.

  7. object ListView

    Permalink
  8. object Separator

    Permalink
  9. package event

    Permalink
  10. package impl

    Permalink

Ungrouped