Skip to content

Fix Scala 2.13.0-RC1 compilation, fix a number of simple bugs / enhancements #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ scalaModuleSettings

name := "scala-swing"

version := "2.1.1-SNAPSHOT"
version := "2.1.1"

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

// Map[JvmMajorVersion, List[(ScalaVersion, UseForPublishing)]]
scalaVersionsByJvm in ThisBuild := Map(
8 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> true),
9 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
10 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
11 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false),
12 -> List("2.11.12", "2.12.8", "2.13.0-M5").map(_ -> false)
8 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> true),
9 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
10 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
11 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false),
12 -> List("2.11.12", "2.12.8", "2.13.0-RC1").map(_ -> false)
)

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

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

Expand All @@ -29,7 +29,7 @@ shellPrompt in ThisBuild := { state => Project.extract(state).currentRef.project
lazy val swing = project.in(file("."))
.settings(
libraryDependencies += {
"org.scalatest" %% "scalatest" % "3.0.7" % Test
"org.scalatest" %% "scalatest" % "3.0.8-RC2" % Test
},
// Adds a `src/main/scala-2.13+` source directory for Scala 2.13 and newer
// and a `src/main/scala-2.13-` source directory for Scala version older than 2.13
Expand Down
6 changes: 2 additions & 4 deletions src/main/scala-2.13+/scala/swing/BufferWrapper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ abstract class BufferWrapper[A] extends mutable.Buffer[A] {
}
}

override def patchInPlace(from: Int, patch: scala.collection.Seq[A], replaced: Int): this.type = {
override def patchInPlace(from: Int, patch: MoreElem[A], replaced: Int): this.type = {
if (replaced > 0) {
remove(from, replaced)
}
if (patch.nonEmpty) {
insertAll(from, patch)
}
insertAll(from, patch)
this
}
}
22 changes: 17 additions & 5 deletions src/main/scala/scala/swing/Action.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,23 @@ abstract class Action(title0: String) {
def actionPerformed(a: java.awt.event.ActionEvent): Unit = apply()
}

/**
* Title is not optional.
*/
def title: String = ifNull(peer.getValue(javax.swing.Action.NAME),"")
def title_=(t: String): Unit = peer.putValue(javax.swing.Action.NAME, t)
/** Gets the `NAME` property.
*/
def text: String = ifNull(peer.getValue(javax.swing.Action.NAME),"")

/** Sets the `NAME` property.
*/
def text_=(t: String): Unit = peer.putValue(javax.swing.Action.NAME, t)

/** An alias for `text`. This is kept for backwards compatibility.
*
* @see [[text]]
*/
def title: String = text

/** An alias for `text_=`. This is kept for backwards compatibility.
*/
def title_=(t: String): Unit = text = t

/**
* None if large icon and small icon are not equal.
Expand Down
14 changes: 0 additions & 14 deletions src/main/scala/scala/swing/Component.scala
Original file line number Diff line number Diff line change
Expand Up @@ -203,20 +203,6 @@ abstract class Component extends UIElement {

protected override def onFirstSubscribe(): Unit = {
super.onFirstSubscribe()
// TODO: deprecated, remove after 2.8
peer.addComponentListener(new java.awt.event.ComponentListener {
def componentHidden(e: java.awt.event.ComponentEvent): Unit =
publish(event.UIElementHidden(Component.this))

def componentShown(e: java.awt.event.ComponentEvent): Unit =
publish(event.UIElementShown(Component.this))

def componentMoved(e: java.awt.event.ComponentEvent): Unit =
publish(event.UIElementMoved(Component.this))

def componentResized(e: java.awt.event.ComponentEvent): Unit =
publish(event.UIElementResized(Component.this))
})

peer.addFocusListener(new java.awt.event.FocusListener {
def other(e: java.awt.event.FocusEvent): Option[Component] = e.getOppositeComponent match {
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/scala/swing/FileChooser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ object FileChooser {
*
* @see [[http://docs.oracle.com/javase/7/docs/api/javax/swing/JFileChooser.html javax.swing.JFileChooser]]
*/
class FileChooser(dir: File) {
class FileChooser(dir: File) extends Component {
import scala.swing.FileChooser._
lazy val peer: JFileChooser = new JFileChooser(dir)
override lazy val peer: JFileChooser = new JFileChooser(dir)

def this() = this(null)

Expand Down
12 changes: 8 additions & 4 deletions src/main/scala/scala/swing/FlowPanel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ class FlowPanel(alignment: FlowPanel.Alignment.Value)(contents0: Component*) ext

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

def vGap: Int = layoutManager.getVgap
def vGap_=(n: Int): Unit = layoutManager.setVgap(n)
def hGap: Int = layoutManager.getHgap
def hGap_=(n: Int): Unit = layoutManager.setHgap(n)
def vGap : Int = layoutManager.getVgap
def vGap_=(n: Int): Unit = layoutManager.setVgap(n)

def hGap : Int = layoutManager.getHgap
def hGap_=(n: Int): Unit = layoutManager.setHgap(n)

def alignOnBaseline : Boolean = layoutManager.getAlignOnBaseline
def alignOnBaseline_=(value : Boolean): Unit = layoutManager.setAlignOnBaseline(value)
}
6 changes: 6 additions & 0 deletions src/main/scala/scala/swing/PopupMenu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ class PopupMenu extends Component with SequentialContainer.Wrapper with Publishe
def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y)

def margin: Insets = peer.getMargin

def label: String = peer.getLabel
def label_=(s: String): Unit = peer.setLabel(s)

/** Lays out the popup menu so that it uses the minimum space
* needed to display its contents.
*/
def pack(): Unit = peer.pack()
}

