scala / scala-swing Goto Github PK
View Code? Open in Web Editor NEWScala wrappers for Java's Swing API for desktop GUIs
License: Apache License 2.0
Scala wrappers for Java's Swing API for desktop GUIs
License: Apache License 2.0
Should a CONTRIBUTING.md
guide be added? What is the policy now that the project is "community maintained". Is there still a CLA that needs to be signed, etc.?
And what would be the forum to discuss; should there be dev gitter room or so?
I'm not quite sure whether this is a bug or intended behavior: A Publisher automatically listens to itself, "for convenience". For a Component, this call to listenTo() calls Publisher's subscribe, not LazyPublisher's - because it happens within initialization, if I'm correct. Additionally, LazyPublisher.subscribe checks for listeners.size == 1 rather than 0. Is this the way it was meant to be? If so, it is at least very obscure, and it would be nice of you to add some comment, because it's hard to tell from the code what's going on and how it should be used.
My current solution is to call listenTo(this) again in my Component subclass. This works for me, but is this how you intended it to be used? Is the calling of listenTo(this) in Publisher really a good thing? Maybe it makes things more complicated than it's worth... What do you think?
Christoph
In order to make a professional swing application. I would need the possibility to add multiple, differently sized Images to the top frame.
If you can add only one icon, The icon is automatically shrieked to very low quality.
in trunk as of april 22 2010:
scala.swing.Window:
37 override def contents_=(c: Component) {
38 super.contents_=(c)
39 peer.pack() // pack also validates, which is generally required after an add
40 }
As can be seen, 'pack()' is called when changing the content of a Window. This is generally NOT what you want. Pack() has the function to resize a window to fit its contents. It's an optional feature. It is normally NOT desired when the programmer sets the size explicitly (using size = ...). It is in general NOT desired when the window has a size set before.
This can cause the window of the app to be suddenly resized when it sets e.g. a new mainpanel in it. E.g. a bank-app; Window resizes when the initial overview screen is installed; resizes again (!) when this is replaced by some detail screen.
To make things worse, imagine the end-user to resize the window to it's liking, which will be undone when the content of the window changes! (caused by this 'pack()')! That would def. be regarded as a bug.
It MIGHT be a nice initial, one-time, fallback auto-behaviour in the case when the window doesn't have a size set yet, but is requested to be displayed. (The pack() call should be moved to that function then and some condition state-checking should be added to the class).[[BR]]
BUT EVEN THEN, I am not sure that there are no valid cases for wanting to display a window with a 'zero' size (if that's the default for a window).
Joseph Darcy (@jddarcy) has tweeted ( https://twitter.com/jddarcy/status/493137546814042112 )
Swing developers, please recompile your apps with JDK 9 build 24 to test the compatibility of recent swing generification changes.
Guess this will need another branch (based on java7) with more changes.
From scala/bug#4903
scala.swing.Component's onFirstSubscribe calls super.onFirstSubscribe first, which adds a ComponentListener, then adds another one on its own. This is clearly not intended behavior.
Bye
Christoph
To enable dynamical Swing comboboxes, scala.swing.ComboBox should also be able to use the MutableComboBoxModel. Something like the addition of a mutable model in addition to the existing constant model:
class MutableModel[A](items: Buffer[A]) extends ConstantModel(items) with MutableComboBoxModel {
def removeElementAt( n: Int ) = items.remove( n )
def removeElement( item: Any ) = items.remove( items.indexOf(item) )
def insertElementAt( item: Any, n: Int ) = items.insert( n, item.asInstanceOf[A] )
def addElement( item: Any ) = items.append( item.asInstanceOf[A] )
}
The choice of the model could depend on some parameters in the constructor (e.g. matching Seq or Buffer).
Action contains the code
def title: String = ifNull(peer.getValue(javax.swing.Action.NAME),"")
def title_=(t: String) { peer.putValue(javax.swing.Action.NAME, t) }
The javax swing JavaDoc for Action http://docs.oracle.com/javase/7/docs/api/javax/swing/Action.html
manipulates the component property "text", not "title".
Action is not in the class inheritance hierarchy of any other component, so adding text defs is safe. Removing title opens up a backwards compatibility issue.
We need a compile-path friendly version of scala-swing that works with java 7 and scala 2.9, but it seems that your java 7 branch only supports scala 2.10.
Are there any plans to release java 7 friendly jars anytime soon? (from all discussions I see, this doesn't sound likely)
In lieu of this, which commit hash should I use to create a s2.9/j7 fork?
Missing method (peer.setUndecorated
)
Hi @adriaanm (/cc @fommil )
I've been asked for a scala-2.10 version so I've managed to change the build (it was only the addition to .travis.yml of scala-2.10) but that means that I need to inc the milestone number to M2 (M1 was good practice :-) )
The travis build look ok but I cannot see the sonatype destinations (asks for login ) but I think that is something on your side, can you check and do your thing.
Thanks
Travis 2.10 job: https://travis-ci.org/scala/scala-swing/jobs/50086905
Travis 2.11 job: https://travis-ci.org/scala/scala-swing/jobs/50086903
Suggested changes:
Constraints
should be a member of the companion object rather than the class, as there's no reason to tie constraint construction to a particular panel instance.
The add
method should not be protected. That may have made sense if GridBagPanel
is to be used only declaratively, but arguably this layout is too complex for that. Rather, it's a prime candidate for wrapping by some application-specific declarative framework, in which case the protection is just a pain.
The single mutating constraints object as used in the demo code is nasty. Ideally Constraints
should be a case class with keyword arguments.
it came up over at scala/sbt-scala-module#32 that @Sciss thought scala-swing was built on Java 6. I thought it was too, and the repo readme here claims it is.
but it isn't. it was, but at some point, it changed, perhaps inadvertently. I looks to me like changes were made on the 1.0.x branch that should probably only been made on 2.0.x. this included building on JDK 8 only and also dropping support for Scala 2.10, which the readme also claims 1.0.x supports.
as for the related sbt version issue:
today I closed the following scala-swing tickets in the Scala JIRA instance:
8495, 7827, 7742, 7738, 7597, 7309, 7307, 5701, 5616, 5492, 5381, 4998, 4905, 4904, 4903, 4823, 4078, 3933, 3823, 3557, 3335, 3319, 3259, 2362, 2154, 2069, 1824, 1613
many of these ought to become issues here in this repo on GitHub. interested community members are invited to open new issues for them here, with links in both directions
For some background see,
https://class.coursera.org/reactive-002/forum/thread?thread_id=719
https://class.coursera.org/reactive-002/forum/thread?thread_id=703
Below is the standalone code that demonstrates the hang for me. Note that after it hangs the GUI still continues to function - So when I say hangs - I mean the console output stops - so the event handler seems to be disconnected.
The hanging behaviour is easy to demonstrate: see the second comment.
Happens on Windows 7 64 bit Java 1.7.0_45 sbt 0.13.8 scalaVersion := "2.11.5" I'm running under sbt / clean / run.
And also under Xubuntu 14.1064 bit under sbt/clean/run and maven as described below:
Here is a tiny self contained example:
pom.xml in root directory:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SuggestionScalaSwingHang</groupId>
<artifactId>SuggestionScalaSwingHang</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-swing_2.11</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>uber</finalName>
<minimizeJar>false</minimizeJar>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>suggestions.gui.SwingHangExample</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
and here's the one source file under src/main/scala/suggestions/gui/WikipediaSuggest.scala:
package suggestions
package gui
import scala.swing.BoxPanel
import scala.swing.Dimension
import scala.swing.MainFrame
import scala.swing.Orientation.Vertical
import scala.swing.Reactions
import scala.swing.Reactions.Reaction
import scala.swing.SimpleSwingApplication
import scala.swing.Swing.EmptyBorder
import scala.swing.event.Event
import javax.swing.SwingUtilities
object SwingHangExample extends SimpleSwingApplication
{
def init(field: scala.swing.TextField) = {
val r: Reactions.Reaction = {
case(e: Event) => {
println("size:" + field.text.length + " " + SwingUtilities.isEventDispatchThread());
}
case _ => {
println("??? size:" + field.text.length + " " + SwingUtilities.isEventDispatchThread());
}
}
field.subscribe(r)
}
def top = new MainFrame {
title = "Hold down a key and wait for a few minutes - console output stops, but GUI remains operational"
minimumSize = new Dimension(900, 100)
val searchTermField = new scala.swing.TextField
contents = new BoxPanel(orientation = Vertical) {
border = EmptyBorder(top = 5, left = 5, bottom = 5, right = 5)
contents += searchTermField
}
println(System.getProperty("java.version"))
init(searchTermField)
}
}
Build with (in root directory):
mvn -U clean package
Run with
java -jar target/uber.jar
Since scala-swing has been offloaded into this module, I can not find the scaladoc to it anywhere. The scaladoc for previous versions, i.e. before scala 2.11, have been together with the scala-library at docs.scala-lang.org. Is there some place where the scaladoc is published? If not, pretty please publish it and link to it from this projects README.md.
either expose layout
or forward that method to the layout manager.
User code will not receive ListDataEvent because the model in ListView is replaced by another model in the later part of ListView constructor. As a result, the user code has to add the listener explicitly to the "other" model manually to get model's events. The same goes for new model added to ListView.
Please refer to the code attached.
In scala.swing.Table the default editor behaviour differs from the expected. The TableModel interface contains the method getColumnClass
which I expected to be used to determine the type of a column in order to select the right cell editor. Instead the code looks at the value in the cell and if it is null
the default editor for Object
is used.
// TODO: a public API for setting editors
protected def editor(row: Int, column: Int) = {
val v = apply(row, column).asInstanceOf[AnyRef]
if (v != null)
Table.this.peer.getDefaultEditor(v.getClass)
else
Table.this.peer.getDefaultEditor(classOf[Object])
Use case where this breaks: I have a date column in a table which might be null. When null I cannot enter a valid date since the wrong editor is used.
This is how I expected the code to look:
def editor(row: Int, column: Int) =
peer.getDefaultEditor(peer.getModel.getColumnClass(column))
I might be missing something, but to me it seems unnecessary to extend DefaultTableModel
at all here, the overridden method calls super
with no changes.
is defined:
object Result extends Enumeration {
import JOptionPane._
val Yes : Result.Value = Value(YES_OPTION)
val Ok : Result.Value = Value(OK_OPTION)
val No : Result.Value = Value(NO_OPTION)
val Cancel: Result.Value = Value(CANCEL_OPTION)
val Closed: Result.Value = Value(CLOSED_OPTION)
}
where
public static final int YES_OPTION = 0;
public static final int OK_OPTION = 0;
public static final int NO_OPTION = 1;
public static final int CANCEL_OPTION = 2;
public static final int CLOSED_OPTION = -1;
As you can see both YES_OPTION
and OK_OPTION
is bound to 0
.
This causes:
Exception in thread "AWT-EventQueue-1" java.lang.AssertionError: assertion failed: Duplicate id: 0
at scala.Enumeration$Val.<init>(Enumeration.scala:237)
at scala.Enumeration.Value(Enumeration.scala:177)
at scala.Enumeration.Value(Enumeration.scala:160)
at scala.swing.Dialog$Result$.<init>(RichWindow.scala:124)
at scala.swing.Dialog$Result$.<clinit>(RichWindow.scala)
when:
Dialog.showConfirmation(
parent = null,
message = "asdf",
title = "asdf",
optionType = Dialog.Options.Default,
messageType = Dialog.Message.Question)
@Sciss writes at #76 (comment) :
Regarding the book examples, the best would probably be to simply drop them into test sources, so we would automatically detect if there is a deviation introduced. I have printed copy of edition 2 somewhere buried, and the PDF of edition 1; could you perhaps - if you have PDF of the latest edition - just send me the code examples, then I can add them. In the version I'm seeing, that's listings 32.1 through 32.4, 33.1 through 33.9 ; or if they've never changed, I can copy them from my sources.
@bvenners do you have the code for this...?
and once available, add to https://github.com/scala/make-release-notes/blob/2.13.x/projects-2.13.md
Frequently, the items in the combobox are dynamic and not known at the time of the ComboBox's instantiation.
Invoking javax.swing.JTable (or hiding this invocation in scala.swing.Table) causes the table head to change to enable sorting. Selecting a row before clicking on the table head makes the selection highlighting to move. But the data in the rows does not move. The code below works with the java7 branch (October 19, 2014). It is possible to get rid of the remaining peer calls with simple modifications to the source.
I maintain legacy lib ScalaSwingContrib and are publishing for 2.12. Was surprised to find only a milestone builds for 2.12.x.
Seems there isn't any likely prospect of much more work on Swing lib, so could we re-publish as 2.0.0
? The M2
suffix suggests expected changes coming...
Testing Ive done with M2
on 2.12:
Unit tests for ScalaSwingContrib plus manual testing of its 3 demos all look good
[1] scalaswingcontrib.test.ColorChooserDemo
[2] scalaswingcontrib.test.TreeDemo
[3] scalaswingcontrib.test.group.GroupLayoutDemo
there are three at https://github.com/scala/scala-swing/settings/hooks. two are bitbucket, one is waffle.io.
are these still useful/relevant? what do they do?
is one of them the thing adding e.g. "odersky added the in progress label 7 hours ago" to e.g. #54 ?
java7 branch is tracking scala 2.11
The default tool tip is ""
, and the constructor does tip = tip0
, resulting, depending on the look and feel, in an empty but nevertheless visible/popping up tool tip.
Probably the call to setToolTipTextAt
should map ""
to null
.
From scala/bug#7738
SplitPane is passing java.awt.Adjustable.HORIZONTAL and etc to JSplitPane, but the latter expects its own constants like JSplitPane.HORIZONTAL_SPLIT. In fact, these values aren't the same.
I miss the GroupPanel (Scala 2.8 RC1). So I have implemented a first simple version.
It does not yet offer all features of GroupPanel, but you can write
some gui very easy and straightforward.
Attached you find the GroupPanel.scala and 2 demo apps.
no traffic in a long time โย I don't think the library needs a dedicated group
@Sciss you are our most prolific contributor and probably know the codebase better than anyone. Would you be interested in joining as a maintainer?
If you'd like for the next version of scala-swing to be included in Scala 2.11.5, please tag a release (right here on github! :-)) and have it on Maven Central by Dec 12. Once it's on maven, submit a PR to scala/scala to update https://github.com/scala/scala/blob/2.11.x/versions.properties#L24
missing method
We need some help getting this done. As Scala Swing heavily relies on the collections API, I assume this is not a trivial task. Opening this issue as a point of contact.
Here is a simple implementation:
import swing.{Component, LayoutContainer, Panel}
import java.awt.CardLayout
class CardPanel extends Panel with LayoutContainer {
type Constraints = String
def layoutManager = peer.getLayout.asInstanceOf[CardLayout]
override lazy val peer = new javax.swing.JPanel(new CardLayout) with SuperMixin
private var cards : Map[String, Component] = Map.empty
protected def areValid(c: Constraints) = (true, "")
protected def add(comp: Component, l: Constraints) = {
// we need to remove previous components with the same constraints as the new one,
// otherwise the layout manager loses track of the old one
cards.get(l).foreach { old => cards -= l; peer.remove(old.peer) }
cards += (l -> comp)
peer.add(comp.peer, l)
}
def show(l : Constraints) = layoutManager.show(peer, l)
protected def constraintsFor(comp: Component) = cards.iterator.find { case (_, c) => c eq comp}.map(_._1).orNull
}
There is a swing.Action with peer javax.swing.Action,
but there is no TextAction with peer javax.swing.text.TextAction.
From the API of javax.swing.text.TextAction
* An Action implementation useful for key bindings that are shared across
* a number of different text components.
A TextAction has no explicit reference to a TextCompont,
but it acts on the last focused TextComponent. So you can have
a MenuItem with a TextAction which can act on each
TextComponent of the swing application.
Attached there is an implementation and an example app with
TextAction changing the fontsize.
Frank
From scala/bug#1824
the swing lib shows
class FileChooser(dir : java.io.File) extends AnyRef
but JFileChooser sends PropertyChangeEvents and ActionEvents.
This feature is essential e.g. for accessory components.http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html#accessory
So here is something that had me scratch my head for quite some time. Sometimes, Reactors would not get notified by a publisher. This didn't happen very often, but often enough to break some functionality.
It turned out that it was caused by the mutable nature of the swing.Publisher#listeners. More precisely, it sometimes happens when a listener, in reaction to an event, decides to unsubscribe from the publisher, i.e., calls deafTo(). This immediately causes the listeners to change state, and therefore may lead to the for comprehension to terminate early, without notifying subsequent listeners.
I think that "if a specific event happens on a publisher, I'm not interested in that publisher anymore" is a valid and not terribly exotic use case for a Reactor, so I consider the current behavior a bug.
I'm attaching a scalatest class which triggers the bug (and also contains one possible solution).
These should be shortcuts to layoutManager.setHgap
, getHgap
etc.
just like e.g. scala/scala-xml#242 and scala/scala-parser-combinators#184
The following code prints 0, the length of the menu's contents field, but it should be 1. It is also impossible to access the elements in contents.
It is interesting to note, however, that if the menu was to be shown, it would indeed have the item "foobar" in it.
import scala.swing._
val menu = new Menu("File") {
contents += new MenuItem("foobar")
}
println(menu.contents.length)
the standard.sbt calculation to compute the scala binary version looks like it was written for 2.10+
A component that extends scala.swing.Scrollable (but not Scrollable.Wrapper) should cause the component's peer to implement javax.swing.Scrollable and forward the latter's methods to the former. That way, custom components can be made scrollable.
In 2.8.0, this is not the case. Rather, extending scala.swing.Scrollable and implementing its methods for a custom scrollable component has no effect, since the resulting peer doesn't implement javax.swing.Scrollable.
Hi @adriaanm
Following on from #33
I'm trying to get a tagged release (tag: v2.0.0-M2) of the java7 branch onto sonatype/maven.com however, as you may guess, its not arriving. I'm copied all your changes to 'master' to the 'java7' branch, hopefully successfully :-)
I'm
Do you know what I'm doing wrong or who to talk to
Thanks
Andy
javax.swing.Action (http://docs.oracle.com/javase/7/docs/api/javax/swing/Action.html ) uses two keys to set the icon property of the components that are constructed with Action instances. The two are LARGE_ICON_KEY and SMALL_ICON. The LARGE_ICON_KEY is used to set the icon property of most Swing components that are AbstractButtons except for MenuItems. The SMALL_ICON property applies when the Action is used to construct MenuItems.
scala.swing.Action should have defs for smallIcon. The MenuItem constructor that takes an Action argument should assign MenuItem icon with the value from Action.smallIcon.
The existing icon defs in scala.swing.Action can remain unchanged.
See this StackOverflow problem that contains a demonstration example. The bug apparently is in the override of the cell renderer in the peer object. The following "fixes" the bug:
new Table {
// disable broken renderer
override lazy val peer: JTable = new JTable with SuperMixin
}
So the getCellRenderer
must be doing something wrong in terms of view versus model indices.
Perhaps related: #30 (says column-sorting though)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.