├── .gitignore ├── README ├── doc ├── README └── build.xml ├── scala └── swing │ ├── AbstractButton.scala │ ├── Action.scala │ ├── Adjustable.scala │ ├── Alignment.scala │ ├── Applet.scala │ ├── BorderPanel.scala │ ├── BoxPanel.scala │ ├── BufferWrapper.scala │ ├── Button.scala │ ├── ButtonGroup.scala │ ├── CheckBox.scala │ ├── ComboBox.scala │ ├── Component.scala │ ├── Container.scala │ ├── EditorPane.scala │ ├── FileChooser.scala │ ├── FlowPanel.scala │ ├── Font.scala.disabled │ ├── FormattedTextField.scala │ ├── GUIApplication.scala │ ├── GridBagPanel.scala │ ├── GridPanel.scala │ ├── Label.scala │ ├── LayoutContainer.scala │ ├── ListView.scala │ ├── MainFrame.scala │ ├── Menu.scala │ ├── Orientable.scala │ ├── Orientation.scala │ ├── Oriented.scala │ ├── Panel.scala │ ├── PasswordField.scala │ ├── ProgressBar.scala │ ├── Publisher.scala │ ├── RadioButton.scala │ ├── Reactions.scala │ ├── Reactor.scala │ ├── RichWindow.scala │ ├── RootPanel.scala │ ├── ScrollBar.scala │ ├── ScrollPane.scala │ ├── Scrollable.scala │ ├── Separator.scala │ ├── SequentialContainer.scala │ ├── SimpleGUIApplication.scala │ ├── SimpleSwingApplication.scala │ ├── Slider.scala │ ├── SplitPane.scala │ ├── Swing.scala │ ├── SwingActor.scala │ ├── SwingApplication.scala │ ├── SwingWorker.scala │ ├── TabbedPane.scala │ ├── Table.scala │ ├── TextArea.scala │ ├── TextComponent.scala │ ├── TextField.scala │ ├── ToggleButton.scala │ ├── UIElement.scala │ ├── Window.scala │ ├── event │ ├── ActionEvent.scala │ ├── AdjustingEvent.scala │ ├── BackgroundChanged.scala │ ├── ButtonClicked.scala │ ├── CaretUpdate.scala │ ├── ComponentEvent.scala │ ├── ContainerEvent.scala │ ├── EditDone.scala │ ├── Event.scala │ ├── FocusEvent.scala │ ├── FontChanged.scala │ ├── ForegroundChanged.scala │ ├── InputEvent.scala │ ├── Key.scala │ ├── KeyEvent.scala │ ├── ListEvent.scala │ ├── MouseEvent.scala │ ├── SelectionEvent.scala │ ├── TableEvent.scala │ ├── UIEvent.scala │ ├── ValueChanged.scala │ ├── WindowActivated.scala │ ├── WindowClosed.scala │ ├── WindowClosing.scala │ ├── WindowDeactivated.scala │ ├── WindowDeiconified.scala │ ├── WindowEvent.scala │ ├── WindowIconified.scala │ └── WindowOpened.scala │ ├── model │ └── Matrix.scala │ ├── package.scala │ └── test │ ├── ButtonApp.scala │ ├── CelsiusConverter.scala │ ├── CelsiusConverter2.scala │ ├── ComboBoxes.scala │ ├── CountButton.scala │ ├── Dialogs.scala │ ├── GridBagDemo.scala │ ├── HelloWorld.scala │ ├── LabelTest.scala │ ├── LinePainting.scala │ ├── ListViewDemo.scala │ ├── SimpleApplet.scala │ ├── SwingApp.scala │ ├── TableSelection.scala │ ├── UIDemo.scala │ └── images │ ├── banana.jpg │ ├── margarita1.jpg │ ├── margarita2.jpg │ └── rose.jpg └── swing.version.properties /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | lib_managed/ 3 | src_managed/ 4 | project/boot/ -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The scala.swing package 2 | 3 | This is a UI library that will wrap most of Java Swing for Scala in a straightforward manner. 4 | The widget class hierarchy loosely resembles that of Java Swing. 5 | 6 | The library comprises three main packages: 7 | 8 | scala.swing 9 | All widget classes and traits. 10 | 11 | scala.swing.event 12 | The event hierarchy. 13 | 14 | scala.swing.test 15 | A set of demos. 16 | 17 | An incubator project can be found on http://github.com/ingoem/scala-swing. -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | scala.swing BETA 2 | 3 | This is a UI library that will wrap most of Java Swing for Scala in a straightforward manner. 4 | The widget class hierarchy loosely resembles that of Java Swing. The main differences are: 5 | 6 | In Java Swing all components are containers per default. This doesn't make much sense for 7 | a number of components, like TextField, CheckBox, RadioButton, and so on. Our guess is that 8 | this architecture was chosen because Java lacks multiple inheritance. 9 | In scala.swing, components that can have child components extend the Container trait. 10 | 11 | Layout managers and panels are coupled. There is no way to exchange the layout manager 12 | of a panel. As a result, the layout constraints for widgets can be typed. 13 | (Note that you gain more type-safety and don't loose much flexibility here. Besides 14 | being not a common operation, exchanging the layout manager of a panel in Java 15 | Swing almost always leads to exchanging the layout constraints for every of the panel's 16 | child component. In the end, it is not more work to move all children to a newly created 17 | panel.) 18 | 19 | The event system. TODO 20 | 21 | 22 | The library comprises three main packages: 23 | 24 | scala.swing 25 | All widget classes and traits. 26 | 27 | scala.swing.event 28 | The event hierarchy. 29 | 30 | scala.swing.test 31 | A set of demos. 32 | 33 | 34 | Notes: 35 | 36 | Visual appearance of combo boxes using the GTK LaF is broken on JDKs < 1.7b30. 37 | This is a Java Swing problem. 38 | 39 | To download the latest version, go to http://lamp.epfl.ch/~imaier or use sbaz. 40 | -------------------------------------------------------------------------------- /doc/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 41 | 54 | 55 | 56 | 57 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /scala/swing/AbstractButton.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing.{AbstractButton => JAbstractButton, Icon} 15 | 16 | /** 17 | * Base class of all button-like widgets, such as push buttons, 18 | * check boxes, and radio buttons. 19 | * 20 | * @see javax.swing.AbstractButton 21 | */ 22 | abstract class AbstractButton extends Component with Action.Trigger.Wrapper with Publisher { 23 | override lazy val peer: JAbstractButton = new JAbstractButton with SuperMixin {} 24 | 25 | def text: String = peer.getText 26 | def text_=(s: String) = peer.setText(s) 27 | 28 | def icon: Icon = peer.getIcon 29 | def icon_=(i: Icon) = peer.setIcon(i) 30 | def pressedIcon: Icon = peer.getPressedIcon 31 | def pressedIcon_=(i: Icon) = peer.setPressedIcon(i) 32 | def selectedIcon: Icon = peer.getSelectedIcon 33 | def selectedIcon_=(i: Icon) = peer.setSelectedIcon(i) 34 | def disabledIcon: Icon = peer.getDisabledIcon 35 | def disabledIcon_=(i: Icon) = peer.setDisabledIcon(i) 36 | def disabledSelectedIcon: Icon = peer.getDisabledSelectedIcon 37 | def disabledSelectedIcon_=(i: Icon) = peer.setDisabledSelectedIcon(i) 38 | def rolloverIcon: Icon = peer.getRolloverIcon 39 | def rolloverIcon_=(b: Icon) = peer.setRolloverIcon(b) 40 | def rolloverSelectedIcon: Icon = peer.getRolloverSelectedIcon 41 | def rolloverSelectedIcon_=(b: Icon) = peer.setRolloverSelectedIcon(b) 42 | 43 | peer.addActionListener(Swing.ActionListener { e => 44 | publish(ButtonClicked(AbstractButton.this)) 45 | }) 46 | 47 | def selected: Boolean = peer.isSelected 48 | def selected_=(b: Boolean) = peer.setSelected(b) 49 | 50 | def contentAreaFilled: Boolean = peer.isContentAreaFilled 51 | def contentAreaFilled_=(b: Boolean) { peer.setContentAreaFilled(b) } 52 | 53 | def borderPainted: Boolean = peer.isBorderPainted 54 | def borderPainted_=(b: Boolean) { peer.setBorderPainted(b) } 55 | def focusPainted: Boolean = peer.isFocusPainted 56 | def focusPainted_=(b: Boolean) { peer.setFocusPainted(b) } 57 | 58 | def rolloverEnabled: Boolean = peer.isRolloverEnabled 59 | def rolloverEnabled_=(b: Boolean) = peer.setRolloverEnabled(b) 60 | 61 | def verticalTextPosition: Alignment.Value = Alignment(peer.getVerticalTextPosition) 62 | def verticalTextPosition_=(a: Alignment.Value) { peer.setVerticalTextPosition(a.id) } 63 | def verticalAlignment: Alignment.Value = Alignment(peer.getVerticalAlignment) 64 | def verticalAlignment_=(a: Alignment.Value) { peer.setVerticalAlignment(a.id) } 65 | 66 | def horizontalTextPosition: Alignment.Value = Alignment(peer.getHorizontalTextPosition) 67 | def horizontalTextPosition_=(a: Alignment.Value) { peer.setHorizontalTextPosition(a.id) } 68 | def horizontalAlignment: Alignment.Value = Alignment(peer.getHorizontalAlignment) 69 | def horizontalAlignment_=(a: Alignment.Value) { peer.setHorizontalAlignment(a.id) } 70 | 71 | def iconTextGap: Int = peer.getIconTextGap 72 | def iconTextGap_=(x: Int) { peer.setIconTextGap(x) } 73 | 74 | def mnemonic: Key.Value = Key(peer.getMnemonic) 75 | def mnemonic_=(k: Key.Value) { peer.setMnemonic(k.id) } 76 | def displayedMnemonicIndex: Int = peer.getDisplayedMnemonicIndex 77 | def displayedMnemonicIndex_=(n: Int) { peer.setDisplayedMnemonicIndex(n) } 78 | 79 | def multiClickThreshold: Long = peer.getMultiClickThreshhold 80 | def multiClickThreshold_=(n: Long) { peer.setMultiClickThreshhold(n) } 81 | 82 | def doClick() { peer.doClick() } 83 | def doClick(times: Int) { peer.doClick(times) } 84 | 85 | def margin: Insets = peer.getMargin 86 | def margin_=(i: Insets) { peer.setMargin(i) } 87 | } 88 | -------------------------------------------------------------------------------- /scala/swing/Action.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.{KeyStroke, Icon} 14 | import java.awt.event.ActionListener 15 | 16 | object Action { 17 | /** 18 | * Special action that has an empty title and all default properties and does nothing. 19 | * Use this as a "null action", i.e., to tell components that they do not have any 20 | * associated action. A component may then obtain its properties from its direct members 21 | * instead of from its action. 22 | * In Java Swing, one would use `null` instead of a designated action. 23 | */ 24 | case object NoAction extends Action("") { def apply() {} } 25 | 26 | object Trigger { 27 | trait Wrapper extends Action.Trigger { 28 | def peer: javax.swing.JComponent { 29 | def addActionListener(a: ActionListener) 30 | def removeActionListener(a: ActionListener) 31 | def setAction(a: javax.swing.Action) 32 | def getAction(): javax.swing.Action 33 | } 34 | 35 | // TODO: we need an action cache 36 | private var _action: Action = Action.NoAction 37 | def action: Action = _action 38 | def action_=(a: Action) { _action = a; peer.setAction(a.peer) } 39 | 40 | //1.6: def hideActionText: Boolean = peer.getHideActionText 41 | //def hideActionText_=(b: Boolean) = peer.setHideActionText(b) 42 | } 43 | } 44 | 45 | /** 46 | * Something that triggers an action. 47 | */ 48 | trait Trigger { 49 | def action: Action 50 | def action_=(a: Action) 51 | 52 | //1.6: def hideActionText: Boolean 53 | //def hideActionText_=(b: Boolean) 54 | } 55 | 56 | /** 57 | * Convenience method to create an action with a given title and body to run. 58 | */ 59 | def apply(title: String)(body: =>Unit) = new Action(title) { 60 | def apply() { body } 61 | } 62 | } 63 | 64 | /** 65 | * An abstract action to be performed in reaction to user input. 66 | * 67 | * Not every action component will honor every property of its action. 68 | * An action itself can generally be configured so that certain properties 69 | * should be ignored and instead taken from the component directly. In the 70 | * end, it is up to a component which property it uses in which way. 71 | * 72 | * @see javax.swing.Action 73 | */ 74 | abstract class Action(title0: String) { 75 | import Swing._ 76 | 77 | lazy val peer: javax.swing.Action = new javax.swing.AbstractAction(title0) { 78 | def actionPerformed(a: java.awt.event.ActionEvent) = apply() 79 | } 80 | 81 | /** 82 | * Title is not optional. 83 | */ 84 | def title: String = ifNull(peer.getValue(javax.swing.Action.NAME),"") 85 | def title_=(t: String) { peer.putValue(javax.swing.Action.NAME, t) } 86 | 87 | /** 88 | * None if large icon and small icon are not equal. 89 | */ 90 | def icon: Icon = smallIcon //if(largeIcon == smallIcon) largeIcon else None 91 | def icon_=(i: Icon) { /*largeIcon = i;*/ smallIcon = i } 92 | // 1.6: def largeIcon: Icon = toNoIcon(peer.getValue(javax.swing.Action.LARGE_ICON_KEY).asInstanceOf[Icon]) 93 | // def largeIcon_=(i: Icon) { peer.putValue(javax.swing.Action.LARGE_ICON_KEY, toNullIcon(i)) } 94 | def smallIcon: Icon = toNoIcon(peer.getValue(javax.swing.Action.SMALL_ICON).asInstanceOf[Icon]) 95 | def smallIcon_=(i: Icon) { peer.putValue(javax.swing.Action.SMALL_ICON, toNullIcon(i)) } 96 | 97 | /** 98 | * For all components. 99 | */ 100 | def toolTip: String = 101 | ifNull(peer.getValue(javax.swing.Action.SHORT_DESCRIPTION), "") 102 | def toolTip_=(t: String) { 103 | peer.putValue(javax.swing.Action.SHORT_DESCRIPTION, t) 104 | } 105 | /** 106 | * Can be used for status bars, for example. 107 | */ 108 | def longDescription: String = 109 | ifNull(peer.getValue(javax.swing.Action.LONG_DESCRIPTION), "") 110 | def longDescription_=(t: String) { 111 | peer.putValue(javax.swing.Action.LONG_DESCRIPTION, t) 112 | } 113 | 114 | /** 115 | * Default: java.awt.event.KeyEvent.VK_UNDEFINED, i.e., no mnemonic key. 116 | * For all buttons and thus menu items. 117 | */ 118 | def mnemonic: Int = ifNull(peer.getValue(javax.swing.Action.MNEMONIC_KEY), 119 | java.awt.event.KeyEvent.VK_UNDEFINED) 120 | def mnemonic_=(m: Int) { peer.putValue(javax.swing.Action.MNEMONIC_KEY, m) } 121 | 122 | /*/** 123 | * Indicates which character of the title should be underlined to indicate the mnemonic key. 124 | * Ignored if out of bounds of the title string. Default: -1, i.e., ignored. 125 | * For all buttons and thus menu items. 126 | */ 127 | 1.6: def mnemonicIndex: Int = 128 | ifNull(peer.getValue(javax.swing.Action.DISPLAYED_MNEMONIC_INDEX_KEY), -1) 129 | def mnemonicIndex_=(n: Int) { peer.putValue(javax.swing.Action.DISPLAYED_MNEMONIC_INDEX_KEY, n) } 130 | */ 131 | 132 | /** 133 | * For menus. 134 | */ 135 | def accelerator: Option[KeyStroke] = 136 | toOption(peer.getValue(javax.swing.Action.ACCELERATOR_KEY)) 137 | def accelerator_=(k: Option[KeyStroke]) { 138 | peer.putValue(javax.swing.Action.ACCELERATOR_KEY, k orNull) 139 | } 140 | 141 | /** 142 | * For all components. 143 | */ 144 | def enabled: Boolean = peer.isEnabled 145 | def enabled_=(b: Boolean) { peer.setEnabled(b) } 146 | 147 | /*/** 148 | * Only honored if not None. For various buttons. 149 | */ 150 | 1.6: def selected: Option[Boolean] = Option(peer.getValue(javax.swing.Action.SELECTED_KEY)) 151 | def selected_=(b: Option[Boolean]) { 152 | peer.putValue(javax.swing.Action.SELECTED_KEY, 153 | if (b == None) null else new java.lang.Boolean(b.get)) 154 | }*/ 155 | 156 | def apply() 157 | } 158 | -------------------------------------------------------------------------------- /scala/swing/Adjustable.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | 3 | import java.awt.{Adjustable => JAdjustable} 4 | 5 | object Adjustable { 6 | trait Wrapper extends Oriented.Wrapper with Adjustable { 7 | def peer: JAdjustable with OrientedMixin 8 | 9 | def unitIncrement = peer.getUnitIncrement 10 | def unitIncrement_=(i: Int) = peer.setUnitIncrement(i) 11 | def blockIncrement = peer.getBlockIncrement 12 | def blockIncrement_=(i: Int) = peer.setBlockIncrement(i) 13 | 14 | def value = peer.getValue 15 | def value_=(v: Int) = peer.setValue(v) 16 | 17 | def visibleAmount = peer.getVisibleAmount 18 | def visibleAmount_=(v: Int) = peer.setVisibleAmount(v) 19 | 20 | def minimum = peer.getMinimum 21 | def minimum_=(m: Int) = peer.setMinimum(m) 22 | def maximum = peer.getMaximum 23 | def maximum_=(m: Int) = peer.setMaximum(m) 24 | } 25 | } 26 | 27 | trait Adjustable extends Oriented { 28 | def unitIncrement: Int 29 | def unitIncrement_=(i: Int) 30 | def blockIncrement: Int 31 | def blockIncrement_=(i: Int) 32 | 33 | def value: Int 34 | def value_=(v : Int) 35 | 36 | def visibleAmount: Int 37 | def visibleAmount_=(v: Int) 38 | 39 | def minimum: Int 40 | def minimum_=(m: Int) 41 | def maximum: Int 42 | def maximum_=(m: Int) 43 | 44 | // Needs implementation of AdjustmentEvent 45 | // 46 | // val adjustments: Publisher = new Publisher { 47 | // peer.addAdjustmentListener(new AdjustmentListener { 48 | // def adjustmentValueChanged(e: java.awt.event.AdjustmentEvent) { 49 | // publish(new AdjustmentEvent(e)) 50 | // } 51 | // }) 52 | // } 53 | } 54 | -------------------------------------------------------------------------------- /scala/swing/Alignment.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.SwingConstants._ 14 | 15 | /** 16 | * Horizontal and vertical alignments. We sacrifice a bit of type-safety 17 | * for simplicity here. 18 | * 19 | * @see javax.swing.SwingConstants 20 | */ 21 | object Alignment extends Enumeration { 22 | val Left = Value(LEFT) 23 | val Right = Value(RIGHT) 24 | val Center = Value(CENTER) 25 | val Top = Value(TOP) 26 | val Bottom = Value(BOTTOM) 27 | //1.6: val Baseline = Value(BASELINE) 28 | 29 | val Leading = Value(LEADING) 30 | val Trailing = Value(TRAILING) 31 | } 32 | 33 | -------------------------------------------------------------------------------- /scala/swing/Applet.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.JApplet 14 | 15 | /**

16 | * Clients should implement the ui field. See the SimpleApplet 17 | * demo for an example. 18 | *

19 | *

20 | * Note: Applet extends javax.swing.JApplet 21 | * to satisfy Java's applet loading mechanism. The usual component wrapping 22 | * scheme doesn't work here. 23 | *