65 changes: 40 additions & 25 deletions src/main/scala/scala/swing/SplitPane.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,69 @@ import javax.swing.JSplitPane
import scala.collection.immutable
import scala.swing.Swing.nullPeer

/**
* A container with exactly two children. Arranges them side by side, either
* horizontally or vertically. Displays a draggable divider component between
* them that lets the user adjust the size ratio of the children.
*
* @see javax.swing.JSplitPane
*/
class SplitPane(o: Orientation.Value, left: Component, right: Component) extends Component with Container with Orientable.Wrapper {
override lazy val peer: JSplitPane =
new javax.swing.JSplitPane(o.id, left.peer, right.peer) with SuperMixin
/** A container with exactly two children. Arranges them side by side, either
* horizontally or vertically. Displays a draggable divider component between
* them that lets the user adjust the size ratio of the children.
*
* @param o the orientation of the divider. Note that we are using
* `Orientation.Horizontal` and `Orientation.Vertical`, which are
* different from the underlying `JSplitPane` values.
* `Orientation.Horizontal` corresponds with `VERTICAL_SPLIT`, thus
* producing a left and right component and a "vertical divider",
* and `Orientation.Vertical` corresponds with `HORIZONTAL_SPLIT`, thus
* producing a top and bottom component and a "horizontal divider".
*
* @see javax.swing.JSplitPane
*/
class SplitPane(o: Orientation.Value, left: Component, right: Component)
extends Component with Container with Orientable.Wrapper {

def this(o: Orientation.Value) = this(o, new Component {}, new Component {})
def this() = this(Orientation.Horizontal)

override lazy val peer: JSplitPane =
new javax.swing.JSplitPane(o.id, left.peer, right.peer) with SuperMixin

def contents: immutable.Seq[Component] = List(leftComponent, rightComponent)

def contents_=(left: Component, right: Component): Unit = {
peer.setLeftComponent(nullPeer(left))
peer.setLeftComponent (nullPeer(left))
peer.setRightComponent(nullPeer(right))
}

def topComponent: Component =
UIElement.cachedWrapper[Component](peer.getTopComponent.asInstanceOf[javax.swing.JComponent])
def topComponent_=(c: Component): Unit = peer.setTopComponent(nullPeer(c))

def bottomComponent: Component =
UIElement.cachedWrapper[Component](peer.getBottomComponent.asInstanceOf[javax.swing.JComponent])
def bottomComponent_=(c: Component): Unit = peer.setBottomComponent(nullPeer(c))

def leftComponent: Component = topComponent
def leftComponent_=(c: Component): Unit = { topComponent = c }
def rightComponent: Component = bottomComponent
def rightComponent_=(c: Component): Unit = { bottomComponent = c }
def leftComponent : Component = topComponent
def leftComponent_= (c: Component): Unit = { topComponent = c }

def dividerLocation: Int = peer.getDividerLocation
def dividerLocation_=(n: Int): Unit = peer.setDividerLocation(n)
def rightComponent : Component = bottomComponent
def rightComponent_=(c: Component): Unit = { bottomComponent = c }

def dividerLocation : Int = peer.getDividerLocation
def dividerLocation_= (n: Int): Unit = peer.setDividerLocation(n)

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

def dividerSize: Int = peer.getDividerSize
def dividerSize_=(n: Int): Unit = peer.setDividerSize(n)
def resizeWeight: Double = peer.getResizeWeight
def resizeWeight_=(n: Double): Unit = peer.setResizeWeight(n)
def dividerSize : Int = peer.getDividerSize
def dividerSize_= (n: Int): Unit = peer.setDividerSize(n)

def resizeWeight : Double = peer.getResizeWeight
def resizeWeight_= (n: Double): Unit = peer.setResizeWeight(n)

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

def oneTouchExpandable: Boolean = peer.isOneTouchExpandable
def oneTouchExpandable_=(b: Boolean): Unit = peer.setOneTouchExpandable(b)
def continuousLayout: Boolean = peer.isContinuousLayout
def continuousLayout_=(b: Boolean): Unit = peer.setContinuousLayout(b)
def oneTouchExpandable : Boolean = peer.isOneTouchExpandable
def oneTouchExpandable_=(b: Boolean): Unit = peer.setOneTouchExpandable(b)

def continuousLayout : Boolean = peer.isContinuousLayout
def continuousLayout_= (b: Boolean): Unit = peer.setContinuousLayout(b)
}
64 changes: 64 additions & 0 deletions src/test/scala/scala/swing/Issue97.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package scala.swing

import java.util.concurrent.TimeUnit

import org.scalatest.{FlatSpec, Matchers}

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future, Promise}
import scala.swing.event.{UIElementHidden, UIElementMoved, UIElementResized, UIElementShown}
import scala.util.control.NonFatal

