Skip to content

Commit 07ce708

Browse files
authored
Merge pull request #100 from Sciss/work
Fix Scala 2.13.0-RC1 compilation, fix a number of simple bugs / enhancements
2 parents 732c1cc + 6af7315 commit 07ce708

File tree

9 files changed

+147
-62
lines changed

9 files changed

+147
-62
lines changed

Diff for: build.sbt

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ scalaModuleSettings
44

55
name := "scala-swing"
66

7-
version := "2.1.1-SNAPSHOT"
7+
version := "2.1.1"
88

99
scalacOptions in ThisBuild ++= Seq("-deprecation", "-feature")
1010

1111
// Map[JvmMajorVersion, List[(ScalaVersion, UseForPublishing)]]
1212
scalaVersionsByJvm in ThisBuild := Map(
13-
8 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> true),
14-
9 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
15-
10 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
16-
11 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
17-
12 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false)
13+
8 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> true),
14+
9 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
15+
10 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
16+
11 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
17+
12 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false)
1818
)
1919

20-
scalaVersion in ThisBuild := "2.13.0-M5" // for testing
20+
scalaVersion in ThisBuild := "2.12.8"
2121

2222
OsgiKeys.exportPackage := Seq(s"scala.swing.*;version=${version.value}")
2323

@@ -29,7 +29,7 @@ shellPrompt in ThisBuild := { state => Project.extract(state).currentRef.project
2929
lazy val swing = project.in(file("."))
3030
.settings(
3131
libraryDependencies += {
32-
"org.scalatest" %% "scalatest" % "3.0.7" % Test
32+
"org.scalatest" %% "scalatest" % "3.0.8-RC2" % Test
3333
},
3434
// Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer
3535
// and a `src/main/scala-2.13-` source directory for Scala version older than 2.13

Diff for: src/main/scala-2.13+/scala/swing/BufferWrapper.scala

+2-4
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,11 @@ abstract class BufferWrapper[A] extends mutable.Buffer[A] {
4848
}
4949
}
5050

51-
override def patchInPlace(from: Int, patch: scala.collection.Seq[A], replaced: Int): this.type = {
51+
override def patchInPlace(from: Int, patch: MoreElem[A], replaced: Int): this.type = {
5252
if (replaced > 0) {
5353
remove(from, replaced)
5454
}
55-
if (patch.nonEmpty) {
56-
insertAll(from, patch)
57-
}
55+
insertAll(from, patch)
5856
this
5957
}
6058
}

Diff for: src/main/scala/scala/swing/Action.scala

+17-5
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,23 @@ abstract class Action(title0: String) {
8181
def actionPerformed(a: java.awt.event.ActionEvent): Unit = apply()
8282
}
8383

84-
/**
85-
* Title is not optional.
86-
*/
87-
def title: String = ifNull(peer.getValue(javax.swing.Action.NAME),"")
88-
def title_=(t: String): Unit = peer.putValue(javax.swing.Action.NAME, t)
84+
/** Gets the `NAME` property.
85+
*/
86+
def text: String = ifNull(peer.getValue(javax.swing.Action.NAME),"")
87+
88+
/** Sets the `NAME` property.
89+
*/
90+
def text_=(t: String): Unit = peer.putValue(javax.swing.Action.NAME, t)
91+
92+
/** An alias for `text`. This is kept for backwards compatibility.
93+
*
94+
* @see [[text]]
95+
*/
96+
def title: String = text
97+
98+
/** An alias for `text_=`. This is kept for backwards compatibility.
99+
*/
100+
def title_=(t: String): Unit = text = t
89101

90102
/**
91103
* None if large icon and small icon are not equal.

Diff for: src/main/scala/scala/swing/Component.scala

-14
Original file line numberDiff line numberDiff line change
@@ -203,20 +203,6 @@ abstract class Component extends UIElement {
203203

204204
protected override def onFirstSubscribe(): Unit = {
205205
super.onFirstSubscribe()
206-
// TODO: deprecated, remove after 2.8
207-
peer.addComponentListener(new java.awt.event.ComponentListener {
208-
def componentHidden(e: java.awt.event.ComponentEvent): Unit =
209-
publish(event.UIElementHidden(Component.this))
210-
211-
def componentShown(e: java.awt.event.ComponentEvent): Unit =
212-
publish(event.UIElementShown(Component.this))
213-
214-
def componentMoved(e: java.awt.event.ComponentEvent): Unit =
215-
publish(event.UIElementMoved(Component.this))
216-
217-
def componentResized(e: java.awt.event.ComponentEvent): Unit =
218-
publish(event.UIElementResized(Component.this))
219-
})
220206

221207
peer.addFocusListener(new java.awt.event.FocusListener {
222208
def other(e: java.awt.event.FocusEvent): Option[Component] = e.getOppositeComponent match {

Diff for: src/main/scala/scala/swing/FileChooser.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ object FileChooser {
4646
*
4747
* @see [[http://docs.oracle.com/javase/7/docs/api/javax/swing/JFileChooser.html javax.swing.JFileChooser]]
4848
*/
49-
class FileChooser(dir: File) {
49+
class FileChooser(dir: File) extends Component {
5050
import scala.swing.FileChooser._
51-
lazy val peer: JFileChooser = new JFileChooser(dir)
51+
override lazy val peer: JFileChooser = new JFileChooser(dir)
5252

5353
def this() = this(null)
5454

Diff for: src/main/scala/scala/swing/FlowPanel.scala

+8-4
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ class FlowPanel(alignment: FlowPanel.Alignment.Value)(contents0: Component*) ext
4343

4444
private def layoutManager: FlowLayout = peer.getLayout.asInstanceOf[FlowLayout]
4545

46-
def vGap: Int = layoutManager.getVgap
47-
def vGap_=(n: Int): Unit = layoutManager.setVgap(n)
48-
def hGap: Int = layoutManager.getHgap
49-
def hGap_=(n: Int): Unit = layoutManager.setHgap(n)
46+
def vGap : Int = layoutManager.getVgap
47+
def vGap_=(n: Int): Unit = layoutManager.setVgap(n)
48+
49+
def hGap : Int = layoutManager.getHgap
50+
def hGap_=(n: Int): Unit = layoutManager.setHgap(n)
51+
52+
def alignOnBaseline : Boolean = layoutManager.getAlignOnBaseline
53+
def alignOnBaseline_=(value : Boolean): Unit = layoutManager.setAlignOnBaseline(value)
5054
}

Diff for: src/main/scala/scala/swing/PopupMenu.scala

+6
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,13 @@ class PopupMenu extends Component with SequentialContainer.Wrapper with Publishe
5959
def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y)
6060

6161
def margin: Insets = peer.getMargin
62+
6263
def label: String = peer.getLabel
6364
def label_=(s: String): Unit = peer.setLabel(s)
65+
66+
/** Lays out the popup menu so that it uses the minimum space
67+
* needed to display its contents.
68+
*/
69+
def pack(): Unit = peer.pack()
6470
}
6571