24 | * 25 | * @see javax.swing.JApplet 26 | */ 27 | abstract class Applet extends JApplet { outer => 28 | val ui: UI 29 | 30 | override def init() { ui.init() } 31 | override def start() { ui.start() } 32 | override def stop() { ui.stop() } 33 | 34 | abstract class UI extends RootPanel { 35 | def peer = outer 36 | override def contents_=(c: Component) { 37 | super.contents_=(c) 38 | peer.validate() 39 | } 40 | 41 | def init() 42 | def start() {} 43 | def stop() {} 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /scala/swing/BorderPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.BorderLayout 14 | 15 | object BorderPanel { 16 | /** 17 | * The position of a component in a BorderPanel 18 | */ 19 | object Position extends Enumeration { 20 | val North = Value(BorderLayout.NORTH) 21 | val South = Value(BorderLayout.SOUTH) 22 | val West = Value(BorderLayout.WEST) 23 | val East = Value(BorderLayout.EAST) 24 | val Center = Value(BorderLayout.CENTER) 25 | } 26 | private[swing] def wrapPosition(s: String): Position.Value = s match { 27 | case BorderLayout.NORTH => Position.North 28 | case BorderLayout.SOUTH => Position.South 29 | case BorderLayout.WEST => Position.West 30 | case BorderLayout.EAST => Position.East 31 | case BorderLayout.CENTER => Position.Center 32 | } 33 | } 34 | 35 | /** 36 | * A container that arranges its children around a central component that 37 | * takes most of the space. The other children are placed on one of four 38 | * borders: north, east, south, west. 39 | * 40 | * @see javax.swing.BorderLayout 41 | */ 42 | class BorderPanel extends Panel with LayoutContainer { 43 | import BorderPanel._ 44 | def layoutManager = peer.getLayout.asInstanceOf[BorderLayout] 45 | override lazy val peer = new javax.swing.JPanel(new BorderLayout) with SuperMixin 46 | 47 | type Constraints = Position.Value 48 | 49 | protected def constraintsFor(comp: Component) = 50 | wrapPosition(layoutManager.getConstraints(comp.peer).asInstanceOf[String]) 51 | 52 | protected def areValid(c: Constraints): (Boolean, String) = (true, "") 53 | protected def add(c: Component, l: Constraints) { 54 | // we need to remove previous components with the same constraints as the new one, 55 | // otherwise the layout manager loses track of the old one 56 | val old = layoutManager.getLayoutComponent(l.toString) 57 | if(old != null) peer.remove(old) 58 | peer.add(c.peer, l.toString) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scala/swing/BoxPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | /** 14 | * A panel that lays out its contents one after the other, 15 | * either horizontally or vertically. 16 | * 17 | * @see javax.swing.BoxLayout 18 | */ 19 | class BoxPanel(orientation: Orientation.Value) extends Panel with SequentialContainer.Wrapper { 20 | override lazy val peer = { 21 | val p = new javax.swing.JPanel with SuperMixin 22 | val l = new javax.swing.BoxLayout(p, orientation.id) 23 | p.setLayout(l) 24 | p 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scala/swing/BufferWrapper.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import scala.collection.mutable.Buffer 14 | 15 | /** 16 | * Default partial implementation for buffer adapters. 17 | */ 18 | protected[swing] abstract class BufferWrapper[A] extends Buffer[A] { outer => 19 | def clear() { for (i <- 0 until length) remove(0) } 20 | def update(n: Int, a: A) { 21 | remove(n) 22 | insertAt(n, a) 23 | } 24 | def insertAll(n: Int, elems: scala.collection.Traversable[A]) { 25 | var i = n 26 | for (el <- elems) { 27 | insertAt(i, el) 28 | i += 1 29 | } 30 | } 31 | protected def insertAt(n: Int, a: A) 32 | 33 | def +=:(a: A): this.type = { insertAt(0, a); this } 34 | def iterator = Iterator.range(0,length).map(apply(_)) 35 | } 36 | -------------------------------------------------------------------------------- /scala/swing/Button.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | 16 | object Button { 17 | def apply(text0: String)(op: => Unit) = new Button(Action(text0)(op)) 18 | } 19 | 20 | /** 21 | * A button that can be clicked, usually to perform some action. 22 | * 23 | * @see javax.swing.JButton 24 | */ 25 | class Button(text0: String) extends AbstractButton with Publisher { 26 | override lazy val peer: JButton = new JButton(text0) with SuperMixin 27 | def this() = this("") 28 | def this(a: Action) = { 29 | this("") 30 | action = a 31 | } 32 | 33 | def defaultButton: Boolean = peer.isDefaultButton 34 | 35 | def defaultCapable: Boolean = peer.isDefaultCapable 36 | def defaultCapable_=(capable: Boolean) { peer.setDefaultCapable(capable) } 37 | } 38 | -------------------------------------------------------------------------------- /scala/swing/ButtonGroup.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing.{AbstractButton => JAbstractButton,Icon} 15 | import scala.collection._ 16 | import scala.collection.mutable.Buffer 17 | 18 | /** 19 | * A button mutex. At most one of its associated buttons is selected 20 | * at a time. 21 | * 22 | * @see javax.swing.ButtonGroup 23 | */ 24 | class ButtonGroup(initialButtons: AbstractButton*) { 25 | val peer: javax.swing.ButtonGroup = new javax.swing.ButtonGroup 26 | 27 | val buttons: mutable.Set[AbstractButton] = new mutable.Set[AbstractButton] { 28 | def -=(b: AbstractButton): this.type = { peer.remove(b.peer); this } 29 | def +=(b: AbstractButton): this.type = { peer.add(b.peer); this } 30 | def contains(b: AbstractButton) = this.iterator.contains(b) 31 | override def size = peer.getButtonCount 32 | def iterator: Iterator[AbstractButton] = new Iterator[AbstractButton] { 33 | val enum = peer.getElements 34 | def next = UIElement.cachedWrapper[AbstractButton](enum.nextElement) 35 | def hasNext = enum.hasMoreElements 36 | } 37 | } 38 | buttons ++= initialButtons 39 | 40 | //1.6: def deselectAll() { peer.clearSelection } 41 | def selected: Option[AbstractButton] = buttons.find(_.selected) 42 | def select(b: AbstractButton) { peer.setSelected(b.peer.getModel, true) } 43 | } 44 | -------------------------------------------------------------------------------- /scala/swing/CheckBox.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing._ 14 | 15 | /** 16 | * Two state button that can either be checked or unchecked. 17 | * 18 | * @see javax.swing.JCheckBox 19 | */ 20 | class CheckBox(text: String) extends ToggleButton { 21 | override lazy val peer: JCheckBox = new JCheckBox(text) with SuperMixin 22 | def this() = this("") 23 | 24 | def borderPaintedFlat: Boolean = peer.isBorderPaintedFlat 25 | def borderPaintedFlat_=(flat: Boolean) { peer.setBorderPaintedFlat(flat) } 26 | } 27 | -------------------------------------------------------------------------------- /scala/swing/ComboBox.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing.{JList, JComponent, JComboBox, JTextField, ComboBoxModel, AbstractListModel, ListCellRenderer} 15 | import java.awt.event.ActionListener 16 | 17 | object ComboBox { 18 | /** 19 | * An editor for a combo box. Let's you edit the currently selected item. 20 | * It is highly recommended to use the BuiltInEditor class. For anything 21 | * else, one cannot guarantee that it integrates nicely with the current 22 | * LookAndFeel. 23 | * 24 | * Publishes action events. 25 | */ 26 | trait Editor[A] extends Publisher { 27 | lazy val comboBoxPeer: javax.swing.ComboBoxEditor = new javax.swing.ComboBoxEditor with Publisher { 28 | def addActionListener(l: ActionListener) { 29 | this match { 30 | // TODO case w: Action.Trigger.Wrapper => 31 | // w.peer.addActionListener(l) 32 | case _ => 33 | this.subscribe(new Reactions.Wrapper(l) ({ 34 | case ActionEvent(c) => l.actionPerformed(new java.awt.event.ActionEvent(c.peer, 0, "")) 35 | })) 36 | } 37 | } 38 | def removeActionListener(l: ActionListener) { 39 | this match { 40 | // TODO case w: Action.Trigger.Wrapper => 41 | // w.peer.removeActionListener(l) 42 | case _ => 43 | this.unsubscribe(new Reactions.Wrapper(l)({ case _ => })) 44 | } 45 | } 46 | def getEditorComponent: JComponent = Editor.this.component.peer 47 | def getItem(): AnyRef = item.asInstanceOf[AnyRef] 48 | def selectAll() { startEditing() } 49 | def setItem(a: Any) { item = a.asInstanceOf[A] } 50 | } 51 | def component: Component 52 | def item: A 53 | def item_=(a: A) 54 | def startEditing() 55 | } 56 | 57 | /** 58 | * Use this editor, if you want to reuse the builtin editor supplied by the current 59 | * Look and Feel. This is restricted to a text field as the editor widget. The 60 | * conversion from and to a string is done by the supplied functions. 61 | * 62 | * It's okay if string2A throws exceptions. They are caught by an input verifier. 63 | */ 64 | class BuiltInEditor[A](comboBox: ComboBox[A])(string2A: String => A, 65 | a2String: A => String) extends ComboBox.Editor[A] { 66 | protected[swing] class DelegatedEditor(editor: javax.swing.ComboBoxEditor) extends javax.swing.ComboBoxEditor { 67 | var value: A = { 68 | val v = comboBox.peer.getSelectedItem 69 | try { 70 | v match { 71 | case s: String => string2A(s) 72 | case _ => v.asInstanceOf[A] 73 | } 74 | } catch { 75 | case _: Exception => 76 | throw new IllegalArgumentException("ComboBox not initialized with a proper value, was '" + v + "'.") 77 | } 78 | } 79 | def addActionListener(l: ActionListener) { 80 | editor.addActionListener(l) 81 | } 82 | def removeActionListener(l: ActionListener) { 83 | editor.removeActionListener(l) 84 | } 85 | 86 | def getEditorComponent: JComponent = editor.getEditorComponent.asInstanceOf[JComponent] 87 | def selectAll() { editor.selectAll() } 88 | def getItem(): AnyRef = { verifier.verify(getEditorComponent); value.asInstanceOf[AnyRef] } 89 | def setItem(a: Any) { editor.setItem(a) } 90 | 91 | val verifier = new javax.swing.InputVerifier { 92 | // TODO: should chain with potentially existing verifier in editor 93 | def verify(c: JComponent) = try { 94 | value = string2A(c.asInstanceOf[JTextField].getText) 95 | true 96 | } 97 | catch { 98 | case e: Exception => false 99 | } 100 | } 101 | 102 | def textEditor = getEditorComponent.asInstanceOf[JTextField] 103 | textEditor.setInputVerifier(verifier) 104 | textEditor.addActionListener(Swing.ActionListener{ a => 105 | getItem() // make sure our value is updated 106 | textEditor.setText(a2String(value)) 107 | }) 108 | } 109 | 110 | override lazy val comboBoxPeer: javax.swing.ComboBoxEditor = new DelegatedEditor(comboBox.peer.getEditor) 111 | 112 | def component = Component.wrap(comboBoxPeer.getEditorComponent.asInstanceOf[JComponent]) 113 | def item: A = { comboBoxPeer.asInstanceOf[DelegatedEditor].value } 114 | def item_=(a: A) { comboBoxPeer.setItem(a2String(a)) } 115 | def startEditing() { comboBoxPeer.selectAll() } 116 | } 117 | 118 | implicit def stringEditor(c: ComboBox[String]): Editor[String] = new BuiltInEditor(c)(s => s, s => s) 119 | implicit def intEditor(c: ComboBox[Int]): Editor[Int] = new BuiltInEditor(c)(s => s.toInt, s => s.toString) 120 | implicit def floatEditor(c: ComboBox[Float]): Editor[Float] = new BuiltInEditor(c)(s => s.toFloat, s => s.toString) 121 | implicit def doubleEditor(c: ComboBox[Double]): Editor[Double] = new BuiltInEditor(c)(s => s.toDouble, s => s.toString) 122 | 123 | def newConstantModel[A](items: Seq[A]): ComboBoxModel = { 124 | new AbstractListModel with ComboBoxModel { 125 | private var selected = items(0) 126 | def getSelectedItem: AnyRef = selected.asInstanceOf[AnyRef] 127 | def setSelectedItem(a: Any) { 128 | if ((selected != null && selected != a) || 129 | selected == null && a != null) { 130 | selected = a.asInstanceOf[A] 131 | fireContentsChanged(this, -1, -1) 132 | } 133 | } 134 | def getElementAt(n: Int) = items(n).asInstanceOf[AnyRef] 135 | def getSize = items.size 136 | } 137 | } 138 | 139 | /*def newMutableModel[A, Self](items: Seq[A] with scala.collection.mutable.Publisher[scala.collection.mutable.Message[A], Self]): ComboBoxModel = { 140 | new AbstractListModel with ComboBoxModel { 141 | private var selected = items(0) 142 | def getSelectedItem: AnyRef = selected.asInstanceOf[AnyRef] 143 | def setSelectedItem(a: Any) { selected = a.asInstanceOf[A] } 144 | def getElementAt(n: Int) = items(n).asInstanceOf[AnyRef] 145 | def getSize = items.size 146 | } 147 | } 148 | 149 | def newConstantModel[A](items: Seq[A]): ComboBoxModel = items match { 150 | case items: Seq[A] with scala.collection.mutable.Publisher[scala.collection.mutable.Message[A], Self] => newMutableModel 151 | case _ => newConstantModel(items) 152 | }*/ 153 | } 154 | 155 | /** 156 | * Let's the user make a selection from a list of predefined items. Visually, 157 | * this is implemented as a button-like component with a pull-down menu. 158 | * 159 | * @see javax.swing.JComboBox 160 | */ 161 | class ComboBox[A](items: Seq[A]) extends Component with Publisher { 162 | override lazy val peer: JComboBox = new JComboBox(ComboBox.newConstantModel(items)) with SuperMixin 163 | 164 | object selection extends Publisher { 165 | def index: Int = peer.getSelectedIndex 166 | def index_=(n: Int) { peer.setSelectedIndex(n) } 167 | def item: A = peer.getSelectedItem.asInstanceOf[A] 168 | def item_=(a: A) { peer.setSelectedItem(a) } 169 | 170 | peer.addActionListener(Swing.ActionListener { e => 171 | publish(event.SelectionChanged(ComboBox.this)) 172 | }) 173 | } 174 | 175 | /** 176 | * Sets the renderer for this combo box's items. Index -1 is 177 | * passed to the renderer for the selected item (not in the pull-down menu). 178 | * 179 | * The underlying combo box renders all items in a ListView 180 | * (both, in the pull-down menu as well as in the box itself), hence the 181 | * ListView.Renderer. 182 | * 183 | * Note that the UI peer of a combo box usually changes the colors 184 | * of the component to its own defaults _after_ the renderer has been 185 | * configured. That's Swing's principle of most suprise. 186 | */ 187 | def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getRenderer) 188 | def renderer_=(r: ListView.Renderer[A]) { peer.setRenderer(r.peer) } 189 | 190 | /* XXX: currently not safe to expose: 191 | def editor: ComboBox.Editor[A] = 192 | def editor_=(r: ComboBox.Editor[A]) { peer.setEditor(r.comboBoxPeer) } 193 | */ 194 | def editable: Boolean = peer.isEditable 195 | 196 | /** 197 | * Makes this combo box editable. In order to do so, this combo needs an 198 | * editor which is supplied by the implicit argument. For default 199 | * editors, see ComboBox companion object. 200 | */ 201 | def makeEditable()(implicit editor: ComboBox[A] => ComboBox.Editor[A]) { 202 | peer.setEditable(true) 203 | peer.setEditor(editor(this).comboBoxPeer) 204 | } 205 | 206 | def prototypeDisplayValue: Option[A] = toOption[A](peer.getPrototypeDisplayValue) 207 | def prototypeDisplayValue_=(v: Option[A]) { 208 | peer.setPrototypeDisplayValue(v map toAnyRef orNull) 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /scala/swing/Container.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import scala.collection.mutable.Buffer 15 | 16 | object Container { 17 | /** 18 | * Utility trait for wrapping containers. Provides an immutable 19 | * implementation of the contents member. 20 | */ 21 | trait Wrapper extends Container with Publisher { 22 | override def peer: javax.swing.JComponent 23 | 24 | protected val _contents = new Content 25 | def contents: Seq[Component] = _contents 26 | 27 | protected class Content extends BufferWrapper[Component] { 28 | override def clear { peer.removeAll() } 29 | override def remove(n: Int): Component = { 30 | val c = peer.getComponent(n) 31 | peer.remove(n) 32 | UIElement.cachedWrapper[Component](c) 33 | } 34 | protected def insertAt(n: Int, c: Component) { peer.add(c.peer, n) } 35 | def +=(c: Component): this.type = { peer.add(c.peer) ; this } 36 | def length = peer.getComponentCount 37 | def apply(n: Int) = UIElement.cachedWrapper[Component](peer.getComponent(n)) 38 | } 39 | 40 | peer.addContainerListener(new java.awt.event.ContainerListener { 41 | def componentAdded(e: java.awt.event.ContainerEvent) { 42 | publish(ComponentAdded(Wrapper.this, 43 | UIElement.cachedWrapper[Component](e.getChild.asInstanceOf[javax.swing.JComponent]))) 44 | } 45 | def componentRemoved(e: java.awt.event.ContainerEvent) { 46 | publish(ComponentRemoved(Wrapper.this, 47 | UIElement.cachedWrapper[Component](e.getChild.asInstanceOf[javax.swing.JComponent]))) 48 | } 49 | }) 50 | } 51 | } 52 | 53 | /** 54 | * The base traits for UI elements that can contain Components. 55 | * 56 | * @note [Java Swing] This is not the wrapper for java.awt.Container but a trait 57 | * that extracts a common interface for components, menus, and windows. 58 | */ 59 | trait Container extends UIElement { 60 | /** 61 | * The child components of this container. 62 | */ 63 | def contents: Seq[Component] 64 | } 65 | -------------------------------------------------------------------------------- /scala/swing/EditorPane.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | package scala.swing 11 | 12 | import event._ 13 | import javax.swing._ 14 | import javax.swing.text._ 15 | import java.awt.event._ 16 | 17 | /** 18 | * A text component that allows multiline text input and display. 19 | * 20 | * @see javax.swing.JEditorPane 21 | */ 22 | class EditorPane(contentType0: String, text0: String) extends TextComponent { 23 | override lazy val peer: JEditorPane = new JEditorPane(contentType0, text0) with SuperMixin 24 | def this() = this("text/plain", "") 25 | 26 | def contentType: String = peer.getContentType 27 | def contentType_=(t: String) = peer.setContentType(t) 28 | 29 | def editorKit: EditorKit = peer.getEditorKit 30 | def editorKit_=(k: EditorKit) = peer.setEditorKit(k) 31 | } 32 | -------------------------------------------------------------------------------- /scala/swing/FileChooser.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.io.File 14 | import javax.swing._ 15 | import javax.swing.filechooser._ 16 | 17 | object FileChooser { 18 | /** 19 | * The result of a file dialog. The precise meaning of the Approve 20 | * result depends on the specific dialog type. Could be "save" or "open" for 21 | * example. 22 | */ 23 | object Result extends Enumeration { 24 | val Cancel = Value(JFileChooser.CANCEL_OPTION) 25 | val Approve = Value(JFileChooser.APPROVE_OPTION) 26 | val Error = Value(JFileChooser.ERROR_OPTION) 27 | } 28 | 29 | /** 30 | * The kind of elements a user can select in a file dialog. 31 | */ 32 | object SelectionMode extends Enumeration { 33 | val FilesOnly = Value(JFileChooser.FILES_ONLY) 34 | val DirectoriesOnly = Value(JFileChooser.DIRECTORIES_ONLY) 35 | val FilesAndDirectories = Value(JFileChooser.FILES_AND_DIRECTORIES) 36 | } 37 | } 38 | 39 | /** 40 | * Used to open file dialogs. 41 | * 42 | * @see javax.swing.JFileChooser 43 | */ 44 | class FileChooser(dir: File) { 45 | import FileChooser._ 46 | lazy val peer: JFileChooser = new JFileChooser(dir) 47 | 48 | def this() = this(null) 49 | 50 | import Swing._ 51 | def showOpenDialog(over: Component): Result.Value = Result(peer.showOpenDialog(nullPeer(over))) 52 | def showSaveDialog(over: Component): Result.Value = Result(peer.showSaveDialog(nullPeer(over))) 53 | def showDialog(over: Component, approveText: String): Result.Value = Result(peer.showDialog(nullPeer(over), approveText)) 54 | 55 | def controlButtonsAreShown: Boolean = peer.getControlButtonsAreShown 56 | def controlButtonsAreShown_=(b: Boolean) { peer.setControlButtonsAreShown(b) } 57 | 58 | def title: String = peer.getDialogTitle 59 | def title_=(t: String) { peer.setDialogTitle(t) } 60 | 61 | def accessory: Component = UIElement.cachedWrapper[Component](peer.getAccessory) 62 | def accessory_=(c: Component) { peer.setAccessory(c.peer) } 63 | 64 | def fileHidingEnabled: Boolean = peer.isFileHidingEnabled 65 | def fileHidingEnabled_=(b: Boolean) { peer.setFileHidingEnabled(b) } 66 | def fileSelectionMode: SelectionMode.Value = SelectionMode(peer.getFileSelectionMode) 67 | def fileSelectionMode_=(s: SelectionMode.Value) { peer.setFileSelectionMode(s.id) } 68 | def fileFilter: FileFilter = peer.getFileFilter 69 | def fileFilter_=(f: FileFilter) { peer.setFileFilter(f) } 70 | 71 | def selectedFile: File = peer.getSelectedFile 72 | def selectedFile_=(file: File) { peer.setSelectedFile(file) } 73 | def selectedFiles: Seq[File] = peer.getSelectedFiles 74 | def selectedFiles_=(files: File*) { peer.setSelectedFiles(files.toArray) } 75 | 76 | def multiSelectionEnabled: Boolean = peer.isMultiSelectionEnabled 77 | def multiSelectionEnabled_=(b: Boolean) { peer.setMultiSelectionEnabled(b) } 78 | 79 | def iconFor(f: File) = peer.getIcon(f) 80 | def descriptionFor(f: File) = peer.getDescription(f) 81 | def nameFor(f: File) = peer.getName(f) 82 | def typeDescriptionFor(f: File) = peer.getTypeDescription(f) 83 | def traversable(f: File) = peer.isTraversable(f) 84 | 85 | def acceptAllFileFilter = peer.getAcceptAllFileFilter 86 | 87 | /*peer.addPropertyChangeListener(new java.beans.PropertyChangeListener { 88 | def propertyChange(e: java.beans.PropertyChangeEvent) { 89 | import JFileChooser._ 90 | e.getPropertyName match { 91 | case APPROVE_BUTTON_TEXT_CHANGED_PROPERTY => 92 | case ACCESSORY_CHANGED_PROPERTY => 93 | case APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY => 94 | case APPROVE_BUTTON_TEXT_CHANGED_PROPERTY => 95 | case APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY => 96 | case CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY => 97 | case CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY => 98 | case DIALOG_TITLE_CHANGED_PROPERTY => 99 | case DIALOG_TYPE_CHANGED_PROPERTY => 100 | case DIRECTORY_CHANGED_PROPERTY => 101 | case FILE_FILTER_CHANGED_PROPERTY => 102 | case FILE_HIDING_CHANGED_PROPERTY => 103 | case FILE_SELECTION_MODE_CHANGED_PROPERTY => 104 | case FILE_SYSTEM_VIEW_CHANGED_PROPERTY => 105 | case FILE_VIEW_CHANGED_PROPERTY => 106 | case MULTI_SELECTION_ENABLED_CHANGED_PROPERTY => 107 | case SELECTED_FILE_CHANGED_PROPERTY => 108 | case SELECTED_FILES_CHANGED_PROPERTY => 109 | case _ => 110 | } 111 | } 112 | })*/ 113 | } 114 | -------------------------------------------------------------------------------- /scala/swing/FlowPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.FlowLayout 14 | import javax.swing.JPanel 15 | 16 | object FlowPanel { 17 | object Alignment extends Enumeration { 18 | val Leading = Value(FlowLayout.LEADING) 19 | val Trailing = Value(FlowLayout.TRAILING) 20 | val Left = Value(FlowLayout.LEFT) 21 | val Right = Value(FlowLayout.RIGHT) 22 | val Center = Value(FlowLayout.CENTER) 23 | } 24 | } 25 | 26 | /** 27 | * A panel that arranges its contents horizontally, one after the other. 28 | * If they don't fit, this panel will try to insert line breaks. 29 | * 30 | * @see java.awt.FlowLayout 31 | */ 32 | class FlowPanel(alignment: FlowPanel.Alignment.Value)(contents0: Component*) extends Panel with SequentialContainer.Wrapper { 33 | override lazy val peer: JPanel = 34 | new JPanel(new java.awt.FlowLayout(alignment.id)) with SuperMixin 35 | def this(contents0: Component*) = this(FlowPanel.Alignment.Center)(contents0: _*) 36 | def this() = this(FlowPanel.Alignment.Center)() 37 | 38 | contents ++= contents0 39 | 40 | private def layoutManager = peer.getLayout.asInstanceOf[java.awt.FlowLayout] 41 | 42 | def vGap: Int = layoutManager.getVgap 43 | def vGap_=(n: Int) { layoutManager.setVgap(n) } 44 | def hGap: Int = layoutManager.getHgap 45 | def hGap_=(n: Int) { layoutManager.setHgap(n) } 46 | } 47 | -------------------------------------------------------------------------------- /scala/swing/Font.scala.disabled: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | 3 | /*object Font { 4 | def apply(fontFormat: Int, fontFile: java.io.File) = java.awt.Font.createFont(fontFormat, fontFile) 5 | def apply(fontFormat: Int, fontStream: java.io.InputStream) = java.awt.Font.createFont(fontFormat, fontStream) 6 | def decode(str: String) = java.awt.Font.decode(str) 7 | 8 | /* TODO: finish implementation 9 | /** 10 | * See [java.awt.Font.getFont]. 11 | */ 12 | def get(attributes: Map[_ <: java.text.AttributedCharacterIterator.Attribute, _]) = 13 | java.awt.Font.getFont(ImmutableMapWrapper(attributes)) 14 | 15 | import java.{util => ju} 16 | private case class ImmutableMapWrapper[A, B](underlying : Map[A, B])(m : ClassManifest[A]) extends ju.AbstractMap[A, B] { 17 | self => 18 | override def size = underlying.size 19 | 20 | override def put(k : A, v : B) = 21 | throw new UnsupportedOperationException("This is a wrapper that does not support mutation") 22 | override def remove(k : AnyRef) = 23 | throw new UnsupportedOperationException("This is a wrapper that does not support mutation") 24 | 25 | override def entrySet : ju.Set[ju.Map.Entry[A, B]] = new ju.AbstractSet[ju.Map.Entry[A, B]] { 26 | def size = self.size 27 | 28 | def iterator = new ju.Iterator[ju.Map.Entry[A, B]] { 29 | val ui = underlying.iterator 30 | var prev : Option[A] = None 31 | 32 | def hasNext = ui.hasNext 33 | 34 | def next = { 35 | val (k, v) = ui.next 36 | prev = Some(k) 37 | new ju.Map.Entry[A, B] { 38 | def getKey = k 39 | def getValue = v 40 | def setValue(v1 : B) = self.put(k, v1) 41 | override def equals(other : Any) = other match { 42 | case e : ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue 43 | case _ => false 44 | } 45 | } 46 | } 47 | 48 | def remove = prev match { 49 | case Some(k) => val v = self.remove(k.asInstanceOf[AnyRef]) ; prev = None ; v 50 | case _ => throw new IllegalStateException("next must be called at least once before remove") 51 | } 52 | } 53 | } 54 | } 55 | */ 56 | 57 | /** 58 | * See [java.awt.Font.getFont]. 59 | */ 60 | def get(nm: String) = java.awt.Font.getFont(nm) 61 | /** 62 | * See [java.awt.Font.getFont]. 63 | */ 64 | def get(nm: String, font: Font) = java.awt.Font.getFont(nm, font) 65 | 66 | def Insets(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height) 67 | def Rectangle(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height) 68 | def Point(x: Int, y: Int) = new Point(x, y) 69 | def Dimension(x: Int, y: Int) = new Dimension(x, y) 70 | }*/ -------------------------------------------------------------------------------- /scala/swing/FormattedTextField.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | import java.awt.event._ 16 | 17 | object FormattedTextField { 18 | /** 19 | * The behavior of a formatted text field when it loses its focus. 20 | */ 21 | object FocusLostBehavior extends Enumeration { 22 | val Commit = Value(JFormattedTextField.COMMIT) 23 | val CommitOrRevert = Value(JFormattedTextField.COMMIT_OR_REVERT) 24 | val Persist = Value(JFormattedTextField.PERSIST) 25 | val Revert = Value(JFormattedTextField.REVERT) 26 | } 27 | } 28 | 29 | /** 30 | * A text field with formatted input. 31 | * 32 | * @see javax.swing.JFormattedTextField 33 | */ 34 | class FormattedTextField(format: java.text.Format) extends TextComponent { 35 | override lazy val peer: JFormattedTextField = new JFormattedTextField(format) with SuperMixin 36 | 37 | import FormattedTextField._ 38 | 39 | def commitEdit() { peer.commitEdit() } 40 | def editValid: Boolean = peer.isEditValid 41 | 42 | def focusLostBehavior: FocusLostBehavior.Value = FocusLostBehavior(peer.getFocusLostBehavior) 43 | def focusLostBehavior_=(b: FocusLostBehavior.Value) { peer.setFocusLostBehavior(b.id) } 44 | } 45 | -------------------------------------------------------------------------------- /scala/swing/GUIApplication.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event.Event 14 | import javax.swing._ 15 | 16 | /** 17 | * Convenience class with utility methods for GUI applications. 18 | */ 19 | @deprecated("Use SwingApplication instead") class GUIApplication { 20 | 21 | /** 22 | * Called before the GUI is created. Override to customize. 23 | */ 24 | def init() {} 25 | 26 | /** 27 | * Initializes the framework and runs the given program. 28 | */ 29 | def run(prog: => Unit) = Swing.onEDT { init(); prog } 30 | } 31 | -------------------------------------------------------------------------------- /scala/swing/GridBagPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.{GridBagConstraints, GridBagLayout} 14 | 15 | 16 | object GridBagPanel { 17 | object Fill extends Enumeration { 18 | val None = Value(GridBagConstraints.NONE) 19 | val Horizontal = Value(GridBagConstraints.HORIZONTAL) 20 | val Vertical = Value(GridBagConstraints.VERTICAL) 21 | val Both = Value(GridBagConstraints.BOTH) 22 | } 23 | object Anchor extends Enumeration { 24 | val North = Value(GridBagConstraints.NORTH) 25 | val NorthEast = Value(GridBagConstraints.NORTHEAST) 26 | val East = Value(GridBagConstraints.EAST) 27 | val SouthEast = Value(GridBagConstraints.SOUTHEAST) 28 | val South = Value(GridBagConstraints.SOUTH) 29 | val SouthWest = Value(GridBagConstraints.SOUTHWEST) 30 | val West = Value(GridBagConstraints.WEST) 31 | val NorthWest = Value(GridBagConstraints.NORTHWEST) 32 | val Center = Value(GridBagConstraints.CENTER) 33 | 34 | val PageStart = Value(GridBagConstraints.PAGE_START) 35 | val PageEnd = Value(GridBagConstraints.PAGE_END) 36 | val LineStart = Value(GridBagConstraints.LINE_START) 37 | val LineEnd = Value(GridBagConstraints.LINE_END) 38 | val FirstLineStart = Value(GridBagConstraints.FIRST_LINE_START) 39 | val FirstLineEnd = Value(GridBagConstraints.FIRST_LINE_END) 40 | val LastLineStart = Value(GridBagConstraints.LAST_LINE_START) 41 | val LastLineEnd = Value(GridBagConstraints.LAST_LINE_END) 42 | } 43 | } 44 | 45 | /** 46 | * A panel that arranges its children in a grid. Layout details can be 47 | * given for each cell of the grid. 48 | * 49 | * @see java.awt.GridBagLayout 50 | */ 51 | class GridBagPanel extends Panel with LayoutContainer { 52 | override lazy val peer = new javax.swing.JPanel(new GridBagLayout) with SuperMixin 53 | import GridBagPanel._ 54 | 55 | private def layoutManager = peer.getLayout.asInstanceOf[GridBagLayout] 56 | 57 | /** 58 | * Convenient conversion from xy-coords given as pairs to 59 | * grid bag constraints. 60 | */ 61 | implicit def pair2Constraints(p: (Int, Int)): Constraints = { 62 | val c = new Constraints 63 | c.gridx = p._1 64 | c.gridy = p._2 65 | c 66 | } 67 | 68 | class Constraints(val peer: GridBagConstraints) extends Proxy { 69 | def self = peer 70 | def this(gridx: Int, gridy: Int, 71 | gridwidth: Int, gridheight: Int, 72 | weightx: Double, weighty: Double, 73 | anchor: Int, fill: Int, insets: Insets, 74 | ipadx: Int, ipady: Int) = 75 | this(new GridBagConstraints(gridx, gridy, 76 | gridwidth, gridheight, 77 | weightx, weighty, 78 | anchor, fill, insets, 79 | ipadx, ipady)) 80 | def this() = this(new GridBagConstraints()) 81 | def gridx: Int = peer.gridx 82 | def gridx_=(x: Int) { peer.gridx = x } 83 | def gridy: Int = peer.gridy 84 | def gridy_=(y: Int) { peer.gridy = y } 85 | def grid: (Int, Int) = (gridx, gridy) 86 | def grid_=(c: (Int, Int)) = { 87 | gridx = c._1 88 | gridy = c._2 89 | } 90 | 91 | def gridwidth: Int = peer.gridwidth 92 | def gridwidth_=(w: Int) { peer.gridwidth = w } 93 | def gridheight: Int = peer.gridheight 94 | def gridheight_=(h: Int) { peer.gridheight = h } 95 | def weightx: Double = peer.weightx 96 | def weightx_=(x: Double) { peer.weightx = x } 97 | def weighty: Double = peer.weighty 98 | def weighty_=(y: Double) { peer.weighty = y } 99 | def anchor: Anchor.Value = Anchor(peer.anchor) 100 | def anchor_=(a: Anchor.Value) { peer.anchor = a.id } 101 | def fill: Fill.Value = Fill(peer.fill) 102 | def fill_=(f: Fill.Value) { peer.fill = f.id } 103 | def insets: Insets = peer.insets 104 | def insets_=(i: Insets) { peer.insets = i } 105 | def ipadx: Int = peer.ipadx 106 | def ipadx_=(x: Int) { peer.ipadx = x } 107 | def ipady: Int = peer.ipady 108 | def ipady_=(y: Int) { peer.ipady = y } 109 | } 110 | 111 | protected def constraintsFor(comp: Component) = 112 | new Constraints(layoutManager.getConstraints(comp.peer)) 113 | 114 | protected def areValid(c: Constraints): (Boolean, String) = (true, "") 115 | protected def add(c: Component, l: Constraints) { peer.add(c.peer, l.peer) } 116 | } 117 | -------------------------------------------------------------------------------- /scala/swing/GridPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | object GridPanel { 14 | val Adapt = 0 15 | } 16 | 17 | /** 18 | * A panel that lays out its contents in a uniform grid. 19 | * 20 | * @see java.awt.GridLayout 21 | */ 22 | class GridPanel(rows0: Int, cols0: Int) extends Panel with SequentialContainer.Wrapper { 23 | override lazy val peer = 24 | new javax.swing.JPanel(new java.awt.GridLayout(rows0, cols0)) with SuperMixin 25 | 26 | /*type Constraints = (Int, Int) 27 | 28 | protected def constraintsFor(comp: Component) = { 29 | assert(peer.getComponentOrientation.isHorizontal) 30 | val idx = contents.indexOf(comp) 31 | val (r, c) = (((idx-1)/columns)+1, ((idx-1)%columns)+1) 32 | if (peer.getComponentOrientation.isLeftToRight) (r, c) 33 | else (r, columns-c+1) 34 | } 35 | 36 | protected def add(c: Component, l: Constraints) { peer.add(c.peer, (l._1-1)*columns+l._2) } 37 | protected def areValid(c: Constraints): (Boolean, String) = 38 | ((c._1 > 0 && c._2 > 0), "Grid coordinates (row,col) must be >= 1 but where " + c)*/ 39 | 40 | private def layoutManager = peer.getLayout.asInstanceOf[java.awt.GridLayout] 41 | 42 | def rows: Int = layoutManager.getRows 43 | def rows_=(n: Int) { layoutManager.setRows(n) } 44 | def columns: Int = layoutManager.getColumns 45 | def columns_=(n: Int) { layoutManager.setColumns(n) } 46 | 47 | def vGap: Int = layoutManager.getVgap 48 | def vGap_=(n: Int) { layoutManager.setVgap(n) } 49 | def hGap: Int = layoutManager.getHgap 50 | def hGap_=(n: Int) { layoutManager.setHgap(n) } 51 | } 52 | -------------------------------------------------------------------------------- /scala/swing/Label.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing._ 14 | import scala.swing.Swing._ 15 | 16 | /** 17 | * A label component that display either a text, an icon, or both. 18 | * 19 | * @see javax.swing.JLabel 20 | */ 21 | class Label(text0: String, icon0: Icon, align: Alignment.Value) extends Component { 22 | override lazy val peer: JLabel = 23 | new JLabel(text0, toNullIcon(icon0), align.id) with SuperMixin 24 | 25 | def this() = this("", EmptyIcon, Alignment.Center) 26 | def this(s: String) = this(s, EmptyIcon, Alignment.Center) 27 | def text: String = peer.getText 28 | def text_=(s: String) = peer.setText(s) 29 | def icon: Icon = peer.getIcon 30 | def icon_=(i: Icon) = peer.setIcon(i) 31 | 32 | /** 33 | * The alignment of the label's contents relative to its bounding box. 34 | */ 35 | def xAlignment: Alignment.Value = Alignment(peer.getHorizontalAlignment) 36 | def xAlignment_=(x: Alignment.Value) { peer.setHorizontalAlignment(x.id) } 37 | def yAlignment: Alignment.Value = Alignment(peer.getVerticalAlignment) 38 | def yAlignment_=(x: Alignment.Value) { peer.setVerticalAlignment(x.id) } 39 | 40 | /** @see javax.swing.JLabel#getHorizontalAlignment() */ 41 | def horizontalAlignment: Alignment.Value = Alignment(peer.getHorizontalAlignment) 42 | /** @see javax.swing.JLabel#setHorizontalAlignment() */ 43 | def horizontalAlignment_=(x: Alignment.Value) { peer.setHorizontalAlignment(x.id) } 44 | 45 | def verticalAlignment: Alignment.Value = Alignment(peer.getVerticalAlignment) 46 | def verticalAlignment_=(x: Alignment.Value) { peer.setVerticalAlignment(x.id) } 47 | 48 | def horizontalTextPosition: Alignment.Value = Alignment(peer.getHorizontalTextPosition) 49 | def horizontalTextPosition_=(x: Alignment.Value) { peer.setHorizontalTextPosition(x.id) } 50 | 51 | def verticalTextPosition: Alignment.Value = Alignment(peer.getVerticalTextPosition) 52 | def verticalTextPosition_=(x: Alignment.Value) { peer.setVerticalTextPosition(x.id) } 53 | 54 | def disabledIcon: Icon = peer.getDisabledIcon 55 | def disabledIcon_=(icon: Icon) { peer.setDisabledIcon(icon) } 56 | 57 | def iconTextGap: Int = peer.getIconTextGap 58 | def iconTextGap_=(gap: Int) { peer.setIconTextGap(gap) } 59 | 60 | def displayedMnemonicIndex: Int = peer.getDisplayedMnemonicIndex 61 | def displayedMnemonicIndex_=(index: Int) { peer.setDisplayedMnemonicIndex(index) } 62 | } 63 | -------------------------------------------------------------------------------- /scala/swing/LayoutContainer.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.JComponent 14 | import scala.collection.mutable.Map 15 | 16 | /**

17 | * A container that associates layout constraints of member type 18 | * Constraints with its children. See GridBagPanel 19 | * for an example container with custom constraints. 20 | *

21 | * 22 | * @note [Java Swing] In scala.swing, panels and layout managers are 23 | * combined into subclasses of this base class. This approach allows for typed 24 | * component constraints. 25 | */ 26 | trait LayoutContainer extends Container.Wrapper { 27 | /** 28 | * The type of component constraints for this container. 29 | */ 30 | type Constraints <: AnyRef 31 | 32 | /** 33 | * Obtains the constraints for the given component from the underlying 34 | * Swing layout manager. 35 | */ 36 | protected def constraintsFor(c: Component): Constraints 37 | /** 38 | * Checks whether the given constraints are valid. Additionally returns 39 | * an error string that is only fetched if the constraints aren't valid. 40 | */ 41 | protected def areValid(c: Constraints): (Boolean, String) 42 | /** 43 | * Adds a component with the given constraints to the underlying layout 44 | * manager and the component peer. This method needs to interact properly 45 | * with method `constraintsFor`, i.e., it might need to remove previously 46 | * held components in order to maintain layout consistency. See `BorderPanel` 47 | * for an example. 48 | */ 49 | protected def add(comp: Component, c: Constraints) 50 | 51 | /** 52 | * A map of components to the associated layout constraints. 53 | * Any element in this map is automatically added to the contents of this 54 | * panel. Therefore, specifying the layout of a component via 55 | * 56 | * layout(myComponent) = myConstraints 57 | * 58 | * also ensures that myComponent is properly added to this container. 59 | */ 60 | def layout: Map[Component, Constraints] = new Map[Component, Constraints] { 61 | def -= (c: Component): this.type = { _contents -= c; this } 62 | def += (cl: (Component, Constraints)): this.type = { update(cl._1, cl._2); this } 63 | override def update (c: Component, l: Constraints) { 64 | val (v, msg) = areValid(l) 65 | if (!v) throw new IllegalArgumentException(msg) 66 | add(c, l) 67 | this 68 | } 69 | def get(c: Component) = Option(constraintsFor(c)) 70 | override def size = peer.getComponentCount 71 | def iterator: Iterator[(Component, Constraints)] = 72 | peer.getComponents.iterator.map { c => 73 | val comp = UIElement.cachedWrapper[Component](c.asInstanceOf[JComponent]) 74 | (comp, constraintsFor(comp)) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /scala/swing/MainFrame.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | 15 | /** 16 | * A frame that can be used for main application windows. Shuts down the 17 | * framework and quits the application when closed. 18 | */ 19 | class MainFrame extends Frame { 20 | override def closeOperation { System.exit(0) } 21 | } 22 | -------------------------------------------------------------------------------- /scala/swing/Menu.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import scala.collection.mutable._ 14 | import javax.swing._ 15 | 16 | object MenuBar { 17 | case object NoMenuBar extends MenuBar 18 | } 19 | 20 | /** 21 | * A menu bar. Each window can contain at most one. Contains a number of menus. 22 | * 23 | * @see javax.swing.JMenuBar 24 | */ 25 | class MenuBar extends Component with SequentialContainer.Wrapper { 26 | override lazy val peer: JMenuBar = new JMenuBar with SuperMixin 27 | 28 | def menus: Seq[Menu] = contents.filter(_.isInstanceOf[Menu]).map(_.asInstanceOf[Menu]) 29 | 30 | // Not implemented by Swing 31 | //def helpMenu: Menu = UIElement.cachedWrapper(peer.getHelpMenu) 32 | //def helpMenu_=(m: Menu) { peer.setHelpMenu(m.peer) } 33 | } 34 | 35 | /** 36 | * A menu item that can be used in a menu. 37 | * 38 | * @see javax.swing.JMenuItem 39 | */ 40 | class MenuItem(title0: String) extends AbstractButton { 41 | override lazy val peer: JMenuItem = new JMenuItem(title0) 42 | def this(a: Action) = { 43 | this("") 44 | action = a 45 | } 46 | } 47 | 48 | /** 49 | * A menu. Contains menu items. Being a menu item itself, menus can be nested. 50 | * 51 | * @see javax.swing.JMenu 52 | */ 53 | class Menu(title0: String) extends MenuItem(title0) with SequentialContainer.Wrapper { self: Menu => 54 | override lazy val peer: JMenu = new JMenu(title0) 55 | } 56 | 57 | /** 58 | * A menu item with a radio button. 59 | * 60 | * @see javax.swing.JRadioButtonMenuItem 61 | */ 62 | class RadioMenuItem(title0: String) extends MenuItem(title0) { 63 | override lazy val peer: JRadioButtonMenuItem = new JRadioButtonMenuItem(title0) 64 | } 65 | /** 66 | * A menu item with a check box. 67 | * 68 | * @see javax.swing.JCheckBoxMenuItem 69 | */ 70 | class CheckMenuItem(title0: String) extends MenuItem(title0) { 71 | override lazy val peer: JCheckBoxMenuItem = new JCheckBoxMenuItem(title0) 72 | } 73 | -------------------------------------------------------------------------------- /scala/swing/Orientable.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | object Orientable { 14 | trait Wrapper extends Oriented.Wrapper with Orientable { 15 | def orientation_=(o: Orientation.Value) { peer.setOrientation(o.id) } 16 | } 17 | } 18 | 19 | /** 20 | * An Oriented whose orientation can be changed. 21 | */ 22 | trait Orientable extends Oriented { 23 | def orientation_=(o: Orientation.Value) 24 | } 25 | -------------------------------------------------------------------------------- /scala/swing/Orientation.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.Adjustable._ 14 | 15 | object Orientation extends Enumeration { 16 | val Horizontal = Value(HORIZONTAL) 17 | val Vertical = Value(VERTICAL) 18 | val NoOrientation = Value(NO_ORIENTATION) 19 | } 20 | -------------------------------------------------------------------------------- /scala/swing/Oriented.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | object Oriented { 14 | trait Wrapper extends Oriented { 15 | def peer: OrientedMixin 16 | 17 | /* 18 | * Need to revert to structural type, since scroll bars are oriented 19 | * and these are created by scroll panes. Shouldn't be a bootleneck. 20 | */ 21 | protected type OrientedMixin = { 22 | def getOrientation(): Int 23 | def setOrientation(n: Int) 24 | } 25 | def orientation: Orientation.Value = Orientation(peer.getOrientation) 26 | } 27 | } 28 | 29 | /** 30 | * Something that can have an orientation. 31 | */ 32 | trait Oriented { 33 | def orientation: Orientation.Value 34 | } 35 | -------------------------------------------------------------------------------- /scala/swing/Panel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | /** 14 | * A component that can contain other components. 15 | * 16 | * @see javax.swing.JPanel 17 | */ 18 | abstract class Panel extends Component with Container.Wrapper { 19 | override lazy val peer: javax.swing.JPanel = new javax.swing.JPanel with SuperMixin 20 | } 21 | -------------------------------------------------------------------------------- /scala/swing/PasswordField.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | import java.awt.event._ 16 | 17 | /** 18 | * A password field, that displays a replacement character for each character in the password. 19 | * 20 | * @see javax.swing.JPasswordField 21 | */ 22 | class PasswordField(text0: String, columns0: Int) extends TextField(text0, columns0) { 23 | override lazy val peer: JPasswordField = new JPasswordField(text0, columns0) with SuperMixin 24 | def this(text: String) = this(text, 0) 25 | def this(columns: Int) = this("", columns) 26 | def this() = this("") 27 | 28 | def echoChar: Char = peer.getEchoChar 29 | def echoChar_=(c: Char) = peer.setEchoChar(c) 30 | 31 | /** 32 | * The text property should not be used on a password field for 33 | * security reasons. 34 | */ 35 | override def text: String = "" 36 | override def text_=(s: String) {} 37 | def password: Array[Char] = peer.getPassword 38 | } 39 | -------------------------------------------------------------------------------- /scala/swing/ProgressBar.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | 15 | /** 16 | * A bar indicating progress of some action. Can be in indeterminate mode, 17 | * in which it indicates that the action is in progress (usually by some 18 | * animation) but does not indicate the amount of work done or to be done. 19 | * 20 | * @see javax.swing.JProgressBar 21 | */ 22 | class ProgressBar extends Component with Orientable.Wrapper { 23 | override lazy val peer: javax.swing.JProgressBar = 24 | new javax.swing.JProgressBar with SuperMixin 25 | 26 | def min: Int = peer.getMinimum 27 | def min_=(v: Int) { peer.setMinimum(v) } 28 | def max: Int = peer.getMaximum 29 | def max_=(v: Int) { peer.setMaximum(v) } 30 | def value: Int = peer.getValue 31 | def value_=(v: Int) { peer.setValue(v) } 32 | 33 | def labelPainted: Boolean = peer.isStringPainted 34 | def labelPainted_=(v: Boolean) { peer.setStringPainted(v) } 35 | 36 | def label: String = peer.getString 37 | def label_=(v: String) = peer.setString(v) 38 | 39 | def indeterminate: Boolean = peer.isIndeterminate 40 | def indeterminate_=(v: Boolean) { peer.setIndeterminate(v) } 41 | 42 | def paintBorder: Boolean = peer.isBorderPainted 43 | def paintBorder(v: Boolean) { peer.setBorderPainted(v) } 44 | } 45 | -------------------------------------------------------------------------------- /scala/swing/Publisher.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import scala.collection._ 14 | import scala.collection.mutable.{Buffer, HashSet, Set} 15 | import event.Event 16 | 17 | /**

18 | * Notifies registered reactions when an event is published. Publishers are 19 | * also reactors and listen to themselves per default as a convenience. 20 | *

21 | *

22 | * In order to reduce memory leaks, reactions are weakly referenced by default, 23 | * unless they implement Reactions.StronglyReferenced. That way, 24 | * the lifetime of reactions are more easily bound to the registering object, 25 | * which are reactors in common client code and hold strong references to their 26 | * reactions. As a result, reactors can be garbage collected even though they 27 | * still have reactions registered at some publisher, but not vice versa 28 | * since reactors (strongly) reference publishers they are interested in. 29 | *

30 | */ 31 | trait Publisher extends Reactor { 32 | import Reactions._ 33 | 34 | protected val listeners = new RefSet[Reaction] { 35 | import scala.ref._ 36 | val underlying = new HashSet[Reference[Reaction]] 37 | protected def Ref(a: Reaction) = a match { 38 | case a: StronglyReferenced => new StrongReference[Reaction](a) with super.Ref[Reaction] 39 | case _ => new WeakReference[Reaction](a, referenceQueue) with super.Ref[Reaction] 40 | } 41 | } 42 | 43 | private[swing] def subscribe(listener: Reaction) { listeners += listener } 44 | private[swing] def unsubscribe(listener: Reaction) { listeners -= listener } 45 | 46 | /** 47 | * Notify all registered reactions. 48 | */ 49 | def publish(e: Event) { for (l <- listeners) l(e) } 50 | 51 | listenTo(this) 52 | } 53 | 54 | /** 55 | * A publisher that subscribes itself to an underlying event source not before the first 56 | * reaction is installed. Can unsubscribe itself when the last reaction is uninstalled. 57 | */ 58 | private[swing] trait LazyPublisher extends Publisher { 59 | import Reactions._ 60 | 61 | protected def onFirstSubscribe() 62 | protected def onLastUnsubscribe() 63 | 64 | override def subscribe(listener: Reaction) { 65 | if(listeners.size == 1) onFirstSubscribe() 66 | super.subscribe(listener) 67 | } 68 | override def unsubscribe(listener: Reaction) { 69 | super.unsubscribe(listener) 70 | if(listeners.size == 1) onLastUnsubscribe() 71 | } 72 | } 73 | 74 | 75 | 76 | import scala.ref._ 77 | 78 | private[swing] trait SingleRefCollection[+A <: AnyRef] extends Iterable[A] { self => 79 | 80 | trait Ref[+A <: AnyRef] extends Reference[A] { 81 | override def hashCode() = { 82 | val v = get 83 | if (v == None) 0 else v.get.## 84 | } 85 | override def equals(that: Any) = that match { 86 | case that: ReferenceWrapper[_] => 87 | val v1 = this.get 88 | val v2 = that.get 89 | v1 == v2 90 | case _ => false 91 | } 92 | } 93 | 94 | //type Ref <: Reference[A] // TODO: could use higher kinded types, but currently crashes 95 | protected[this] def Ref(a: A): Ref[A] 96 | protected[this] val referenceQueue = new ReferenceQueue[A] 97 | 98 | protected val underlying: Iterable[Reference[A]] 99 | 100 | def purgeReferences() { 101 | var ref = referenceQueue.poll 102 | while (ref != None) { 103 | removeReference(ref.get.asInstanceOf[Reference[A]]) 104 | ref = referenceQueue.poll 105 | } 106 | } 107 | 108 | protected[this] def removeReference(ref: Reference[A]) 109 | 110 | def iterator = new Iterator[A] { 111 | private val elems = self.underlying.iterator 112 | private var hd: A = _ 113 | private var ahead: Boolean = false 114 | private def skip: Unit = 115 | while (!ahead && elems.hasNext) { 116 | // make sure we have a reference to the next element, 117 | // otherwise it might be garbage collected 118 | val next = elems.next.get 119 | ahead = next != None 120 | if (ahead) hd = next.get 121 | } 122 | def hasNext: Boolean = { skip; ahead } 123 | def next(): A = 124 | if (hasNext) { ahead = false; hd } 125 | else throw new NoSuchElementException("next on empty iterator") 126 | } 127 | } 128 | 129 | private[swing] class StrongReference[+T <: AnyRef](value: T) extends Reference[T] { 130 | private[this] var ref: Option[T] = Some(value) 131 | def isValid: Boolean = ref != None 132 | def apply(): T = ref.get 133 | def get : Option[T] = ref 134 | override def toString = get.map(_.toString).getOrElse("") 135 | def clear() { ref = None } 136 | def enqueue(): Boolean = false 137 | def isEnqueued(): Boolean = false 138 | } 139 | 140 | abstract class RefBuffer[A <: AnyRef] extends Buffer[A] with SingleRefCollection[A] { self => 141 | protected val underlying: Buffer[Reference[A]] 142 | 143 | def +=(el: A): this.type = { purgeReferences(); underlying += Ref(el); this } 144 | def +=:(el: A) = { purgeReferences(); Ref(el) +=: underlying; this } 145 | def remove(el: A) { underlying -= Ref(el); purgeReferences(); } 146 | def remove(n: Int) = { val el = apply(n); remove(el); el } 147 | def insertAll(n: Int, iter: Iterable[A]) { 148 | purgeReferences() 149 | underlying.insertAll(n, iter.view.map(Ref(_))) 150 | } 151 | def update(n: Int, el: A) { purgeReferences(); underlying(n) = Ref(el) } 152 | def apply(n: Int) = { 153 | purgeReferences() 154 | var el = underlying(n).get 155 | while (el == None) { 156 | purgeReferences(); el = underlying(n).get 157 | } 158 | el.get 159 | } 160 | 161 | def length = { purgeReferences(); underlying.length } 162 | def clear() { underlying.clear(); purgeReferences() } 163 | 164 | protected[this] def removeReference(ref: Reference[A]) { underlying -= ref } 165 | } 166 | 167 | private[swing] abstract class RefSet[A <: AnyRef] extends Set[A] with SingleRefCollection[A] { self => 168 | protected val underlying: Set[Reference[A]] 169 | 170 | def -=(el: A): this.type = { underlying -= Ref(el); purgeReferences(); this } 171 | def +=(el: A): this.type = { purgeReferences(); underlying += Ref(el); this } 172 | def contains(el: A): Boolean = { purgeReferences(); underlying.contains(Ref(el)) } 173 | override def size = { purgeReferences(); underlying.size } 174 | 175 | protected[this] def removeReference(ref: Reference[A]) { underlying -= ref } 176 | } 177 | -------------------------------------------------------------------------------- /scala/swing/RadioButton.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing._ 14 | 15 | /** 16 | * A two state button that is usually used in a ButtonGroup 17 | * together with other RadioButtons, in order to indicate 18 | * that at most one of them can be selected. 19 | * 20 | * @see javax.swing.JRadioButton 21 | */ 22 | class RadioButton(text0: String) extends ToggleButton { 23 | override lazy val peer: JRadioButton = new JRadioButton(text0) with SuperMixin 24 | def this() = this("") 25 | } 26 | -------------------------------------------------------------------------------- /scala/swing/Reactions.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event.Event 14 | import scala.collection.mutable.{Buffer, ListBuffer} 15 | 16 | object Reactions { 17 | import scala.ref._ 18 | 19 | class Impl extends Reactions { 20 | private val parts: Buffer[Reaction] = new ListBuffer[Reaction] 21 | def isDefinedAt(e: Event) = parts.exists(_ isDefinedAt e) 22 | def += (r: Reaction): this.type = { parts += r; this } 23 | def -= (r: Reaction): this.type = { parts -= r; this } 24 | def apply(e: Event) { 25 | for (p <- parts) if (p isDefinedAt e) p(e) 26 | } 27 | } 28 | 29 | type Reaction = PartialFunction[Event, Unit] 30 | 31 | /** 32 | * A Reaction implementing this trait is strongly referenced in the reaction list 33 | */ 34 | trait StronglyReferenced 35 | 36 | class Wrapper(listener: Any)(r: Reaction) extends Reaction with StronglyReferenced with Proxy { 37 | def self = listener 38 | def isDefinedAt(e: Event) = r.isDefinedAt(e) 39 | def apply(e: Event) { r(e) } 40 | } 41 | } 42 | 43 | /** 44 | * Used by reactors to let clients register custom event reactions. 45 | */ 46 | abstract class Reactions extends Reactions.Reaction { 47 | /** 48 | * Add a reaction. 49 | */ 50 | def += (r: Reactions.Reaction): this.type 51 | 52 | /** 53 | * Remove the given reaction. 54 | */ 55 | def -= (r: Reactions.Reaction): this.type 56 | } 57 | -------------------------------------------------------------------------------- /scala/swing/Reactor.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | /** 14 | * The counterpart to publishers. Listens to events from registered publishers. 15 | */ 16 | trait Reactor { 17 | /** 18 | * All reactions of this reactor. 19 | */ 20 | val reactions: Reactions = new Reactions.Impl 21 | /** 22 | * Listen to the given publisher as long as deafTo isn't called for 23 | * them. 24 | */ 25 | def listenTo(ps: Publisher*) = for (p <- ps) p.subscribe(reactions) 26 | /** 27 | * Installed reaction won't receive events from the given publisher anylonger. 28 | */ 29 | def deafTo(ps: Publisher*) = for (p <- ps) p.unsubscribe(reactions) 30 | } 31 | -------------------------------------------------------------------------------- /scala/swing/RichWindow.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.{Window => AWTWindow, Frame => AWTFrame} 14 | import javax.swing._ 15 | import Swing._ 16 | 17 | object RichWindow { 18 | /** 19 | * Mixin this trait if you want an undecorated window. 20 | */ 21 | trait Undecorated extends RichWindow { 22 | // we do a mixin here, since setUndecorated is only allowed to be called 23 | // when the component is not displayable. 24 | peer.setUndecorated(true) 25 | } 26 | } 27 | 28 | /** 29 | * A window that adds some functionality to the plain Window class and serves as 30 | * the common base class for frames and dialogs. 31 | * 32 | * Implementation note: this class is sealed since we need to know that a rich 33 | * window is either a dialog or a frame at some point. 34 | */ 35 | sealed trait RichWindow extends Window { 36 | def peer: AWTWindow with InterfaceMixin 37 | 38 | trait InterfaceMixin extends super.InterfaceMixin { 39 | def getJMenuBar: JMenuBar 40 | def setJMenuBar(b: JMenuBar) 41 | def setUndecorated(b: Boolean) 42 | def setTitle(s: String) 43 | def getTitle: String 44 | def setResizable(b: Boolean) 45 | def isResizable: Boolean 46 | } 47 | 48 | def title: String = peer.getTitle 49 | def title_=(s: String) = peer.setTitle(s) 50 | 51 | /** 52 | * The menu bar of this frame or `NoMenuBar` if no menu bar is set. 53 | */ 54 | def menuBar: MenuBar = { 55 | val m = UIElement.cachedWrapper[MenuBar](peer.getJMenuBar) 56 | if (m != null) m else MenuBar.NoMenuBar 57 | } 58 | /** 59 | * Set the current menu bar of this frame. Pass `NoMenuBar` if this frame 60 | * should not show a menu bar. 61 | */ 62 | def menuBar_=(m: MenuBar) = 63 | peer.setJMenuBar(if(m == MenuBar.NoMenuBar) null else m.peer) 64 | 65 | def resizable_=(b: Boolean) { peer.setResizable(b) } 66 | def resizable = peer.isResizable 67 | } 68 | 69 | /** 70 | * A window with decoration such as a title, border, and action buttons. 71 | * 72 | * An AWT window cannot be wrapped dynamically with this class, i.e., you cannot 73 | * write something like new Window { def peer = myAWTWindow } 74 | * 75 | * @see javax.swing.JFrame 76 | */ 77 | class Frame extends RichWindow { 78 | override lazy val peer: JFrame with InterfaceMixin = new JFrame with InterfaceMixin with SuperMixin 79 | 80 | protected trait SuperMixin extends JFrame { 81 | override protected def processWindowEvent(e: java.awt.event.WindowEvent) { 82 | super.processWindowEvent(e) 83 | if (e.getID() == java.awt.event.WindowEvent.WINDOW_CLOSING) 84 | closeOperation() 85 | } 86 | } 87 | 88 | def iconify() { peer.setExtendedState(peer.getExtendedState | AWTFrame.ICONIFIED) } 89 | def uniconify() { peer.setExtendedState(peer.getExtendedState & ~AWTFrame.ICONIFIED) } 90 | def iconified() { (peer.getExtendedState & AWTFrame.ICONIFIED) != 0 } 91 | def maximize() { peer.setExtendedState(peer.getExtendedState | AWTFrame.MAXIMIZED_BOTH) } 92 | def unmaximize() { peer.setExtendedState(peer.getExtendedState & ~AWTFrame.MAXIMIZED_BOTH) } 93 | def maximized() { (peer.getExtendedState & AWTFrame.MAXIMIZED_BOTH) != 0 } 94 | 95 | def iconImage: Image = peer.getIconImage 96 | def iconImage_=(i: Image) { peer.setIconImage(i) } 97 | } 98 | 99 | /** 100 | * Simple predefined dialogs. 101 | * 102 | * @see javax.swing.JOptionPane 103 | */ 104 | object Dialog { 105 | /** 106 | * The message type of a dialog. 107 | */ 108 | object Message extends Enumeration { 109 | val Error = Value(JOptionPane.ERROR_MESSAGE) 110 | val Info = Value(JOptionPane.INFORMATION_MESSAGE) 111 | val Warning = Value(JOptionPane.WARNING_MESSAGE) 112 | val Question = Value(JOptionPane.QUESTION_MESSAGE) 113 | val Plain = Value(JOptionPane.PLAIN_MESSAGE) 114 | } 115 | 116 | /** 117 | * The possible answers a user can select. 118 | */ 119 | object Options extends Enumeration { 120 | val Default = Value(JOptionPane.DEFAULT_OPTION) 121 | val YesNo = Value(JOptionPane.YES_NO_OPTION) 122 | val YesNoCancel = Value(JOptionPane.YES_NO_CANCEL_OPTION) 123 | val OkCancel = Value(JOptionPane.OK_CANCEL_OPTION) 124 | } 125 | 126 | /** 127 | * The selected result of dialog. 128 | */ 129 | object Result extends Enumeration { 130 | val Yes = Value(JOptionPane.YES_OPTION) 131 | val Ok = Yes 132 | val No = Value(JOptionPane.NO_OPTION) 133 | val Cancel = Value(JOptionPane.CANCEL_OPTION) 134 | val Closed = Value(JOptionPane.CLOSED_OPTION) 135 | } 136 | 137 | private def uiString(txt: String) = UIManager.getString(txt) 138 | 139 | def showConfirmation(parent: Component = null, 140 | message: Any, 141 | title: String = uiString("OptionPane.titleText"), 142 | optionType: Options.Value = Options.YesNo, 143 | messageType: Message.Value = Message.Question, 144 | icon: Icon = EmptyIcon): Result.Value = 145 | Result(JOptionPane.showConfirmDialog(nullPeer(parent), message, title, 146 | optionType.id, messageType.id, Swing.wrapIcon(icon))) 147 | 148 | def showOptions(parent: Component = null, 149 | message: Any, 150 | title: String = uiString("OptionPane.titleText"), 151 | optionType: Options.Value = Options.YesNo, 152 | messageType: Message.Value = Message.Question, 153 | icon: Icon = EmptyIcon, 154 | entries: Seq[Any], 155 | initial: Int): Result.Value = { 156 | val r = JOptionPane.showOptionDialog(nullPeer(parent), message, title, 157 | optionType.id, messageType.id, Swing.wrapIcon(icon), 158 | entries map toAnyRef toArray, entries(initial)) 159 | Result(r) 160 | } 161 | 162 | def showInput[A](parent: Component = null, 163 | message: Any, 164 | title: String = uiString("OptionPane.inputDialogTitle"), 165 | messageType: Message.Value = Message.Question, 166 | icon: Icon = EmptyIcon, 167 | entries: Seq[A] = Nil, 168 | initial: A): Option[A] = { 169 | val e = if (entries.isEmpty) null 170 | else entries map toAnyRef toArray 171 | val r = JOptionPane.showInputDialog(nullPeer(parent), message, title, 172 | messageType.id, Swing.wrapIcon(icon), 173 | e, initial) 174 | 175 | toOption[A](r) 176 | } 177 | def showMessage(parent: Component = null, 178 | message: Any, 179 | title: String = uiString("OptionPane.messageDialogTitle"), 180 | messageType: Message.Value = Message.Info, 181 | icon: Icon = EmptyIcon) { 182 | JOptionPane.showMessageDialog(nullPeer(parent), message, title, 183 | messageType.id, Swing.wrapIcon(icon)) 184 | } 185 | } 186 | 187 | /** 188 | * A dialog window. 189 | * 190 | * @see javax.swing.JDialog 191 | */ 192 | class Dialog(owner: Window) extends RichWindow { 193 | override lazy val peer: JDialog with InterfaceMixin = 194 | if (owner == null) new JDialog with InterfaceMixin 195 | else owner match { 196 | case f: Frame => new JDialog(f.peer) with InterfaceMixin 197 | case d: Dialog => new JDialog(d.peer) with InterfaceMixin 198 | } 199 | 200 | def this() = this(null) 201 | 202 | def modal_=(b: Boolean) { peer.setModal(b) } 203 | def modal = peer.isModal 204 | } 205 | 206 | -------------------------------------------------------------------------------- /scala/swing/RootPanel.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | /** 14 | * The root of a component hierarchy. Contains at most one component. 15 | * 16 | * @see javax.swing.RootPaneContainer 17 | */ 18 | trait RootPanel extends Container { 19 | def peer: java.awt.Component with javax.swing.RootPaneContainer 20 | 21 | /** 22 | * At most one component. 23 | */ 24 | def contents: Seq[Component] = 25 | if (peer.getContentPane.getComponentCount == 0) Nil 26 | else { 27 | val c = peer.getContentPane.getComponent(0).asInstanceOf[javax.swing.JComponent] 28 | List(UIElement.cachedWrapper[Component](c)) 29 | } 30 | 31 | def contents_=(c: Component) { 32 | if (peer.getContentPane.getComponentCount > 0) { 33 | val old = peer.getContentPane.getComponent(0) 34 | peer.getContentPane.remove(old) 35 | } 36 | peer.getContentPane.add(c.peer) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scala/swing/ScrollBar.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.{JScrollBar, BoundedRangeModel} 14 | import java.awt.event.{AdjustmentListener} 15 | 16 | object ScrollBar { 17 | def wrap(c: JScrollBar): ScrollBar = { 18 | val w = UIElement.cachedWrapper[ScrollBar](c) 19 | if (w != null) w 20 | else new ScrollBar { override lazy val peer = c } 21 | } 22 | } 23 | 24 | class ScrollBar extends Component with Orientable.Wrapper with Adjustable.Wrapper { 25 | override lazy val peer: JScrollBar = new JScrollBar with SuperMixin 26 | 27 | def valueIsAjusting = peer.getValueIsAdjusting 28 | def valueIsAjusting_=(b : Boolean) = peer.setValueIsAdjusting(b) 29 | 30 | // TODO: can we find a better interface? 31 | //def setValues(value: Int = this.value, visible: Int = visibleAmount, 32 | // min: Int = minimum, max: Int = maximum) = 33 | // peer.setValues(value, visible, min, max) 34 | 35 | // Not currently needed, requires wrapper for BoundedRangeModel 36 | // 37 | // def model = peer.getModel 38 | // def model_=(m : BoundedRangeModel) = peer.setModel(m) 39 | } 40 | -------------------------------------------------------------------------------- /scala/swing/ScrollPane.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.{JScrollPane, ScrollPaneConstants} 14 | 15 | object ScrollPane { 16 | object BarPolicy extends Enumeration { 17 | import ScrollPaneConstants._ 18 | val AsNeeded = new Value(HORIZONTAL_SCROLLBAR_AS_NEEDED, 19 | VERTICAL_SCROLLBAR_AS_NEEDED) 20 | val Never = new Value(HORIZONTAL_SCROLLBAR_NEVER, 21 | VERTICAL_SCROLLBAR_NEVER) 22 | val Always = new Value(HORIZONTAL_SCROLLBAR_ALWAYS, 23 | VERTICAL_SCROLLBAR_ALWAYS) 24 | 25 | def wrap(id: Int) = id match { 26 | case HORIZONTAL_SCROLLBAR_AS_NEEDED | VERTICAL_SCROLLBAR_AS_NEEDED => AsNeeded 27 | case HORIZONTAL_SCROLLBAR_NEVER | VERTICAL_SCROLLBAR_NEVER => Never 28 | case HORIZONTAL_SCROLLBAR_ALWAYS | VERTICAL_SCROLLBAR_ALWAYS => Always 29 | } 30 | class Value(val horizontalPeer: Int, val verticalPeer: Int) extends super.Val { 31 | override def id = horizontalPeer 32 | } 33 | } 34 | } 35 | 36 | /** 37 | * Can have at most a single child component, which will be put inside a canvas (the viewport) 38 | * that can be scrolled. 39 | * 40 | * @see javax.swing.JScrollPane 41 | */ 42 | class ScrollPane extends Component with Container { 43 | import ScrollPane._ 44 | 45 | override lazy val peer: JScrollPane = new JScrollPane with SuperMixin 46 | def this(c: Component) = { 47 | this() 48 | contents = c 49 | } 50 | def contents: Seq[Component] = 51 | List(UIElement.cachedWrapper[Component](peer.getViewport.getView.asInstanceOf[javax.swing.JComponent])) 52 | 53 | /** 54 | * Sets the single child. 55 | */ 56 | def contents_=(c: Component) { peer.setViewportView(c.peer) } 57 | 58 | /** 59 | * The component being displayed in this pane's row header. 60 | * 61 | * If you want to create a row header for lists or tables, you probably 62 | * want to let the row header be a list view with the same row height as 63 | * the viewport component. 64 | */ 65 | def rowHeaderView: Option[Component] = 66 | Option(peer.getRowHeader.getView) map UIElement.cachedWrapper[Component] 67 | def rowHeaderView_=(c: Component) = peer.setRowHeaderView(c.peer) 68 | def rowHeaderView_=(c: Option[Component]) = peer.setRowHeaderView(c map (_.peer) orNull) 69 | 70 | def columnHeaderView: Option[Component] = 71 | Option(peer.getColumnHeader.getView) map UIElement.cachedWrapper[Component] 72 | def columnHeaderView_=(c: Component) = peer.setColumnHeaderView(c.peer) 73 | def columnHeaderView_=(c: Option[Component]) = peer.setColumnHeaderView(c map (_.peer) orNull) 74 | 75 | def viewportView: Option[Component] = 76 | Option(peer.getViewport.getView) map UIElement.cachedWrapper[Component] 77 | def viewportView_=(c: Component) = peer.setViewportView(c.peer) 78 | def viewportView_=(c: Option[Component]) = peer.setViewportView(c map (_.peer) orNull) 79 | 80 | def verticalScrollBarPolicy = BarPolicy.wrap(peer.getVerticalScrollBarPolicy) 81 | def verticalScrollBarPolicy_=(p: BarPolicy.Value) = peer.setVerticalScrollBarPolicy(p.verticalPeer) 82 | 83 | def horizontalScrollBarPolicy = BarPolicy.wrap(peer.getHorizontalScrollBarPolicy) 84 | def horizontalScrollBarPolicy_=(p: BarPolicy.Value) = peer.setHorizontalScrollBarPolicy(p.horizontalPeer) 85 | 86 | def horizontalScrollBar = ScrollBar.wrap(peer.getHorizontalScrollBar) 87 | def verticalScrollBar = ScrollBar.wrap(peer.getVerticalScrollBar) 88 | } 89 | -------------------------------------------------------------------------------- /scala/swing/Scrollable.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | object Scrollable { 14 | trait Wrapper extends Scrollable { 15 | protected def scrollablePeer: javax.swing.Scrollable 16 | def preferredViewportSize = scrollablePeer.getPreferredScrollableViewportSize 17 | 18 | def tracksViewportHeight: Boolean = scrollablePeer.getScrollableTracksViewportHeight 19 | def tracksViewportWidth: Boolean = scrollablePeer.getScrollableTracksViewportWidth 20 | 21 | def blockIncrement(visibleRect: Rectangle, orientation: Orientation.Value, direction: Int): Int = 22 | scrollablePeer.getScrollableBlockIncrement(visibleRect, orientation.id, direction) 23 | 24 | def unitIncrement(visibleRect: Rectangle, orientation: Orientation.Value, direction: Int): Int = 25 | scrollablePeer.getScrollableUnitIncrement(visibleRect, orientation.id, direction) 26 | } 27 | } 28 | 29 | /** 30 | * A component that is specially suitable for being placed inside a 31 | * ScrollPane. 32 | * 33 | * @see javax.swing.Scrollable 34 | */ 35 | trait Scrollable extends Component { 36 | def preferredViewportSize: Dimension 37 | 38 | def tracksViewportHeight: Boolean 39 | def tracksViewportWidth: Boolean 40 | 41 | def blockIncrement(visibleRect: Rectangle, orientation: Orientation.Value, direction: Int): Int 42 | def unitIncrement(visibleRect: Rectangle, orientation: Orientation.Value, direction: Int): Int 43 | } 44 | -------------------------------------------------------------------------------- /scala/swing/Separator.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing._ 14 | 15 | /** 16 | * A bar that can be used a separator, most commonly in menus. 17 | * 18 | * @see javax.swing.JSeparator 19 | */ 20 | class Separator(o: Orientation.Value) extends Component with Oriented.Wrapper { 21 | override lazy val peer: JSeparator = new JSeparator(o.id) with SuperMixin 22 | def this() = this(Orientation.Horizontal) 23 | } 24 | -------------------------------------------------------------------------------- /scala/swing/SequentialContainer.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import scala.collection.mutable.Buffer 14 | 15 | object SequentialContainer { 16 | /** 17 | * Utility trait for wrapping sequential containers. 18 | */ 19 | trait Wrapper extends SequentialContainer with Container.Wrapper { 20 | override val contents: Buffer[Component] = new Content 21 | //def contents_=(c: Component*) { contents.clear(); contents ++= c } 22 | } 23 | } 24 | 25 | /** 26 | * A container for which a sequential order of children makes sense, such as 27 | * flow panels, or menus. Its contents are mutable. 28 | */ 29 | trait SequentialContainer extends Container { 30 | /** 31 | * The mutable child components of this container. The order matters and 32 | * usually indicates the layout of the children. 33 | */ 34 | override def contents: Buffer[Component] 35 | //def contents_=(c: Component*) 36 | } 37 | -------------------------------------------------------------------------------- /scala/swing/SimpleGUIApplication.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing._ 14 | 15 | /** 16 | * Extend this class for most simple UI applications. Clients need to implement the 17 | * top method. Framework initialization is done by this class. 18 | * 19 | * In order to conform to Swing's threading policy, never implement top or any additional 20 | * member that created Swing components as a value unless component creation happens on 21 | * the EDT (see Swing.onEDT and Swing.onEDTWait). Lazy values are okay for the same reason 22 | * if they are initialized on the EDT always. 23 | */ 24 | @deprecated("Use SimpleSwingApplication instead") abstract class SimpleGUIApplication extends GUIApplication { 25 | 26 | /** 27 | * A GUI application's version of the main method. Called by the default 28 | * main method implementation provided by this class. 29 | * Implement to return the top-level frame of this application. 30 | */ 31 | def top: Frame 32 | 33 | /** 34 | * Calls top, packs the frame, and displays it. 35 | */ 36 | def main(args: Array[String]) = run { 37 | val t = top 38 | t.pack() 39 | t.visible = true 40 | } 41 | 42 | def resourceFromClassloader(path: String): java.net.URL = 43 | this.getClass.getResource(path) 44 | 45 | def resourceFromUserDirectory(path: String): java.io.File = 46 | new java.io.File(util.Properties.userDir, path) 47 | } 48 | -------------------------------------------------------------------------------- /scala/swing/SimpleSwingApplication.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | 3 | abstract class SimpleSwingApplication extends SwingApplication { 4 | def top: Frame 5 | 6 | override def startup(args: Array[String]) { 7 | val t = top 8 | if (t.size == new Dimension(0,0)) t.pack() 9 | t.visible = true 10 | } 11 | 12 | def resourceFromClassloader(path: String): java.net.URL = 13 | this.getClass.getResource(path) 14 | 15 | def resourceFromUserDirectory(path: String): java.io.File = 16 | new java.io.File(util.Properties.userDir, path) 17 | } 18 | -------------------------------------------------------------------------------- /scala/swing/Slider.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import javax.swing.{JSlider, JLabel} 14 | import event._ 15 | 16 | /** 17 | * Lets users select a value from a given range. Visually, this is represented 18 | * as a draggable knob on a horizontal or vertical bar. 19 | * 20 | * Fires a ValueChanged event whenever the slider's value changes and 21 | * when the knob is released. 22 | * 23 | * @see javax.swing.JSlider 24 | */ 25 | class Slider extends Component with Orientable.Wrapper with Publisher { 26 | override lazy val peer: JSlider = new JSlider with SuperMixin 27 | 28 | def min: Int = peer.getMinimum 29 | def min_=(v: Int) { peer.setMinimum(v) } 30 | def max: Int = peer.getMaximum 31 | def max_=(v: Int) { peer.setMaximum(v) } 32 | def value: Int = peer.getValue 33 | def value_=(v: Int) { peer.setValue(v) } 34 | def extent: Int = peer.getExtent 35 | def extent_=(v: Int) { peer.setExtent(v) } 36 | 37 | def paintLabels: Boolean = peer.getPaintLabels 38 | def paintLabels_=(v: Boolean) { peer.setPaintLabels(v) } 39 | def paintTicks: Boolean = peer.getPaintTicks 40 | def paintTicks_=(v: Boolean) { peer.setPaintTicks(v) } 41 | def paintTrack: Boolean = peer.getPaintTrack 42 | def paintTrack_=(v: Boolean) { peer.setPaintTrack(v) } 43 | 44 | def snapToTicks: Boolean = peer.getSnapToTicks 45 | def snapToTicks_=(v: Boolean) { peer.setSnapToTicks(v) } 46 | 47 | def minorTickSpacing: Int = peer.getMinorTickSpacing 48 | def minorTickSpacing_=(v: Int) { peer.setMinorTickSpacing(v) } 49 | def majorTickSpacing: Int = peer.getMajorTickSpacing 50 | def majorTickSpacing_=(v: Int) { peer.setMajorTickSpacing(v) } 51 | 52 | def adjusting = peer.getValueIsAdjusting 53 | 54 | def labels: scala.collection.Map[Int, Label] = { 55 | val labelTable = peer.getLabelTable.asInstanceOf[java.util.Hashtable[Int, JLabel]] 56 | new scala.collection.JavaConversions.JMapWrapper(labelTable) 57 | .mapValues(v => UIElement.cachedWrapper[Label](v)) 58 | } 59 | def labels_=(l: scala.collection.Map[Int, Label]) { 60 | // TODO: do some lazy wrapping 61 | val table = new java.util.Hashtable[Any, Any] 62 | for ((k,v) <- l) table.put(k, v.peer) 63 | peer.setLabelTable(table) 64 | } 65 | 66 | peer.addChangeListener(new javax.swing.event.ChangeListener { 67 | def stateChanged(e: javax.swing.event.ChangeEvent) { 68 | publish(new ValueChanged(Slider.this)) 69 | } 70 | }) 71 | } 72 | -------------------------------------------------------------------------------- /scala/swing/SplitPane.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import Swing._ 15 | 16 | /** 17 | * A container with exactly two children. Arranges them side by side, either 18 | * horizontally or vertically. Displays a draggable divider component between 19 | * them that lets the user adjust the size ratio of the children. 20 | * 21 | * @see javax.swing.JSplitPane 22 | */ 23 | class SplitPane(o: Orientation.Value, left: Component, right: Component) extends Component with Container with Orientable.Wrapper { 24 | override lazy val peer: javax.swing.JSplitPane = 25 | new javax.swing.JSplitPane(o.id, left.peer, right.peer) with SuperMixin 26 | def this(o: Orientation.Value) = this(o, new Component {}, new Component {}) 27 | def this() = this(Orientation.Horizontal) 28 | 29 | def contents: Seq[Component] = List(leftComponent, rightComponent) 30 | def contents_=(left: Component, right: Component) { 31 | peer.setLeftComponent(left.peer) 32 | peer.setRightComponent(right.peer) 33 | } 34 | 35 | def topComponent: Component = 36 | UIElement.cachedWrapper[Component](peer.getTopComponent.asInstanceOf[javax.swing.JComponent]) 37 | def topComponent_=(c: Component) { peer.setTopComponent(c.peer) } 38 | def bottomComponent: Component = 39 | UIElement.cachedWrapper[Component](peer.getBottomComponent.asInstanceOf[javax.swing.JComponent]) 40 | def bottomComponent_=(c: Component) { peer.setBottomComponent(c.peer) } 41 | 42 | def leftComponent: Component = topComponent 43 | def leftComponent_=(c: Component) { topComponent = c } 44 | def rightComponent: Component = bottomComponent 45 | def rightComponent_=(c: Component) { bottomComponent = c } 46 | 47 | def dividerLocation: Int = peer.getDividerLocation 48 | def dividerLocation_=(n: Int) { peer.setDividerLocation(n) } 49 | 50 | /*def proportionalDividerLocation: Double = 51 | if (orientation == Orientation.Vertical) dividerLocation / (size.height - dividerSize) 52 | else dividerLocation / (size.width - dividerSize)*/ 53 | def dividerLocation_=(f: Double) { peer.setDividerLocation(f) } 54 | 55 | def dividerSize: Int = peer.getDividerSize 56 | def dividerSize_=(n: Int) { peer.setDividerSize(n) } 57 | def resizeWeight: Double = peer.getResizeWeight 58 | def resizeWeight_=(n: Double) { peer.setResizeWeight(n) } 59 | 60 | def resetToPreferredSizes() { peer.resetToPreferredSizes() } 61 | 62 | def oneTouchExpandable: Boolean = peer.isOneTouchExpandable 63 | def oneTouchExpandable_=(b: Boolean) { peer.setOneTouchExpandable(b) } 64 | def continuousLayout: Boolean = peer.isContinuousLayout 65 | def continuousLayout_=(b: Boolean) { peer.setContinuousLayout(b) } 66 | } 67 | -------------------------------------------------------------------------------- /scala/swing/Swing.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.event._ 14 | import javax.swing.event._ 15 | import javax.swing.border._ 16 | import javax.swing.{JComponent, Icon, BorderFactory, SwingUtilities} 17 | 18 | /** 19 | * Helpers for this package. 20 | */ 21 | object Swing { 22 | protected[swing] def toNoIcon(i: Icon): Icon = if(i == null) EmptyIcon else i 23 | protected[swing] def toNullIcon(i: Icon): Icon = if(i == EmptyIcon) null else i 24 | protected[swing] def nullPeer(c: Component) = if (c != null) c.peer else null 25 | 26 | implicit def pair2Dimension(p: (Int, Int)): Dimension = new Dimension(p._1, p._2) 27 | implicit def pair2Point(p: (Int, Int)): Point = new Point(p._1, p._2) 28 | implicit def pair2Point(p: (Int, Int, Int, Int)): Rectangle = new Rectangle(p._1, p._2, p._3, p._4) 29 | 30 | @inline final def Runnable(@inline block: =>Unit) = new Runnable { 31 | def run = block 32 | } 33 | final def ChangeListener(f: ChangeEvent => Unit) = new ChangeListener { 34 | def stateChanged(e: ChangeEvent) { f(e) } 35 | } 36 | final def ActionListener(f: ActionEvent => Unit) = new ActionListener { 37 | def actionPerformed(e: ActionEvent) { f(e) } 38 | } 39 | 40 | def Box(min: Dimension, pref: Dimension, max: Dimension) = new Component { 41 | override lazy val peer = new javax.swing.Box.Filler(min, pref, max) 42 | } 43 | def HGlue = new Component { 44 | override lazy val peer = javax.swing.Box.createHorizontalGlue.asInstanceOf[JComponent] 45 | } 46 | def VGlue = new Component { 47 | override lazy val peer = javax.swing.Box.createVerticalGlue.asInstanceOf[JComponent] 48 | } 49 | def Glue = new Component { 50 | override lazy val peer = javax.swing.Box.createGlue.asInstanceOf[JComponent] 51 | } 52 | def RigidBox(dim: Dimension) = new Component { 53 | override lazy val peer = javax.swing.Box.createRigidArea(dim).asInstanceOf[JComponent] 54 | } 55 | def HStrut(width: Int) = new Component { 56 | override lazy val peer = javax.swing.Box.createHorizontalStrut(width).asInstanceOf[JComponent] 57 | } 58 | def VStrut(height: Int) = new Component { 59 | override lazy val peer = javax.swing.Box.createVerticalStrut(height).asInstanceOf[JComponent] 60 | } 61 | 62 | def Icon(image: java.awt.Image) = new javax.swing.ImageIcon(image) 63 | def Icon(filename: String) = new javax.swing.ImageIcon(filename) 64 | def Icon(url: java.net.URL) = new javax.swing.ImageIcon(url) 65 | 66 | /** 67 | * The empty icon. Use this icon instead of null to indicate 68 | * that you don't want an icon. 69 | */ 70 | case object EmptyIcon extends Icon { 71 | def getIconHeight: Int = 0 72 | def getIconWidth: Int = 0 73 | def paintIcon(c: java.awt.Component, g: java.awt.Graphics, x: Int, y: Int) {} 74 | } 75 | 76 | def unwrapIcon(icon: Icon): Icon = if (icon == null) EmptyIcon else icon 77 | def wrapIcon(icon: Icon): Icon = if (icon == EmptyIcon) null else icon 78 | 79 | def EmptyBorder = BorderFactory.createEmptyBorder() 80 | def EmptyBorder(weight: Int) = 81 | BorderFactory.createEmptyBorder(weight, weight, weight, weight) 82 | def EmptyBorder(top: Int, left: Int, bottom: Int, right: Int) = 83 | BorderFactory.createEmptyBorder(top, left, bottom, right) 84 | 85 | def LineBorder(c: Color) = BorderFactory.createLineBorder(c) 86 | def LineBorder(c: Color, weight: Int) = BorderFactory.createLineBorder(c, weight) 87 | 88 | def BeveledBorder(kind: Embossing) = BorderFactory.createBevelBorder(kind.bevelPeer) 89 | def BeveledBorder(kind: Embossing, highlight: Color, shadow: Color) = 90 | BorderFactory.createBevelBorder(kind.bevelPeer, highlight, shadow) 91 | def BeveledBorder(kind: Embossing, 92 | highlightOuter: Color, highlightInner: Color, 93 | shadowOuter: Color, shadowInner: Color) = 94 | BorderFactory.createBevelBorder(kind.bevelPeer, 95 | highlightOuter, highlightInner, 96 | shadowOuter, shadowInner) 97 | 98 | sealed abstract class Embossing { 99 | def bevelPeer: Int 100 | def etchPeer: Int 101 | } 102 | case object Lowered extends Embossing { 103 | def bevelPeer = BevelBorder.LOWERED 104 | def etchPeer = javax.swing.border.EtchedBorder.LOWERED 105 | } 106 | case object Raised extends Embossing { 107 | def bevelPeer = BevelBorder.RAISED 108 | def etchPeer = javax.swing.border.EtchedBorder.RAISED 109 | } 110 | 111 | def EtchedBorder = BorderFactory.createEtchedBorder() 112 | def EtchedBorder(kind: Embossing) = 113 | BorderFactory.createEtchedBorder(kind.etchPeer) 114 | def EtchedBorder(kind: Embossing, highlight: Color, shadow: Color) = 115 | BorderFactory.createEtchedBorder(kind.etchPeer, highlight, shadow) 116 | 117 | def MatteBorder(top: Int, left: Int, bottom: Int, right: Int, color: Color) = 118 | BorderFactory.createMatteBorder(top, left, bottom, right, color) 119 | def MatteBorder(top: Int, left: Int, bottom: Int, right: Int, icon: Icon) = 120 | BorderFactory.createMatteBorder(top, left, bottom, right, icon) 121 | 122 | def CompoundBorder(outside: Border, inside: Border) = 123 | BorderFactory.createCompoundBorder(outside, inside) 124 | 125 | def TitledBorder(border: Border, title: String) = 126 | BorderFactory.createTitledBorder(border, title) 127 | 128 | /** 129 | * Schedule the given code to be executed on the Swing event dispatching 130 | * thread (EDT). Returns immediately. 131 | */ 132 | @inline final def onEDT(op: =>Unit) = SwingUtilities invokeLater Runnable(op) 133 | 134 | /** 135 | * Schedule the given code to be executed on the Swing event dispatching 136 | * thread (EDT). Blocks until after the code has been run. 137 | */ 138 | @inline final def onEDTWait(op: =>Unit) = SwingUtilities invokeAndWait Runnable(op) 139 | } 140 | -------------------------------------------------------------------------------- /scala/swing/SwingActor.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import scala.actors._ 14 | 15 | // Dummy to keep ant from recompiling on every run. 16 | trait SwingActor { } 17 | 18 | /*object SwingActor { 19 | /** 20 | * Similar to Actor.actor, but creates an instance of a SwingActor. 21 | */ 22 | def apply(body: => Unit): Actor = 23 | new SwingActor { def act() = body }.start() 24 | } 25 | 26 | /** 27 | * An actor that runs on the Swing event dispatching thread (EDT). 28 | */ 29 | abstract class SwingActor extends Actor { 30 | override val scheduler = new SchedulerAdapter { 31 | def execute(op: =>Unit) = Swing onEDT op 32 | def onTerminate(a: Actor)(op: => Unit) {} 33 | def terminated(a: Actor) {} 34 | } 35 | }*/ 36 | -------------------------------------------------------------------------------- /scala/swing/SwingApplication.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | 3 | abstract class SwingApplication extends Reactor { 4 | def main(args: Array[String]) = Swing.onEDT { startup(args) } 5 | 6 | def startup(args: Array[String]) 7 | def quit() { shutdown(); System.exit(0) } 8 | def shutdown() {} 9 | } 10 | -------------------------------------------------------------------------------- /scala/swing/SwingWorker.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | 3 | import scala.actors._ 4 | 5 | object SwingWorker { 6 | 7 | } 8 | 9 | abstract class SwingWorker extends Actor { 10 | def queue() { 11 | 12 | } 13 | 14 | def done() { 15 | 16 | } 17 | 18 | private var _cancelled = false 19 | def cancelled: Boolean = _cancelled 20 | def cancelled_=(b: Boolean) { _cancelled = b } 21 | } -------------------------------------------------------------------------------- /scala/swing/TabbedPane.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import scala.collection.mutable.Buffer 15 | import javax.swing.{JTabbedPane, JComponent} 16 | 17 | 18 | object TabbedPane { 19 | object Layout extends Enumeration { 20 | val Wrap = Value(JTabbedPane.WRAP_TAB_LAYOUT) 21 | val Scroll = Value(JTabbedPane.SCROLL_TAB_LAYOUT) 22 | } 23 | 24 | class Page protected[TabbedPane](parent0: TabbedPane, title0: String, content0: Component, tip0: String) extends Proxy { 25 | def self = content0 26 | 27 | def this(title0: String, content0: Component, tip0: String) = 28 | this(null, title0, content0, tip0) 29 | def this(title0: String, content0: Component) = 30 | this(title0, content0, "") 31 | content = content0 // first add component, *then* set other things 32 | title = title0 33 | tip = tip0 34 | 35 | protected[TabbedPane] var parent: TabbedPane = parent0 36 | 37 | protected var _title = title0 38 | def title: String = _title 39 | def title_=(t: String) { 40 | // beware to keep this order since, index depends on the _old_ title 41 | if (parent != null) parent.peer.setTitleAt(index, t) 42 | _title = t 43 | } 44 | protected var _content = content0 45 | def content: Component = _content//UIElement.cachedWrapper(peer.getComponentAt(index).asInstanceOf[JComponent]) 46 | def content_=(c: Component) { _content = c; if (parent != null) parent.peer.setComponentAt(index, c.peer) } 47 | protected var _tip = tip0 48 | def tip: String = _tip//peer.getToolTipTextAt(index) 49 | def tip_=(t: String) { _tip = t; if (parent != null) parent.peer.setToolTipTextAt(index, t) } 50 | protected var _enabled = true 51 | def enabled: Boolean = _enabled//peer.isEnabledAt(index) 52 | def enabled_=(b: Boolean) { _enabled = b; if (parent != null) parent.peer.setEnabledAt(index, b) } 53 | protected var _mnemonic = -1 54 | def mnemonic: Int = _mnemonic//peer.getMnemonicAt(index) 55 | def mnemonic_=(k: Int) { _mnemonic = k; if (parent != null) parent.peer.setMnemonicAt(index, k)} 56 | protected var _foreground: Color = null 57 | def foreground: Color = _foreground//peer.getForegroundAt(index) 58 | def foreground_=(c: Color) { _foreground = c; if (parent != null) parent.peer.setForegroundAt(index, c)} 59 | protected var _background: Color = null 60 | def background: Color = _background //peer.getBackgroundAt(index) 61 | def background_=(c: Color) { _background = c; if (parent != null) parent.peer.setBackgroundAt(index, c)} 62 | def bounds: Rectangle = parent.peer.getBoundsAt(index) 63 | 64 | // TODO: icon, disabledIcon 65 | 66 | def index = if(parent != null) parent.peer.indexOfTab(title) else 0//_index 67 | //protected[TabbedPane] var _index: Int = index0 68 | } 69 | } 70 | 71 | /** 72 | * Displays the contents of one of several pages at a time. For each page a tab is 73 | * visible at all times. The user can click on one of these tabs to move the 74 | * corresponding page to the front. 75 | * 76 | * @see javax.swing.JTabbedPane 77 | */ 78 | class TabbedPane extends Component with Publisher { 79 | override lazy val peer: JTabbedPane = new JTabbedPane with SuperMixin 80 | import TabbedPane._ 81 | 82 | object pages extends BufferWrapper[Page] { 83 | def runCount: Int = peer.getTabRunCount 84 | 85 | def remove(n: Int): Page = { 86 | val t = apply(n) 87 | peer.removeTabAt(n) 88 | t.parent = null 89 | //for(i <- n to length) apply(i)._index -= 1 90 | t 91 | } 92 | protected def insertAt(n: Int, t: Page) { 93 | //for(i <- n to length) apply(i)._index += 1 94 | t.parent = TabbedPane.this 95 | peer.insertTab(t.title, null, t.content.peer, t.tip, n) 96 | } 97 | 98 | def +=(t: Page): this.type = { t.parent = TabbedPane.this; peer.addTab(t.title, null, t.content.peer, t.tip); this } 99 | def length = peer.getTabCount 100 | def apply(n: Int) = new Page(TabbedPane.this, peer.getTitleAt(n), 101 | UIElement.cachedWrapper[Component](peer.getComponentAt(n).asInstanceOf[javax.swing.JComponent]), 102 | peer.getToolTipTextAt(n)) 103 | } 104 | 105 | def tabLayoutPolicy: Layout.Value = Layout(peer.getTabLayoutPolicy) 106 | def tabLayoutPolicy_=(p: Layout.Value) { peer.setTabLayoutPolicy(p.id) } 107 | 108 | 109 | def tabPlacement: Alignment.Value = Alignment(peer.getTabPlacement) 110 | /** 111 | * Possible values are Left, Right, Top, Bottom. 112 | */ 113 | def tabPlacement(b: Alignment.Value) { peer.setTabPlacement(b.id) } 114 | 115 | /** 116 | * The current page selection 117 | */ 118 | object selection extends Publisher { 119 | def page: Page = pages(index) 120 | def page_=(p: Page) { index = p.index } 121 | 122 | def index: Int = peer.getSelectedIndex 123 | def index_=(n: Int) { peer.setSelectedIndex(n) } 124 | 125 | peer.addChangeListener(new javax.swing.event.ChangeListener { 126 | def stateChanged(e: javax.swing.event.ChangeEvent) { 127 | publish(SelectionChanged(TabbedPane.this)) 128 | } 129 | }) 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /scala/swing/TextArea.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | import java.awt.event._ 16 | 17 | /** 18 | * A text component that allows multiline text input and display. 19 | * 20 | * @see javax.swing.JTextArea 21 | */ 22 | class TextArea(text0: String, rows0: Int, columns0: Int) extends TextComponent 23 | with TextComponent.HasColumns with TextComponent.HasRows { 24 | override lazy val peer: JTextArea = new JTextArea(text0, rows0, columns0) with SuperMixin 25 | def this(text: String) = this(text, 0, 0) 26 | def this(rows: Int, columns: Int) = this("", rows, columns) 27 | def this() = this("", 0, 0) 28 | 29 | // TODO: we could make contents StringBuilder-like 30 | def append(t: String) { peer.append(t) } 31 | 32 | def rows: Int = peer.getRows 33 | def rows_=(n: Int) = peer.setRows(n) 34 | def columns: Int = peer.getColumns 35 | def columns_=(n: Int) = peer.setColumns(n) 36 | 37 | def tabSize: Int = peer.getTabSize 38 | def tabSize_=(n: Int) = peer.setTabSize(n) 39 | def lineCount: Int = peer.getLineCount 40 | 41 | def lineWrap: Boolean = peer.getLineWrap 42 | def lineWrap_=(w: Boolean) = peer.setLineWrap(w) 43 | def wordWrap: Boolean = peer.getWrapStyleWord 44 | def wordWrap_=(w: Boolean) = peer.setWrapStyleWord(w) 45 | def charWrap: Boolean = !peer.getWrapStyleWord 46 | def charWrap_=(w: Boolean) = peer.setWrapStyleWord(!w) 47 | } 48 | -------------------------------------------------------------------------------- /scala/swing/TextComponent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | import javax.swing.text._ 16 | import javax.swing.event._ 17 | 18 | object TextComponent { 19 | trait HasColumns extends TextComponent { 20 | def columns: Int 21 | def columns_=(n: Int) 22 | } 23 | trait HasRows extends TextComponent { 24 | def rows: Int 25 | def rows_=(n: Int) 26 | } 27 | } 28 | 29 | /** 30 | * A component that allows some kind of text input and display. 31 | * 32 | * @see javax.swing.JTextComponent 33 | */ 34 | class TextComponent extends Component with Publisher { 35 | override lazy val peer: JTextComponent = new JTextComponent with SuperMixin {} 36 | def text: String = peer.getText 37 | def text_=(t: String) = peer.setText(t) 38 | 39 | class Caret extends Publisher { 40 | def dot: Int = peer.getCaret.getDot 41 | def dot_=(n: Int) { peer.getCaret.setDot(n) } 42 | def mark: Int = peer.getCaret.getMark 43 | def moveDot(n: Int) { peer.getCaret.moveDot(n) } 44 | def visible: Boolean = peer.getCaret.isVisible 45 | def visible_=(b: Boolean) { peer.getCaret.setVisible(b) } 46 | def selectionVisible: Boolean = peer.getCaret.isSelectionVisible 47 | def selectionVisible_=(b: Boolean) { peer.getCaret.setSelectionVisible(b) } 48 | def blinkRate: Int = peer.getCaret.getBlinkRate 49 | def blinkRate_=(n: Int) { peer.getCaret.setBlinkRate(n) } 50 | def color: Color = peer.getCaretColor 51 | def color_=(c: Color) = peer.setCaretColor(c) 52 | def position: Int = peer.getCaretPosition 53 | def position_=(p: Int) = peer.setCaretPosition(p) 54 | 55 | peer.addCaretListener { 56 | new CaretListener { 57 | def caretUpdate(e: CaretEvent) { publish(CaretUpdate(TextComponent.this)) } 58 | } 59 | } 60 | } 61 | 62 | object caret extends Caret 63 | 64 | def editable: Boolean = peer.isEditable 65 | def editable_=(x: Boolean) = peer.setEditable(x) 66 | def cut() { peer.cut() } 67 | def copy() { peer.copy() } 68 | def paste() { peer.paste() } 69 | def selected: String = peer.getSelectedText 70 | 71 | def selectAll() { peer.selectAll() } 72 | 73 | peer.getDocument.addDocumentListener(new DocumentListener { 74 | def changedUpdate(e:DocumentEvent) { publish(new ValueChanged(TextComponent.this)) } 75 | def insertUpdate(e:DocumentEvent) { publish(new ValueChanged(TextComponent.this)) } 76 | def removeUpdate(e:DocumentEvent) { publish(new ValueChanged(TextComponent.this)) } 77 | }) 78 | } 79 | -------------------------------------------------------------------------------- /scala/swing/TextField.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | import java.awt.event._ 16 | 17 | 18 | /*object TextField { 19 | object FocusLostBehavior extends Enumeration { 20 | val Revert = Value(JFormattedTextField.REVERT) 21 | val Commit = Value(JFormattedTextField.REVERT) 22 | val CommitOrRevert = Value(JFormattedTextField.REVERT) 23 | val Persist = Value(JFormattedTextField.REVERT) 24 | } 25 | }*/ 26 | 27 | /** 28 | * A text component that allows single line text input and display. 29 | * 30 | * @see javax.swing.JTextField 31 | */ 32 | class TextField(text0: String, columns0: Int) extends TextComponent with TextComponent.HasColumns with Action.Trigger.Wrapper { 33 | override lazy val peer: JTextField = new JTextField(text0, columns0) with SuperMixin 34 | def this(text: String) = this(text, 0) 35 | def this(columns: Int) = this("", columns) 36 | def this() = this("") 37 | 38 | def columns: Int = peer.getColumns 39 | def columns_=(n: Int) = peer.setColumns(n) 40 | 41 | /** @see javax.swing.JTextField#getHorizontalAlignment() */ 42 | def horizontalAlignment: Alignment.Value = Alignment(peer.getHorizontalAlignment) 43 | /** @see javax.swing.JTextField#setHorizontalAlignment() */ 44 | def horizontalAlignment_=(x: Alignment.Value) { peer.setHorizontalAlignment(x.id) } 45 | 46 | private lazy val actionListener = Swing.ActionListener { e => 47 | publish(EditDone(TextField.this)) 48 | } 49 | 50 | protected override def onFirstSubscribe { 51 | super.onFirstSubscribe 52 | peer.addActionListener(actionListener) 53 | peer.addFocusListener(new FocusAdapter { 54 | override def focusLost(e: java.awt.event.FocusEvent) { publish(EditDone(TextField.this)) } 55 | }) 56 | } 57 | 58 | protected override def onLastUnsubscribe { 59 | super.onLastUnsubscribe 60 | peer.removeActionListener(actionListener) 61 | } 62 | 63 | def verifier: String => Boolean = s => peer.getInputVerifier.verify(peer) 64 | def verifier_=(v: String => Boolean) { 65 | peer.setInputVerifier(new InputVerifier { 66 | private val old = peer.getInputVerifier 67 | def verify(c: JComponent) = v(text) 68 | override def shouldYieldFocus(c: JComponent) = old.shouldYieldFocus(c) 69 | }) 70 | } 71 | def shouldYieldFocus: String=>Boolean = s => peer.getInputVerifier.shouldYieldFocus(peer) 72 | def shouldYieldFocus_=(y: String=>Boolean) { 73 | peer.setInputVerifier(new InputVerifier { 74 | private val old = peer.getInputVerifier 75 | def verify(c: JComponent) = old.verify(c) 76 | override def shouldYieldFocus(c: JComponent) = y(text) 77 | }) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /scala/swing/ToggleButton.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import event._ 14 | import javax.swing._ 15 | 16 | /** 17 | * A two state button with a push button like user interface. 18 | * Usually used in tool bars. 19 | * 20 | * @see javax.swing.JToggleButton 21 | */ 22 | class ToggleButton(text0: String) extends AbstractButton { 23 | override lazy val peer: JToggleButton = new JToggleButton(text0) with SuperMixin 24 | def this() = this("") 25 | } 26 | -------------------------------------------------------------------------------- /scala/swing/UIElement.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.Cursor 14 | import event._ 15 | import scala.collection.mutable.HashMap 16 | import scala.ref._ 17 | import java.util.WeakHashMap 18 | 19 | object UIElement { 20 | private val ClientKey = "scala.swingWrapper" 21 | private[this] val wrapperCache = new WeakHashMap[java.awt.Component, WeakReference[UIElement]] 22 | 23 | private def cache(e: UIElement) = e.peer match { 24 | case p: javax.swing.JComponent => p.putClientProperty(ClientKey, e) 25 | case _ => wrapperCache.put(e.peer, new WeakReference(e)) 26 | } 27 | 28 | /** 29 | * Looks up the internal component cache for a wrapper of the given 30 | * Java Swing peer. If this method finds one of the given type `C`, 31 | * it will return that wrapper. Otherwise it returns `null`. This 32 | * method never throws an exception. 33 | * 34 | * Clients should be extremely careful with type parameter `C` and 35 | * its interaction with type inference. Better err on the side of caution 36 | * and explicitly specify `C`. 37 | */ 38 | private[swing] def cachedWrapper[C>:Null<:UIElement](c: java.awt.Component): C = { 39 | val w = c match { 40 | case c: javax.swing.JComponent => c.getClientProperty(ClientKey) 41 | case _ => wrapperCache.get(c) 42 | } 43 | try { w.asInstanceOf[C] } catch { case _ => null } 44 | } 45 | 46 | /** 47 | * Returns a wrapper for a given Java Swing peer. If there is a 48 | * compatible wrapper in use, this method will return it. 49 | * 50 | * `wrap` methods in companion objects of subclasses of UIElement have the 51 | * same behavior, except that they return more specific wrappers. 52 | */ 53 | def wrap(c: java.awt.Component): UIElement = { 54 | val w = cachedWrapper[UIElement](c) 55 | if (w != null) w 56 | else new UIElement { def peer = c } 57 | } 58 | } 59 | 60 | /** 61 | * The base trait of all user interface elements. Subclasses belong to one 62 | * of two groups: top-level elements such as windows and dialogs, or 63 | * Components. 64 | * 65 | * @note [Java Swing] This trait does not have an exact counterpart in 66 | * Java Swing. The peer is of type java.awt.Component since this is the 67 | * least common upper bound of possible underlying peers. 68 | * 69 | * @note [Implementation] A UIElement automatically adds itself to the 70 | * component cache on creation. 71 | * 72 | * @see java.awt.Component 73 | */ 74 | trait UIElement extends Proxy with LazyPublisher { 75 | /** 76 | * The underlying Swing peer. 77 | */ 78 | def peer: java.awt.Component 79 | def self = peer 80 | 81 | UIElement.cache(this) 82 | 83 | def foreground: Color = peer.getForeground 84 | def foreground_=(c: Color) = peer.setForeground(c) 85 | def background: Color = peer.getBackground 86 | def background_=(c: Color) = peer.setBackground(c) 87 | 88 | def minimumSize = peer.getMinimumSize 89 | def minimumSize_=(x: Dimension) = peer.setMinimumSize(x) 90 | def maximumSize = peer.getMaximumSize 91 | def maximumSize_=(x: Dimension) = peer.setMaximumSize(x) 92 | def preferredSize = peer.getPreferredSize 93 | def preferredSize_=(x: Dimension) = peer.setPreferredSize(x) 94 | 95 | def font: Font = peer.getFont 96 | def font_=(f: Font) = peer.setFont(f) 97 | 98 | def locationOnScreen = peer.getLocationOnScreen 99 | def location = peer.getLocation 100 | def bounds = peer.getBounds 101 | def size = peer.getSize 102 | @deprecated("Explicit size assignement for UIElements is not supported anymore. " + 103 | "Use a layout manager or subclass Window.") 104 | def size_=(dim: Dimension) = peer.setSize(dim) 105 | 106 | def locale = peer.getLocale 107 | def toolkit = peer.getToolkit 108 | 109 | def cursor: Cursor = peer.getCursor 110 | def cursor_=(c: Cursor) { peer.setCursor(c) } 111 | 112 | def visible: Boolean = peer.isVisible 113 | def visible_=(b: Boolean) { peer.setVisible(b) } 114 | def showing: Boolean = peer.isShowing 115 | def displayable: Boolean = peer.isDisplayable 116 | 117 | def repaint() { peer.repaint } 118 | def repaint(rect: Rectangle) { peer.repaint(rect.x, rect.y, rect.width, rect.height) } 119 | def ignoreRepaint: Boolean = peer.getIgnoreRepaint 120 | def ignoreRepaint_=(b: Boolean) { peer.setIgnoreRepaint(b) } 121 | 122 | protected def onFirstSubscribe { 123 | peer.addComponentListener(new java.awt.event.ComponentListener { 124 | def componentHidden(e: java.awt.event.ComponentEvent) { 125 | publish(UIElementHidden(UIElement.this)) 126 | } 127 | def componentShown(e: java.awt.event.ComponentEvent) { 128 | publish(UIElementShown(UIElement.this)) 129 | } 130 | def componentMoved(e: java.awt.event.ComponentEvent) { 131 | publish(UIElementMoved(UIElement.this)) 132 | } 133 | def componentResized(e: java.awt.event.ComponentEvent) { 134 | publish(UIElementResized(UIElement.this)) 135 | } 136 | }) 137 | } 138 | protected def onLastUnsubscribe {} 139 | } 140 | -------------------------------------------------------------------------------- /scala/swing/Window.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | 13 | import java.awt.{Window => AWTWindow} 14 | import event._ 15 | import javax.swing._ 16 | 17 | /** 18 | * A window with decoration such as a title, border, and action buttons. 19 | * 20 | * An AWT window cannot be wrapped dynamically with this class, i.e., you cannot 21 | * write something like new Window { def peer = myAWTWindow } 22 | * 23 | * @see javax.swing.JFrame 24 | */ 25 | abstract class Window extends UIElement with RootPanel with Publisher { outer => 26 | def peer: AWTWindow with InterfaceMixin 27 | 28 | protected trait InterfaceMixin extends javax.swing.RootPaneContainer 29 | 30 | /** 31 | * This method is called when the window is closing, after all other window 32 | * event listeners have been processed. 33 | */ 34 | def closeOperation() {} 35 | 36 | override def contents_=(c: Component) { 37 | super.contents_=(c) 38 | peer.pack() // pack also validates, which is generally required after an add 39 | } 40 | def defaultButton: Option[Button] = 41 | toOption(peer.getRootPane.getDefaultButton) map UIElement.cachedWrapper[Button] 42 | def defaultButton_=(b: Button) { 43 | peer.getRootPane.setDefaultButton(b.peer) 44 | } 45 | def defaultButton_=(b: Option[Button]) { 46 | peer.getRootPane.setDefaultButton(b map (_.peer) orNull) 47 | } 48 | 49 | def dispose() { peer.dispose() } 50 | 51 | def pack(): this.type = { peer.pack(); this } 52 | 53 | def setLocationRelativeTo(c: UIElement) { peer.setLocationRelativeTo(c.peer) } 54 | def centerOnScreen() { peer.setLocationRelativeTo(null) } 55 | def location_=(p: Point) { peer.setLocation(p) } 56 | override def size_=(size: Dimension) { peer.setSize(size) } 57 | def bounds_=(rect: Rectangle) { peer.setBounds(rect) } 58 | 59 | def owner: Window = UIElement.cachedWrapper[Window](peer.getOwner) 60 | 61 | def open() { peer setVisible true } 62 | def close() { peer setVisible false } 63 | 64 | peer.addWindowListener(new java.awt.event.WindowListener { 65 | def windowActivated(e: java.awt.event.WindowEvent) { publish(WindowActivated(outer)) } 66 | def windowClosed(e: java.awt.event.WindowEvent) { publish(WindowClosed(outer)) } 67 | def windowClosing(e: java.awt.event.WindowEvent) { publish(WindowClosing(outer)) } 68 | def windowDeactivated(e: java.awt.event.WindowEvent) { publish(WindowDeactivated(outer)) } 69 | def windowDeiconified(e: java.awt.event.WindowEvent) { publish(WindowDeiconified(outer)) } 70 | def windowIconified(e: java.awt.event.WindowEvent) { publish(WindowIconified(outer)) } 71 | def windowOpened(e: java.awt.event.WindowEvent) { publish(WindowOpened(outer)) } 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /scala/swing/event/ActionEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | object ActionEvent { 15 | def unapply(a: ActionEvent): Option[Component] = Some(a.source) 16 | } 17 | 18 | class ActionEvent(override val source: Component) extends ComponentEvent 19 | -------------------------------------------------------------------------------- /scala/swing/event/AdjustingEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | /**

15 | * An event that indicates some editing operation that can be still in 16 | * progress.
17 | * Example: dragging a slider creates a number of AdjustmentEvents 18 | * with adjusting == true until the user finally releases the 19 | * mouse button. 20 | *

21 | */ 22 | trait AdjustingEvent extends ComponentEvent { 23 | def adjusting: Boolean 24 | def committed: Boolean = !adjusting 25 | } 26 | -------------------------------------------------------------------------------- /scala/swing/event/BackgroundChanged.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class BackgroundChanged(override val source: Component) extends ComponentEvent 15 | -------------------------------------------------------------------------------- /scala/swing/event/ButtonClicked.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class ButtonClicked(override val source: AbstractButton) extends ActionEvent(source) 15 | 16 | -------------------------------------------------------------------------------- /scala/swing/event/CaretUpdate.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class CaretUpdate(override val source: TextComponent) extends ComponentEvent 15 | -------------------------------------------------------------------------------- /scala/swing/event/ComponentEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | trait ComponentEvent extends UIEvent { 15 | val source: Component 16 | } 17 | 18 | @deprecated("Use UIElementMoved instead.") 19 | case class ComponentMoved(source: Component) extends ComponentEvent 20 | @deprecated("Use UIElementResized instead.") 21 | case class ComponentResized(source: Component) extends ComponentEvent 22 | @deprecated("Use UIElementShown instead.") 23 | case class ComponentShown(source: Component) extends ComponentEvent 24 | @deprecated("Use UIElementHidden instead.") 25 | case class ComponentHidden(source: Component) extends ComponentEvent 26 | -------------------------------------------------------------------------------- /scala/swing/event/ContainerEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | abstract class ContainerEvent(override val source: Container) extends UIEvent 15 | 16 | case class ComponentAdded(override val source: Container, child: Component) extends ContainerEvent(source) 17 | case class ComponentRemoved(override val source: Container, child: Component) extends ContainerEvent(source) 18 | -------------------------------------------------------------------------------- /scala/swing/event/EditDone.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class EditDone(override val source: TextField) extends ValueChanged(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/Event.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | trait Event 15 | -------------------------------------------------------------------------------- /scala/swing/event/FocusEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | /** 15 | * The other component is None if it is a non Swing, i.e., AWT or native, component. 16 | */ 17 | abstract class FocusEvent(override val source: Component, val other: Option[Component], val temporary: Boolean) extends ComponentEvent 18 | 19 | case class FocusGained(override val source: Component, override val other: Option[Component], override val temporary: Boolean) 20 | extends FocusEvent(source, other, temporary) 21 | 22 | case class FocusLost(override val source: Component, override val other: Option[Component], override val temporary: Boolean) 23 | extends FocusEvent(source, other, temporary) 24 | -------------------------------------------------------------------------------- /scala/swing/event/FontChanged.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class FontChanged(override val source: Component) extends ComponentEvent 15 | -------------------------------------------------------------------------------- /scala/swing/event/ForegroundChanged.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class ForegroundChanged(override val source: Component) extends ComponentEvent 15 | -------------------------------------------------------------------------------- /scala/swing/event/InputEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | trait InputEvent extends ComponentEvent { 15 | def peer: java.awt.event.InputEvent 16 | def when: Long = peer.getWhen 17 | def modifiers: Key.Modifiers 18 | def consume() { peer.consume() } 19 | def consumed: Boolean = peer.isConsumed 20 | } 21 | -------------------------------------------------------------------------------- /scala/swing/event/KeyEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | import javax.swing.JComponent 15 | 16 | sealed abstract class KeyEvent extends InputEvent { 17 | def peer: java.awt.event.KeyEvent 18 | } 19 | 20 | case class KeyTyped(val source: Component, char: Char, val modifiers: Key.Modifiers, 21 | location: Key.Location.Value) 22 | (val peer: java.awt.event.KeyEvent) extends KeyEvent { 23 | def this(e: java.awt.event.KeyEvent) = 24 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 25 | e.getKeyChar, e.getModifiersEx, 26 | Key.Location(e.getKeyLocation))(e) 27 | } 28 | 29 | case class KeyPressed(val source: Component, key: Key.Value, val modifiers: Key.Modifiers, 30 | location: Key.Location.Value) 31 | (val peer: java.awt.event.KeyEvent) extends KeyEvent { 32 | def this(e: java.awt.event.KeyEvent) = 33 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 34 | Key(e.getKeyCode), e.getModifiersEx, Key.Location(e.getKeyLocation))(e) 35 | } 36 | 37 | case class KeyReleased(val source: Component, key: Key.Value, val modifiers: Key.Modifiers, 38 | location: Key.Location.Value) 39 | (val peer: java.awt.event.KeyEvent) extends KeyEvent { 40 | def this(e: java.awt.event.KeyEvent) = 41 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 42 | Key(e.getKeyCode), e.getModifiersEx, Key.Location(e.getKeyLocation))(e) 43 | } 44 | -------------------------------------------------------------------------------- /scala/swing/event/ListEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | trait ListEvent[A] extends ComponentEvent { 15 | override val source: ListView[A] 16 | } 17 | 18 | //case class ElementSelected[A](override val source: ListView[A], range: Range, live: Boolean) 19 | // extends ListEvent[A] with AdjustingEvent with ListSelectionEvent 20 | 21 | abstract class ListChange[A](override val source: ListView[A]) extends ListEvent[A] 22 | 23 | object ListChanged { 24 | def unapply[A](e: ListChanged[A]) = Some(e.source) 25 | def apply[A](source: ListView[A]) = new ListChanged(source) 26 | } 27 | 28 | class ListChanged[A](override val source: ListView[A]) extends ListChange(source) 29 | 30 | object ListElementsAdded { 31 | def unapply[A](e: ListElementsAdded[A]) = Some(e.source, e.range) 32 | def apply[A](source: ListView[A], range: Range) = new ListElementsAdded(source, range) 33 | } 34 | 35 | class ListElementsAdded[A](override val source: ListView[A], val range: Range) 36 | extends ListChange(source) 37 | 38 | object ListElementsRemoved { 39 | def unapply[A](e: ListElementsRemoved[A]) = Some(e.source, e.range) 40 | def apply[A](source: ListView[A], range: Range) = new ListElementsRemoved(source, range) 41 | } 42 | class ListElementsRemoved[A](override val source: ListView[A], val range: Range) 43 | extends ListChange(source) 44 | -------------------------------------------------------------------------------- /scala/swing/event/MouseEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | import java.awt.Point 15 | import javax.swing.JComponent 16 | 17 | sealed abstract class MouseEvent extends InputEvent { 18 | def peer: java.awt.event.MouseEvent 19 | def point: Point 20 | } 21 | 22 | sealed abstract class MouseButtonEvent extends MouseEvent { 23 | def clicks: Int 24 | def triggersPopup: Boolean 25 | } 26 | case class MouseClicked(val source: Component, point: Point, val modifiers: Key.Modifiers, 27 | clicks: Int, triggersPopup: Boolean)(val peer: java.awt.event.MouseEvent) 28 | extends MouseButtonEvent { 29 | def this(e: java.awt.event.MouseEvent) = 30 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 31 | e.getPoint, e.getModifiersEx, e.getClickCount, e.isPopupTrigger)(e) 32 | } 33 | case class MousePressed(val source: Component, point: Point, val modifiers: Key.Modifiers, 34 | clicks: Int, triggersPopup: Boolean)(val peer: java.awt.event.MouseEvent) 35 | extends MouseButtonEvent { 36 | def this(e: java.awt.event.MouseEvent) = 37 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 38 | e.getPoint, e.getModifiersEx, e.getClickCount, e.isPopupTrigger)(e) 39 | } 40 | case class MouseReleased(val source: Component, point: Point, val modifiers: Key.Modifiers, 41 | clicks: Int, triggersPopup: Boolean)(val peer: java.awt.event.MouseEvent) 42 | extends MouseButtonEvent { 43 | def this(e: java.awt.event.MouseEvent) = 44 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 45 | e.getPoint, e.getModifiersEx, e.getClickCount, e.isPopupTrigger)(e) 46 | } 47 | 48 | sealed abstract class MouseMotionEvent extends MouseEvent 49 | case class MouseMoved(val source: Component, point: Point, val modifiers: Key.Modifiers)(val peer: java.awt.event.MouseEvent) 50 | extends MouseMotionEvent { 51 | def this(e: java.awt.event.MouseEvent) = 52 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 53 | e.getPoint, e.getModifiersEx)(e) 54 | } 55 | case class MouseDragged(val source: Component, point: Point, val modifiers: Key.Modifiers)(val peer: java.awt.event.MouseEvent) 56 | extends MouseMotionEvent { 57 | def this(e: java.awt.event.MouseEvent) = 58 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 59 | e.getPoint, e.getModifiersEx)(e) 60 | } 61 | case class MouseEntered(val source: Component, point: Point, val modifiers: Key.Modifiers)(val peer: java.awt.event.MouseEvent) 62 | extends MouseMotionEvent { 63 | def this(e: java.awt.event.MouseEvent) = 64 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 65 | e.getPoint, e.getModifiersEx)(e) 66 | } 67 | case class MouseExited(val source: Component, point: Point, val modifiers: Key.Modifiers)(val peer: java.awt.event.MouseEvent) 68 | extends MouseMotionEvent { 69 | def this(e: java.awt.event.MouseEvent) = 70 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 71 | e.getPoint, e.getModifiersEx)(e) 72 | } 73 | 74 | case class MouseWheelMoved(val source: Component, point: Point, val modifiers: Key.Modifiers, rotation: Int)(val peer: java.awt.event.MouseEvent) 75 | extends MouseEvent { 76 | def this(e: java.awt.event.MouseWheelEvent) = 77 | this(UIElement.cachedWrapper[Component](e.getSource.asInstanceOf[JComponent]), 78 | e.getPoint, e.getModifiersEx, e.getWheelRotation)(e) 79 | } 80 | -------------------------------------------------------------------------------- /scala/swing/event/SelectionEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | /** 15 | * An event that indicates a change in a selection such as in a list view or a table. 16 | */ 17 | trait SelectionEvent 18 | 19 | /** 20 | * An event that indicates a selection of a range of indices. 21 | */ 22 | trait ListSelectionEvent extends SelectionEvent { 23 | def range: Range 24 | } 25 | 26 | case class SelectionChanged(override val source: Component) extends ComponentEvent with SelectionEvent 27 | 28 | object ListSelectionChanged { 29 | def unapply[A](e: ListSelectionChanged[A]): Option[(ListView[A], Range, Boolean)] = 30 | Some((e.source, e.range, e.live)) 31 | } 32 | 33 | class ListSelectionChanged[A](override val source: ListView[A], val range: Range, val live: Boolean) 34 | extends SelectionChanged(source) with ListEvent[A] 35 | -------------------------------------------------------------------------------- /scala/swing/event/TableEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | abstract class TableEvent(override val source: Table) extends ComponentEvent 15 | 16 | abstract class TableChange(override val source: Table) extends TableEvent(source) 17 | 18 | /** 19 | * The most general table change. The table might have changed completely, 20 | * i.e., columns might have been reordered, rows added or removed, etc. 21 | * No other event indicates that the structure might have changed. 22 | */ 23 | case class TableStructureChanged(override val source: Table) extends TableChange(source) 24 | /** 25 | * The table structure, i.e., the column order, names, and types stay the same, 26 | * but anything else might have changed. 27 | */ 28 | case class TableChanged(override val source: Table) extends TableChange(source) 29 | /** 30 | * The size of the table stays the same, but the given range of rows might 31 | * have changed but only in the given column. A value of -1 for the column 32 | * denotes all columns. 33 | */ 34 | case class TableUpdated(override val source: Table, range: Range, column: Int) 35 | extends TableChange(source) 36 | /** 37 | * Any change that caused the table to change it's size 38 | */ 39 | class TableResized(override val source: Table) extends TableChange(source) 40 | case class TableRowsAdded(override val source: Table, range: Range) extends TableResized(source) 41 | case class TableRowsRemoved(override val source: Table, range: Range) extends TableResized(source) 42 | 43 | case class TableColumnsSelected(override val source: Table, range: Range, adjusting: Boolean) 44 | extends TableEvent(source) with AdjustingEvent with ListSelectionEvent 45 | case class TableRowsSelected(override val source: Table, range: Range, adjusting: Boolean) 46 | extends TableEvent(source) with AdjustingEvent with ListSelectionEvent 47 | -------------------------------------------------------------------------------- /scala/swing/event/UIEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | trait UIEvent extends Event { 15 | val source: UIElement 16 | } 17 | 18 | case class UIElementMoved(source: UIElement) extends UIEvent 19 | case class UIElementResized(source: UIElement) extends UIEvent 20 | case class UIElementShown(source: UIElement) extends UIEvent 21 | case class UIElementHidden(source: UIElement) extends UIEvent 22 | -------------------------------------------------------------------------------- /scala/swing/event/ValueChanged.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | object ValueChanged { 15 | def unapply(a: ValueChanged): Option[Component] = Some(a.source) 16 | } 17 | 18 | class ValueChanged(override val source: Component) extends ComponentEvent 19 | -------------------------------------------------------------------------------- /scala/swing/event/WindowActivated.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowActivated(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowClosed.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package event 3 | 4 | case class WindowClosed(override val source: Window) extends WindowEvent(source) 5 | -------------------------------------------------------------------------------- /scala/swing/event/WindowClosing.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowClosing(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowDeactivated.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowDeactivated(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowDeiconified.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowDeiconified(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowEvent.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | abstract class WindowEvent(override val source: Window) extends UIEvent 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowIconified.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowIconified(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/event/WindowOpened.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | 11 | package scala.swing 12 | package event 13 | 14 | case class WindowOpened(override val source: Window) extends WindowEvent(source) 15 | -------------------------------------------------------------------------------- /scala/swing/model/Matrix.scala: -------------------------------------------------------------------------------- 1 | /* __ *\ 2 | ** ________ ___ / / ___ Scala API ** 3 | ** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** 4 | ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** 5 | ** /____/\___/_/ |_/____/_/ | | ** 6 | ** |/ ** 7 | \* */ 8 | 9 | 10 | package scala.swing 11 | package model 12 | 13 | // Dummy to keep ant from recompiling on every run. 14 | trait Matrix { } 15 | 16 | /*trait Matrix[A] extends Function2[Int, Int, A] { 17 | 18 | val width: Int 19 | val height: Int 20 | 21 | assert(width > 0 && height > 0) 22 | 23 | private val delegate = new Array[A](width * height) 24 | 25 | override def apply(col: Int, row: Int): A = 26 | delegate(col * height + row) 27 | 28 | def apply(coord: (Int, Int)): A = 29 | apply(coord._1, coord._2) 30 | 31 | def col(index: Int): Matrix.FlatSeq[A] = 32 | new Matrix.SubArray[A](delegate, index * height, height) 33 | 34 | def row(index: Int): Matrix.FlatSeq[A] = 35 | new Matrix.SparseArray[A](delegate, index, height) 36 | 37 | def update(xpos: Int, ypos: Int, elem: A) { 38 | delegate(xpos % width * height + ypos % height) = elem 39 | } 40 | 41 | def update(coord: (Int, Int), elem: A) { 42 | update(coord._1, coord._2, elem) 43 | } 44 | 45 | def initializeWith(f: (Int, Int) => A): this.type = { 46 | for (index <- 0 until (width * height)) 47 | delegate(index) = f(index / height, index % height) 48 | this 49 | } 50 | 51 | def initializeTo(v: => A): this.type = { 52 | for (index <- 0 until (width * height)) 53 | delegate(index) = v 54 | this 55 | } 56 | 57 | def size: (Int, Int) = (width, height) 58 | 59 | /** A flattened view of the matrix. The flattening is done on columns i.e. 60 | * the first values of the flattened sequence are the cells of the first 61 | * column. As this is a view of the matrix, any change to the matrix will 62 | * also be visible in the flattened array, and vice-versa. */ 63 | def flat: Array[A] = delegate 64 | 65 | } 66 | 67 | object Matrix { 68 | 69 | def apply[A](columns: Int, rows: Int) = new Matrix[A] { 70 | val width = columns 71 | val height = rows 72 | } 73 | 74 | def apply[A](default: (Int, Int) => A, columns: Int, rows: Int) = new Matrix[A] { 75 | val width = columns 76 | val height = rows 77 | initializeWith(default) 78 | } 79 | 80 | def apply[A](default: => A, columns: Int, rows: Int) = new Matrix[A] { 81 | val width = columns 82 | val height = rows 83 | initializeTo(default) 84 | } 85 | 86 | trait FlatSeq[A] extends RandomAccessSeq[A] { 87 | def update (index: Int, elem: A): Unit 88 | } 89 | 90 | private class SubArray[A](delegate: Array[A], start: Int, val length: Int) extends FlatSeq[A] { 91 | def apply(index: Int): A = 92 | if (index < length) 93 | delegate(index + start) 94 | else throw new IndexOutOfBoundsException 95 | def update(index: Int, elem: A): Unit = 96 | if (index < length) 97 | delegate(index + start) = elem 98 | else throw new IndexOutOfBoundsException 99 | } 100 | 101 | private class SparseArray[A](delegate: Array[A], start: Int, span: Int) extends FlatSeq[A] { 102 | def apply(index: Int): A = { 103 | if (index < length) 104 | delegate((index * span) + start) 105 | else throw new IndexOutOfBoundsException 106 | } 107 | def length: Int = delegate.length / span 108 | def update(index: Int, elem: A): Unit = 109 | if (index < length) 110 | delegate((index * span) + start) = elem 111 | else throw new IndexOutOfBoundsException 112 | } 113 | 114 | implicit def MatrixToSeqs[A](matrix: Matrix[A]): Seq[Seq[A]] = { 115 | val result = new Array[SubArray[A]](matrix.width) 116 | for (col <- 0 until matrix.width) 117 | result(col) = new SubArray[A](matrix.delegate, col * matrix.height, matrix.height) 118 | result 119 | } 120 | 121 | }*/ 122 | -------------------------------------------------------------------------------- /scala/swing/package.scala: -------------------------------------------------------------------------------- 1 | package scala 2 | 3 | /** 4 | * Useful imports that don't have wrappers. 5 | */ 6 | package object swing { 7 | type Point = java.awt.Point 8 | type Dimension = java.awt.Dimension 9 | type Rectangle = java.awt.Rectangle 10 | type Insets = java.awt.Insets 11 | 12 | type Graphics2D = java.awt.Graphics2D 13 | type Color = java.awt.Color 14 | type Image = java.awt.Image 15 | type Font = java.awt.Font 16 | 17 | protected[swing] def ifNull[A](o: Object, a: A): A = if(o eq null) a else o.asInstanceOf[A] 18 | protected[swing] def toOption[A](o: Object): Option[A] = if(o eq null) None else Some(o.asInstanceOf[A]) 19 | protected[swing] def toAnyRef(x: Any): AnyRef = x.asInstanceOf[AnyRef] 20 | } 21 | -------------------------------------------------------------------------------- /scala/swing/test/ButtonApp.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import java.awt.Dimension 5 | 6 | import swing._ 7 | import swing.event._ 8 | 9 | object ButtonApp extends SimpleSwingApplication { 10 | def top = new MainFrame { 11 | title = "My Frame" 12 | contents = new GridPanel(2, 2) { 13 | hGap = 3 14 | vGap = 3 15 | contents += new Button { 16 | text = "Press Me!" 17 | reactions += { 18 | case ButtonClicked(_) => text = "Hello Scala" 19 | } 20 | } 21 | } 22 | size = new Dimension(300, 80) 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /scala/swing/test/CelsiusConverter.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import event._ 6 | 7 | /** A GUI app to convert celsius to centigrade 8 | */ 9 | object CelsiusConverter extends SimpleSwingApplication { 10 | def top = new MainFrame { 11 | title = "Convert Celsius to Fahrenheit" 12 | val tempCelsius = new TextField 13 | val celsiusLabel = new Label { 14 | text = "Celsius" 15 | border = Swing.EmptyBorder(5, 5, 5, 5) 16 | } 17 | val convertButton = new Button { 18 | text = "Convert"//new javax.swing.ImageIcon("c:\\workspace\\gui\\images\\convert.gif") 19 | //border = Border.Empty(5, 5, 5, 5) 20 | } 21 | val fahrenheitLabel = new Label { 22 | text = "Fahrenheit " 23 | border = Swing.EmptyBorder(5, 5, 5, 5) 24 | listenTo(convertButton, tempCelsius) 25 | 26 | def convert() { 27 | val c = Integer.parseInt(tempCelsius.text) 28 | val f = c * 9 / 5 + 32 29 | text = ""+f+" Fahrenheit" 30 | } 31 | 32 | reactions += { 33 | case ButtonClicked(_) | EditDone(_) => convert() 34 | } 35 | } 36 | contents = new GridPanel(2,2) { 37 | contents.append(tempCelsius, celsiusLabel, convertButton, fahrenheitLabel) 38 | border = Swing.EmptyBorder(10, 10, 10, 10) 39 | } 40 | //defaultButton = Some(convertButton) 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /scala/swing/test/CelsiusConverter2.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import event._ 6 | 7 | object CelsiusConverter2 extends SimpleSwingApplication { 8 | def newField = new TextField { 9 | text = "0" 10 | columns = 5 11 | horizontalAlignment = Alignment.Right 12 | } 13 | val celsius = newField 14 | val fahrenheit = newField 15 | 16 | listenTo(fahrenheit, celsius) 17 | reactions += { 18 | case EditDone(`fahrenheit`) => 19 | val f = Integer.parseInt(fahrenheit.text) 20 | val c = (f - 32) * 5 / 9 21 | celsius.text = c.toString 22 | case EditDone(`celsius`) => 23 | val c = Integer.parseInt(celsius.text) 24 | val f = c * 9 / 5 + 32 25 | fahrenheit.text = f.toString 26 | } 27 | 28 | lazy val ui = new FlowPanel(celsius, new Label(" Celsius = "), 29 | fahrenheit, new Label(" Fahrenheit")) { 30 | border = Swing.EmptyBorder(15, 10, 10, 10) 31 | } 32 | def top = new MainFrame { 33 | title = "Convert Celsius / Fahrenheit" 34 | contents = ui 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /scala/swing/test/ComboBoxes.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import event._ 6 | import java.util.Date 7 | import java.awt.Color 8 | import java.text.SimpleDateFormat 9 | import javax.swing.{Icon, ImageIcon} 10 | 11 | /** 12 | * Demonstrates how to use combo boxes and custom item renderers. 13 | * 14 | * TODO: clean up layout 15 | */ 16 | object ComboBoxes extends SimpleSwingApplication { 17 | import ComboBox._ 18 | lazy val ui = new FlowPanel { 19 | contents += new ComboBox(List(1,2,3,4)) 20 | 21 | val patterns = List("dd MMMMM yyyy", 22 | "dd.MM.yy", 23 | "MM/dd/yy", 24 | "yyyy.MM.dd G 'at' hh:mm:ss z", 25 | "EEE, MMM d, ''yy", 26 | "h:mm a", 27 | "H:mm:ss:SSS", 28 | "K:mm a,z", 29 | "yyyy.MMMMM.dd GGG hh:mm aaa") 30 | val dateBox = new ComboBox(patterns) { makeEditable() } 31 | contents += dateBox 32 | val field = new TextField(20) { editable = false } 33 | contents += field 34 | 35 | reactions += { 36 | case SelectionChanged(`dateBox`) => reformat() 37 | } 38 | listenTo(dateBox.selection) 39 | 40 | def reformat() { 41 | try { 42 | val today = new Date 43 | val formatter = new SimpleDateFormat(dateBox.selection.item) 44 | val dateString = formatter.format(today) 45 | field.foreground = Color.black 46 | field.text = dateString 47 | } catch { 48 | case e: IllegalArgumentException => 49 | field.foreground = Color.red 50 | field.text = "Error: " + e.getMessage 51 | } 52 | } 53 | 54 | 55 | val icons = try { 56 | List(new ImageIcon(resourceFromClassloader("images/margarita1.jpg")), 57 | new ImageIcon(resourceFromClassloader("images/margarita2.jpg")), 58 | new ImageIcon(resourceFromClassloader("images/rose.jpg")), 59 | new ImageIcon(resourceFromClassloader("images/banana.jpg"))) 60 | } catch { 61 | case _ => 62 | println("Couldn't load images for combo box") 63 | List(Swing.EmptyIcon) 64 | } 65 | 66 | val iconBox = new ComboBox(icons) { 67 | renderer = new ListView.AbstractRenderer[Icon, Label](new Label) { 68 | def configure(list: ListView[_], isSelected: Boolean, focused: Boolean, icon: Icon, index: Int) { 69 | component.icon = icon 70 | component.xAlignment = Alignment.Center 71 | if(isSelected) { 72 | component.border = Swing.LineBorder(list.selectionBackground, 3) 73 | } else { 74 | component.border = Swing.EmptyBorder(3) 75 | } 76 | } 77 | } 78 | } 79 | contents += iconBox 80 | } 81 | 82 | def top = new MainFrame { 83 | title = "ComboBoxes Demo" 84 | contents = ui 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /scala/swing/test/CountButton.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import scala.swing._ 5 | import scala.swing.event._ 6 | 7 | object CountButton extends SimpleSwingApplication { 8 | def top = new MainFrame { 9 | title = "My Frame" 10 | contents = new GridPanel(2, 2) { 11 | hGap = 3 12 | vGap = 3 13 | val button = new Button { 14 | text = "Press Me!" 15 | } 16 | contents += button 17 | val label = new Label { 18 | text = "No button clicks registered" 19 | } 20 | contents += label 21 | 22 | listenTo(button) 23 | var nclicks = 0 24 | reactions += { 25 | case ButtonClicked(b) => 26 | nclicks += 1 27 | label.text = "Number of button clicks: "+nclicks 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scala/swing/test/Dialogs.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import swing.event._ 6 | 7 | object Dialogs extends SimpleSwingApplication { 8 | import TabbedPane._ 9 | 10 | lazy val label = new Label("No Result yet") 11 | lazy val tabs = new TabbedPane { 12 | pages += new Page("File", new GridBagPanel { grid => 13 | import GridBagPanel._ 14 | val buttonText = new TextField("Click Me") 15 | 16 | val c = new Constraints 17 | c.fill = Fill.Horizontal 18 | c.grid = (1,1) 19 | 20 | val chooser = new FileChooser 21 | layout(new Button(Action("Open") { 22 | chooser.showOpenDialog(grid) 23 | })) = c 24 | 25 | c.grid = (1,2) 26 | layout(new Button(Action("Save") { 27 | chooser.showSaveDialog(grid) 28 | })) = c 29 | 30 | c.grid = (1,3) 31 | layout(new Button(Action("Custom") { 32 | chooser.showDialog(grid, buttonText.text) 33 | })) = c 34 | 35 | c.grid = (2,3) 36 | layout(new Label(" with Text ")) = c 37 | 38 | c.grid = (3,3) 39 | c.ipadx = 50 40 | layout(buttonText) = c 41 | 42 | border = Swing.EmptyBorder(5, 5, 5, 5) 43 | }) 44 | pages += new Page("Simple Modal Dialogs", new BorderPanel { 45 | import BorderPanel._ 46 | val mutex = new ButtonGroup 47 | val ok = new RadioButton("OK (in the L&F's words)") 48 | val ynlf = new RadioButton("Yes/No (in the L&F's words)") 49 | val ynp = new RadioButton("Yes/No (in the programmer's words)") 50 | val yncp = new RadioButton("Yes/No/Cancel (in the programmer's words)") 51 | val radios = List(ok, ynlf, ynp, yncp) 52 | mutex.buttons ++= radios 53 | mutex.select(ok) 54 | val buttons = new BoxPanel(Orientation.Vertical) { 55 | contents ++= radios 56 | } 57 | layout(buttons) = Position.North 58 | layout(new Button(Action("Show It!") { 59 | import Dialog._ 60 | mutex.selected.get match { 61 | case `ok` => 62 | showMessage(buttons, "Eggs aren't supposed to be green.") 63 | case `ynlf` => 64 | label.text = showConfirmation(buttons, 65 | "Would you like green eggs and ham?", 66 | "An Inane Question") match { 67 | case Result.Yes => "Ewww!" 68 | case Result.No => "Me neither!" 69 | case _ => "Come on -- tell me!" 70 | } 71 | case `ynp` => 72 | val options = List("Yes, please", 73 | "No, thanks", 74 | "No eggs, no ham!") 75 | label.text = showOptions(buttons, 76 | "Would you like some green eggs to go with that ham?", 77 | "A Silly Question", 78 | entries = options, 79 | initial = 2) match { 80 | case Result.Yes => "You're kidding!" 81 | case Result.No => "I don't like them, either." 82 | case _ => "Come on -- 'fess up!" 83 | } 84 | case `yncp` => 85 | val options = List("Yes, please", 86 | "No, thanks", 87 | "No eggs, no ham!") 88 | label.text = showOptions(buttons, 89 | message = "Would you like some green eggs to go with that ham?", 90 | title = "A Silly Question", 91 | entries = options, 92 | initial = 2) match { 93 | case Result.Yes => "Here you go: green eggs and ham!" 94 | case Result.No => "OK, just the ham, then." 95 | case Result.Cancel => "Well, I'm certainly not going to eat them!" 96 | case _ => "Please tell me what you want!" 97 | } 98 | } 99 | })) = Position.South 100 | }) 101 | pages += new Page("More Dialogs", new BorderPanel { 102 | import BorderPanel._ 103 | val mutex = new ButtonGroup 104 | val pick = new RadioButton("Pick one of several choices") 105 | val enter = new RadioButton("Enter some text") 106 | val custom = new RadioButton("Custom") 107 | val customUndec = new RadioButton("Custom undecorated") 108 | val custom2 = new RadioButton("2 custom dialogs") 109 | val radios = List(pick, enter, custom, customUndec, custom2) 110 | mutex.buttons ++= radios 111 | mutex.select(pick) 112 | val buttons = new BoxPanel(Orientation.Vertical) { 113 | contents ++= radios 114 | } 115 | layout(buttons) = Position.North 116 | layout(new Button(Action("Show It!") { 117 | import Dialog._ 118 | mutex.selected.get match { 119 | case `pick` => 120 | val possibilities = List("ham", "spam", "yam") 121 | val s = showInput(buttons, 122 | "Complete the sentence:\n\"Green eggs and...\"", 123 | "Customized Dialog", 124 | Message.Plain, 125 | Swing.EmptyIcon, 126 | possibilities, "ham") 127 | 128 | //If a string was returned, say so. 129 | label.text = if ((s != None) && (s.get.length > 0)) 130 | "Green eggs and... " + s.get + "!" 131 | else 132 | "Come on, finish the sentence!" 133 | case `enter` => 134 | val s = showInput(buttons, 135 | "Complete the sentence:\n\"Green eggs and...\"", 136 | "Customized Dialog", 137 | Message.Plain, 138 | Swing.EmptyIcon, 139 | Nil, "ham") 140 | 141 | //If a string was returned, say so. 142 | label.text = if ((s != None) && (s.get.length > 0)) 143 | "Green eggs and... " + s.get + "!" 144 | else 145 | "Come on, finish the sentence!" 146 | case `custom` => 147 | val dialog = new Dialog(top) 148 | dialog.open() 149 | dialog.contents = Button("Close Me!") { dialog.close() } 150 | case `customUndec` => 151 | val dialog = new Dialog with RichWindow.Undecorated 152 | dialog.open() 153 | dialog.contents = Button("Close Me!") { dialog.close() } 154 | case `custom2` => 155 | val d1 = new Dialog 156 | val d2 = new Dialog(d1) 157 | d1.open() 158 | d2.open() 159 | d1.contents = Button("Close Me! I am the owner and will automatically close the other one") { d1.close() } 160 | d2.contents = Button("Close Me!") { d2.close() } 161 | } 162 | })) = Position.South 163 | }) 164 | } 165 | 166 | lazy val ui: Panel = new BorderPanel { 167 | layout(tabs) = BorderPanel.Position.Center 168 | layout(label) = BorderPanel.Position.South 169 | } 170 | 171 | 172 | lazy val top = new MainFrame { 173 | title = "Dialog Demo" 174 | contents = ui 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /scala/swing/test/GridBagDemo.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import swing.event._ 6 | import GridBagPanel._ 7 | import java.awt.Insets 8 | 9 | object GridBagDemo extends SimpleSwingApplication { 10 | lazy val ui = new GridBagPanel { 11 | val c = new Constraints 12 | val shouldFill = true 13 | if (shouldFill) { 14 | c.fill = Fill.Horizontal 15 | } 16 | 17 | val button1 = new Button("Button 1") 18 | 19 | c.weightx = 0.5 20 | 21 | c.fill = Fill.Horizontal 22 | c.gridx = 0; 23 | c.gridy = 0; 24 | layout(button1) = c 25 | 26 | val button2 = new Button("Button 2") 27 | c.fill = Fill.Horizontal 28 | c.weightx = 0.5; 29 | c.gridx = 1; 30 | c.gridy = 0; 31 | layout(button2) = c 32 | 33 | val button3 = new Button("Button 3") 34 | c.fill = Fill.Horizontal 35 | c.weightx = 0.5; 36 | c.gridx = 2; 37 | c.gridy = 0; 38 | layout(button3) = c 39 | 40 | val button4 = new Button("Long-Named Button 4") 41 | c.fill = Fill.Horizontal 42 | c.ipady = 40; //make this component tall 43 | c.weightx = 0.0; 44 | c.gridwidth = 3; 45 | c.gridx = 0; 46 | c.gridy = 1; 47 | layout(button4) = c 48 | 49 | val button5 = new Button("5") 50 | c.fill = Fill.Horizontal 51 | c.ipady = 0; //reset to default 52 | c.weighty = 1.0; //request any extra vertical space 53 | c.anchor = Anchor.PageEnd 54 | c.insets = new Insets(10,0,0,0); //top padding 55 | c.gridx = 1; //aligned with button 2 56 | c.gridwidth = 2; //2 columns wide 57 | c.gridy = 2; //third row 58 | layout(button5) = c 59 | } 60 | 61 | def top = new MainFrame { 62 | title = "GridBag Demo" 63 | contents = ui 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /scala/swing/test/HelloWorld.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | 6 | /** 7 | * A simple swing demo. 8 | */ 9 | object HelloWorld extends SimpleSwingApplication { 10 | def top = new MainFrame { 11 | title = "Hello, World!" 12 | contents = new Button("Click Me!") 13 | } 14 | } -------------------------------------------------------------------------------- /scala/swing/test/LabelTest.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import scala.swing._ 5 | import scala.swing.event._ 6 | 7 | object LabelTest extends SimpleSwingApplication { 8 | def top = new MainFrame{ 9 | contents = new Label { 10 | text = "Hello" 11 | import java.awt.event._ 12 | listenTo(mouse.clicks) 13 | reactions += { 14 | case MousePressed(_,_,_,_,_) => 15 | println("Mouse pressed2") 16 | } 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /scala/swing/test/LinePainting.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | import scala.swing.Swing._ 4 | import scala.swing.{MainFrame, Panel, SimpleGUIApplication} 5 | import scala.swing.event._ 6 | import java.awt.{Color, Dimension, Graphics, Graphics2D, Point, geom} 7 | 8 | /** 9 | * Dragging the mouse draws a simple graph 10 | * 11 | * @author Frank Teubler, Ingo Maier 12 | */ 13 | object LinePainting extends SimpleSwingApplication { 14 | lazy val ui = new Panel { 15 | background = Color.white 16 | preferredSize = (200,200) 17 | 18 | focusable = true 19 | listenTo(mouse.clicks, mouse.moves, keys) 20 | 21 | reactions += { 22 | case e: MousePressed => 23 | moveTo(e.point) 24 | requestFocusInWindow() 25 | case e: MouseDragged => lineTo(e.point) 26 | case e: MouseReleased => lineTo(e.point) 27 | case KeyTyped(_,'c',_,_) => 28 | path = new geom.GeneralPath 29 | repaint() 30 | case _: FocusLost => repaint() 31 | } 32 | 33 | /* records the dragging */ 34 | var path = new geom.GeneralPath 35 | 36 | def lineTo(p: Point) { path.lineTo(p.x, p.y); repaint() } 37 | def moveTo(p: Point) { path.moveTo(p.x, p.y); repaint() } 38 | 39 | override def paintComponent(g: Graphics2D) = { 40 | super.paintComponent(g) 41 | g.setColor(new Color(100,100,100)) 42 | g.drawString("Press left mouse button and drag to paint." + 43 | (if(hasFocus) " Press 'c' to clear." else ""), 10, size.height-10) 44 | g.setColor(Color.black) 45 | g.draw(path) 46 | } 47 | } 48 | 49 | def top = new MainFrame { 50 | title = "Simple Line Painting Demo" 51 | contents = ui 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /scala/swing/test/ListViewDemo.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | object ListViewDemo extends SimpleSwingApplication { 5 | def top = new MainFrame { 6 | case class City(name: String, country: String, population: Int, capital: Boolean) 7 | val items = List(City("Lausanne", "Switzerland", 129273, false), 8 | City("Paris", "France", 2203817, true), 9 | City("New York", "USA", 8363710 , false), 10 | City("Berlin", "Germany", 3416300, true), 11 | City("Tokio", "Japan", 12787981, true)) 12 | import ListView._ 13 | contents = new FlowPanel(new ScrollPane(new ListView(items) { 14 | renderer = Renderer(_.name) 15 | })) 16 | //new ScrollPane(new Table(items))) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scala/swing/test/SimpleApplet.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import event._ 5 | 6 | class SimpleApplet extends Applet { 7 | object ui extends UI with Reactor { 8 | def init() = { 9 | val button = new Button("Press here!") 10 | val text = new TextArea("Java Version: " + util.Properties.javaVersion + "\n") 11 | listenTo(button) 12 | reactions += { 13 | case ButtonClicked(_) => text.text += "Button Pressed!\n" 14 | case _ => 15 | } 16 | contents = new BoxPanel(Orientation.Vertical) { contents.append(button, text) } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scala/swing/test/SwingApp.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import swing.event._ 6 | 7 | object SwingApp extends SimpleSwingApplication { 8 | def top = new MainFrame { 9 | title = "SwingApp" 10 | var numclicks = 0 11 | object label extends Label { 12 | val prefix = "Number of button clicks: " 13 | text = prefix + "0 " 14 | listenTo(button) 15 | reactions += { 16 | case ButtonClicked(button) => 17 | numclicks = numclicks + 1 18 | text = prefix + numclicks 19 | } 20 | } 21 | object button extends Button { 22 | text = "I am a button" 23 | } 24 | contents = new FlowPanel { 25 | contents.append(button, label) 26 | border = Swing.EmptyBorder(5, 5, 5, 5) 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /scala/swing/test/TableSelection.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import java.awt.Dimension 5 | import swing.event._ 6 | 7 | object TableSelection extends SimpleSwingApplication { 8 | val model = Array(List("Mary", "Campione", "Snowboarding", 5, false).toArray, 9 | List("Alison", "Huml", "Rowing", 5, false).toArray, 10 | List("Kathy", "Walrath", "Knitting", 5, false).toArray, 11 | List("Sharon", "Zakhour", "Speed reading", 5, false).toArray, 12 | List("Philip", "Milne", "Pool", 5, false).toArray) 13 | /*val model = Array.tabulate(10000) { i => 14 | List("Mary", "Campione", "Snowboarding", i, false).toArray 15 | }*/ 16 | 17 | lazy val ui = new BoxPanel(Orientation.Vertical) { 18 | val table = new Table(model, Array("First Name", "Last Name", "Sport", "# of Years", "Vegetarian")) { 19 | preferredViewportSize = new Dimension(500, 70) 20 | } 21 | //1.6:table.fillsViewportHeight = true 22 | listenTo(table.selection) 23 | 24 | contents += new ScrollPane(table) 25 | contents += new Label("Selection Mode") 26 | 27 | def radio(mutex: ButtonGroup, text: String): RadioButton = { 28 | val b = new RadioButton(text) 29 | listenTo(b) 30 | mutex.buttons += b 31 | contents += b 32 | b 33 | } 34 | 35 | val intervalMutex = new ButtonGroup 36 | val multiInterval = radio(intervalMutex, "Multiple Interval Selection") 37 | val elementInterval = radio(intervalMutex, "Single Selection") 38 | val singleInterval = radio(intervalMutex, "Single Interval Selection") 39 | intervalMutex.select(multiInterval) 40 | 41 | contents += new Label("Selection Options") 42 | val elemMutex = new ButtonGroup 43 | val rowSelection = radio(elemMutex, "Row Selection") 44 | val columnSelection = radio(elemMutex, "Column Selection") 45 | val cellSelection = radio(elemMutex, "Cell Selection") 46 | elemMutex.select(rowSelection) 47 | 48 | val output = new TextArea(5, 40) { editable = false } 49 | contents += new ScrollPane(output) 50 | 51 | def outputSelection() { 52 | output.append("Lead: " + table.selection.rows.leadIndex + "," + 53 | table.selection.columns.leadIndex + ". ") 54 | output.append("Rows:") 55 | for (c <- table.selection.rows) output.append(" " + c) 56 | output.append(". Columns:") 57 | for (c <- table.selection.columns) output.append(" " + c) 58 | output.append(".\n") 59 | } 60 | 61 | reactions += { 62 | case ButtonClicked(`multiInterval`) => 63 | table.selection.intervalMode = Table.IntervalMode.MultiInterval 64 | if (cellSelection.selected) { 65 | elemMutex.select(rowSelection) 66 | table.selection.elementMode = Table.ElementMode.None 67 | } 68 | cellSelection.enabled = false 69 | case ButtonClicked(`elementInterval`) => 70 | table.selection.intervalMode = Table.IntervalMode.Single 71 | cellSelection.enabled = true 72 | case ButtonClicked(`singleInterval`) => 73 | table.selection.intervalMode = Table.IntervalMode.SingleInterval 74 | cellSelection.enabled = true 75 | case ButtonClicked(`rowSelection`) => 76 | if (rowSelection.selected) 77 | table.selection.elementMode = Table.ElementMode.Row 78 | case ButtonClicked(`columnSelection`) => 79 | if (columnSelection.selected) 80 | table.selection.elementMode = Table.ElementMode.Column 81 | case ButtonClicked(`cellSelection`) => 82 | if (cellSelection.selected) 83 | table.selection.elementMode = Table.ElementMode.Cell 84 | case TableRowsSelected(_, range, false) => 85 | output.append("Rows selected, changes: " + range + "\n") 86 | outputSelection() 87 | case TableColumnsSelected(_, range, false) => 88 | output.append("Columns selected, changes " + range + "\n") 89 | outputSelection() 90 | } 91 | } 92 | 93 | def top = new MainFrame { 94 | title = "Table Selection" 95 | contents = ui 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /scala/swing/test/UIDemo.scala: -------------------------------------------------------------------------------- 1 | package scala.swing 2 | package test 3 | 4 | import swing._ 5 | import event._ 6 | import Swing._ 7 | import ListView._ 8 | 9 | object UIDemo extends SimpleSwingApplication { 10 | def top = new MainFrame { 11 | title = "Scala Swing Demo" 12 | 13 | /* 14 | * Create a menu bar with a couple of menus and menu items and 15 | * set the result as this frame's menu bar. 16 | */ 17 | menuBar = new MenuBar { 18 | contents += new Menu("A Menu") { 19 | contents += new MenuItem("An item") 20 | contents += new MenuItem(Action("An action item") { 21 | println("Action '"+ title +"' invoked") 22 | }) 23 | contents += new Separator 24 | contents += new CheckMenuItem("Check me") 25 | contents += new CheckMenuItem("Me too!") 26 | contents += new Separator 27 | val a = new RadioMenuItem("a") 28 | val b = new RadioMenuItem("b") 29 | val c = new RadioMenuItem("c") 30 | val mutex = new ButtonGroup(a,b,c) 31 | contents ++= mutex.buttons 32 | } 33 | contents += new Menu("Empty Menu") 34 | } 35 | 36 | /* 37 | * The root component in this frame is a panel with a border layout. 38 | */ 39 | contents = new BorderPanel { 40 | import BorderPanel.Position._ 41 | 42 | var reactLive = false 43 | 44 | val tabs = new TabbedPane { 45 | import TabbedPane._ 46 | val buttons = new FlowPanel { 47 | border = Swing.EmptyBorder(5,5,5,5) 48 | 49 | contents += new BoxPanel(Orientation.Vertical) { 50 | border = CompoundBorder(TitledBorder(EtchedBorder, "Radio Buttons"), EmptyBorder(5,5,5,10)) 51 | val a = new RadioButton("Green Vegetables") 52 | val b = new RadioButton("Red Meat") 53 | val c = new RadioButton("White Tofu") 54 | val mutex = new ButtonGroup(a,b,c) 55 | contents ++= mutex.buttons 56 | } 57 | contents += new BoxPanel(Orientation.Vertical) { 58 | border = CompoundBorder(TitledBorder(EtchedBorder, "Check Boxes"), EmptyBorder(5,5,5,10)) 59 | val paintLabels = new CheckBox("Paint Labels") 60 | val paintTicks = new CheckBox("Paint Ticks") 61 | val snapTicks = new CheckBox("Snap To Ticks") 62 | val live = new CheckBox("Live") 63 | contents.append(paintLabels, paintTicks, snapTicks, live) 64 | listenTo(paintLabels, paintTicks, snapTicks, live) 65 | reactions += { 66 | case ButtonClicked(`paintLabels`) => 67 | slider.paintLabels = paintLabels.selected 68 | case ButtonClicked(`paintTicks`) => 69 | slider.paintTicks = paintTicks.selected 70 | case ButtonClicked(`snapTicks`) => 71 | slider.snapToTicks = snapTicks.selected 72 | case ButtonClicked(`live`) => 73 | reactLive = live.selected 74 | } 75 | } 76 | contents += new Button(Action("Center Frame") { centerOnScreen() }) 77 | } 78 | pages += new Page("Buttons", buttons) 79 | pages += new Page("GridBag", GridBagDemo.ui) 80 | pages += new Page("Converter", CelsiusConverter2.ui) 81 | pages += new Page("Tables", TableSelection.ui) 82 | pages += new Page("Dialogs", Dialogs.ui) 83 | pages += new Page("Combo Boxes", ComboBoxes.ui) 84 | pages += new Page("Split Panes", 85 | new SplitPane(Orientation.Vertical, new Button("Hello"), new Button("World")) { 86 | continuousLayout = true 87 | }) 88 | 89 | val password = new FlowPanel { 90 | contents += new Label("Enter your secret password here ") 91 | val field = new PasswordField(10) 92 | contents += field 93 | val label = new Label(field.text) 94 | contents += label 95 | listenTo(field) 96 | reactions += { 97 | case EditDone(`field`) => label.text = field.password.mkString 98 | } 99 | } 100 | 101 | pages += new Page("Password", password) 102 | pages += new Page("Painting", LinePainting.ui) 103 | //pages += new Page("Text Editor", TextEditor.ui) 104 | } 105 | 106 | val list = new ListView(tabs.pages) { 107 | selectIndices(0) 108 | selection.intervalMode = ListView.IntervalMode.Single 109 | renderer = ListView.Renderer(_.title) 110 | } 111 | val center = new SplitPane(Orientation.Vertical, new ScrollPane(list), tabs) { 112 | oneTouchExpandable = true 113 | continuousLayout = true 114 | } 115 | layout(center) = Center 116 | 117 | /* 118 | * This slider is used above, so we need lazy initialization semantics. 119 | * Objects or lazy vals are the way to go, but objects give us better 120 | * type inference at times. 121 | */ 122 | object slider extends Slider { 123 | min = 0 124 | value = tabs.selection.index 125 | max = tabs.pages.size-1 126 | majorTickSpacing = 1 127 | } 128 | layout(slider) = South 129 | 130 | /* 131 | * Establish connection between the tab pane, slider, and list view. 132 | */ 133 | listenTo(slider) 134 | listenTo(tabs.selection) 135 | listenTo(list.selection) 136 | reactions += { 137 | case ValueChanged(`slider`) => 138 | if(!slider.adjusting || reactLive) tabs.selection.index = slider.value 139 | case SelectionChanged(`tabs`) => 140 | slider.value = tabs.selection.index 141 | list.selectIndices(tabs.selection.index) 142 | case SelectionChanged(`list`) => 143 | if (list.selection.items.length == 1) 144 | tabs.selection.page = list.selection.items(0) 145 | } 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /scala/swing/test/images/banana.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ingoem/scala-swing/5b45ba65a6afa15b6083bc4c0654d551a379e9a3/scala/swing/test/images/banana.jpg -------------------------------------------------------------------------------- /scala/swing/test/images/margarita1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ingoem/scala-swing/5b45ba65a6afa15b6083bc4c0654d551a379e9a3/scala/swing/test/images/margarita1.jpg -------------------------------------------------------------------------------- /scala/swing/test/images/margarita2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ingoem/scala-swing/5b45ba65a6afa15b6083bc4c0654d551a379e9a3/scala/swing/test/images/margarita2.jpg -------------------------------------------------------------------------------- /scala/swing/test/images/rose.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ingoem/scala-swing/5b45ba65a6afa15b6083bc4c0654d551a379e9a3/scala/swing/test/images/rose.jpg -------------------------------------------------------------------------------- /swing.version.properties: -------------------------------------------------------------------------------- 1 | version.major=0 2 | version.minor=4 3 | --------------------------------------------------------------------------------