// Note: `AsyncFlatSpec` has issues with swallowing errors and returning early.
class Issue97 extends FlatSpec with Matchers {
case class Count(shown: Int = 0, hidden: Int = 0, moved: Int = 0, resized: Int = 0)

def countEvents(): Future[Count] = {
val p = Promise[Count]()

def safely(thunk: => Unit): Unit =
try {
thunk
} catch {
case NonFatal(ex) =>
p.tryFailure(ex)
}

Swing.onEDT {
safely {
var c = Count()
val lb = new Label("Foo")
lb.listenTo(lb)
lb.reactions += {
case UIElementShown (`lb`) => c = c.copy(shown = c.shown + 1)
case UIElementHidden (`lb`) => c = c.copy(hidden = c.hidden + 1)
case UIElementMoved (`lb`) => c = c.copy(moved = c.moved + 1)
case UIElementResized (`lb`) => c = c.copy(resized = c.resized + 1)
}
val b = new BoxPanel(Orientation.Horizontal)
b.contents += lb
lb.visible = false
lb.visible = true
b.contents.insert(0, new Label("Bar")) // about to move `lb` to the right
b.peer.doLayout()
// note: `Frame#pack()` creates a native window peer,
// and thus is not possible to run on Travis without X11

// wait till next EDT cycle
Swing.onEDT {
p.trySuccess(c)
}
}
}
p.future
}

"Components" should "fire exactly one event when moved, removed or made visible or invisible" in {
val futCount = countEvents()
val c = Await.result(futCount, Duration(20, TimeUnit.SECONDS))
assert(c.shown === 1)
assert(c.hidden === 1)
assert(c.moved === 1)
assert(c.resized === 1)
}
}