Diff for: src/main/scala/scala/swing/SplitPane.scala

+40-25
Original file line numberDiff line numberDiff line change
@@ -17,54 +17,69 @@ import javax.swing.JSplitPane
1717
import scala.collection.immutable
1818
import scala.swing.Swing.nullPeer
1919

20-
/**
21-
* A container with exactly two children. Arranges them side by side, either
22-
* horizontally or vertically. Displays a draggable divider component between
23-
* them that lets the user adjust the size ratio of the children.
24-
*
25-
* @see javax.swing.JSplitPane
26-
*/
27-
class SplitPane(o: Orientation.Value, left: Component, right: Component) extends Component with Container with Orientable.Wrapper {
28-
override lazy val peer: JSplitPane =
29-
new javax.swing.JSplitPane(o.id, left.peer, right.peer) with SuperMixin
20+
/** A container with exactly two children. Arranges them side by side, either
21+
* horizontally or vertically. Displays a draggable divider component between
22+
* them that lets the user adjust the size ratio of the children.
23+
*
24+
* @param o the orientation of the divider. Note that we are using
25+
* `Orientation.Horizontal` and `Orientation.Vertical`, which are
26+
* different from the underlying `JSplitPane` values.
27+
* `Orientation.Horizontal` corresponds with `VERTICAL_SPLIT`, thus
28+
* producing a left and right component and a "vertical divider",
29+
* and `Orientation.Vertical` corresponds with `HORIZONTAL_SPLIT`, thus
30+
* producing a top and bottom component and a "horizontal divider".
31+
*
32+
* @see javax.swing.JSplitPane
33+
*/
34+
class SplitPane(o: Orientation.Value, left: Component, right: Component)
35+
extends Component with Container with Orientable.Wrapper {
36+
3037
def this(o: Orientation.Value) = this(o, new Component {}, new Component {})
3138
def this() = this(Orientation.Horizontal)
3239

40+
override lazy val peer: JSplitPane =
41+
new javax.swing.JSplitPane(o.id, left.peer, right.peer) with SuperMixin
42+
3343
def contents: immutable.Seq[Component] = List(leftComponent, rightComponent)
44+
3445
def contents_=(left: Component, right: Component): Unit = {
35-
peer.setLeftComponent(nullPeer(left))
46+
peer.setLeftComponent (nullPeer(left))
3647
peer.setRightComponent(nullPeer(right))
3748
}
3849

3950
def topComponent: Component =
4051
UIElement.cachedWrapper[Component](peer.getTopComponent.asInstanceOf[javax.swing.JComponent])
4152
def topComponent_=(c: Component): Unit = peer.setTopComponent(nullPeer(c))
53+
4254
def bottomComponent: Component =
4355
UIElement.cachedWrapper[Component](peer.getBottomComponent.asInstanceOf[javax.swing.JComponent])
4456
def bottomComponent_=(c: Component): Unit = peer.setBottomComponent(nullPeer(c))
4557

46-
def leftComponent: Component = topComponent
47-
def leftComponent_=(c: Component): Unit = { topComponent = c }
48-
def rightComponent: Component = bottomComponent
49-
def rightComponent_=(c: Component): Unit = { bottomComponent = c }
58+
def leftComponent : Component = topComponent
59+
def leftComponent_= (c: Component): Unit = { topComponent = c }
5060

51-
def dividerLocation: Int = peer.getDividerLocation
52-
def dividerLocation_=(n: Int): Unit = peer.setDividerLocation(n)
61+
def rightComponent : Component = bottomComponent
62+
def rightComponent_=(c: Component): Unit = { bottomComponent = c }
63+
64+
def dividerLocation : Int = peer.getDividerLocation
65+
def dividerLocation_= (n: Int): Unit = peer.setDividerLocation(n)
5366

5467
/*def proportionalDividerLocation: Double =
5568
if (orientation == Orientation.Vertical) dividerLocation / (size.height - dividerSize)
5669
else dividerLocation / (size.width - dividerSize)*/
5770
def dividerLocation_=(f: Double): Unit = peer.setDividerLocation(f)
5871

59-
def dividerSize: Int = peer.getDividerSize
60-
def dividerSize_=(n: Int): Unit = peer.setDividerSize(n)
61-
def resizeWeight: Double = peer.getResizeWeight
62-
def resizeWeight_=(n: Double): Unit = peer.setResizeWeight(n)
72+
def dividerSize : Int = peer.getDividerSize
73+
def dividerSize_= (n: Int): Unit = peer.setDividerSize(n)
74+
75+
def resizeWeight : Double = peer.getResizeWeight
76+
def resizeWeight_= (n: Double): Unit = peer.setResizeWeight(n)
6377

6478
def resetToPreferredSizes(): Unit = peer.resetToPreferredSizes()
6579

66-
def oneTouchExpandable: Boolean = peer.isOneTouchExpandable
67-
def oneTouchExpandable_=(b: Boolean): Unit = peer.setOneTouchExpandable(b)
68-
def continuousLayout: Boolean = peer.isContinuousLayout
69-
def continuousLayout_=(b: Boolean): Unit = peer.setContinuousLayout(b)
80+
def oneTouchExpandable : Boolean = peer.isOneTouchExpandable
81+
def oneTouchExpandable_=(b: Boolean): Unit = peer.setOneTouchExpandable(b)
82+
83+
def continuousLayout : Boolean = peer.isContinuousLayout
84+
def continuousLayout_= (b: Boolean): Unit = peer.setContinuousLayout(b)
7085
}

Diff for: src/test/scala/scala/swing/Issue97.scala

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package scala.swing
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.scalatest.{FlatSpec, Matchers}
6+
7+
import scala.concurrent.duration.Duration
8+
import scala.concurrent.{Await, Future, Promise}
9+
import scala.swing.event.{UIElementHidden, UIElementMoved, UIElementResized, UIElementShown}
10+
import scala.util.control.NonFatal
11+
12+
// Note: `AsyncFlatSpec` has issues with swallowing errors and returning early.
13+
class Issue97 extends FlatSpec with Matchers {
14+
case class Count(shown: Int = 0, hidden: Int = 0, moved: Int = 0, resized: Int = 0)
15+
16+
def countEvents(): Future[Count] = {
17+
val p = Promise[Count]()
18+
19+
def safely(thunk: => Unit): Unit =
20+
try {
21+
thunk
22+
} catch {
23+
case NonFatal(ex) =>
24+
p.tryFailure(ex)
25+
}
26+
27+
Swing.onEDT {
28+
safely {
29+
var c = Count()
30+
val lb = new Label("Foo")
31+
lb.listenTo(lb)
32+
lb.reactions += {
33+
case UIElementShown (`lb`) => c = c.copy(shown = c.shown + 1)
34+
case UIElementHidden (`lb`) => c = c.copy(hidden = c.hidden + 1)
35+
case UIElementMoved (`lb`) => c = c.copy(moved = c.moved + 1)
36+
case UIElementResized (`lb`) => c = c.copy(resized = c.resized + 1)
37+
}
38+
val b = new BoxPanel(Orientation.Horizontal)
39+
b.contents += lb
40+
lb.visible = false
41+
lb.visible = true
42+
b.contents.insert(0, new Label("Bar")) // about to move `lb` to the right
43+
b.peer.doLayout()
44+
// note: `Frame#pack()` creates a native window peer,
45+
// and thus is not possible to run on Travis without X11
46+
47+
// wait till next EDT cycle
48+
Swing.onEDT {
49+
p.trySuccess(c)
50+
}
51+
}
52+
}
53+
p.future
54+
}
55+
56+
"Components" should "fire exactly one event when moved, removed or made visible or invisible" in {
57+
val futCount = countEvents()
58+
val c = Await.result(futCount, Duration(20, TimeUnit.SECONDS))
59+
assert(c.shown === 1)
60+
assert(c.hidden === 1)
61+
assert(c.moved === 1)
62+
assert(c.resized === 1)
63+
}
64+
}

0 commit comments

Comments
 (0)