clj-commons / seesaw Goto Github PK
View Code? Open in Web Editor NEWSeesaw turns the Horror of Swing into a friendly, well-documented, Clojure library
Home Page: https://groups.google.com/group/seesaw-clj
Seesaw turns the Horror of Swing into a friendly, well-documented, Clojure library
Home Page: https://groups.google.com/group/seesaw-clj
minimize, maximize, etc.
Preferably with a nice mapping onto a clojure-y data model.
The docstring says
(listen (text)
#{:remove-update insert-update} (fn [e] ...))
where it should say
(listen (text)
#{:remove-update :insert-update} (fn [e] ...))
JTable has got to be the most disgustingly over complex and insane thing I've ever ran into while using Swing. Not that it's all bad. JTable is designed to make very, very, very hard things possible. Unfortunately, it makes very, very, very simple things very, very, very hard. I think that JTable is something that Seesaw can really make a lot funner to use.
For the most part, there is no perfect way to wrap JTable in it's entirety. Instead, my thoughts are that we could provide a wrapper around a very generalized use of JTable that makes it feel more dynamic and Clojure-like.
For an example of the pain that JTable deals out, check this out: https://github.com/Raynes/tallyho
When (native!)
is called it automatically chooses the system look and feel. There should be some way to override this behavior for users that prefer a different L&F. Maybe a system property?
For complex widgets like tree and table (selection)
gives back a pretty vanilla value, row indices in the case of table. Maybe there's a way to associate a user-supplied selection adapter function with a widget so they can customize what selection
gives back.
Reference: https://groups.google.com/group/seesaw-clj/t/2266f24fc785dd5f
Currently when creating an Action the syntax :tip ::myaction.tip
doesn't work.
Would you add this one, too?
See this ML thread: https://groups.google.com/group/seesaw-clj/browse_thread/thread/d883ab3c78497bc6
In version 1.0.7 of seesaw.
I create a horizontal panel using code like: (seesaw-core/horizontal-panel :id :has-panel :items [...])
Later I try to get the panel using code like: (seesaw-core/select parent-component ["#has-panel"]) where parent-component is the frame containing the panel.
For some reason, the select above always returns nil. It should be returning the JPanel created with the call to horizontal-panel.
hi
some defs are as the subject line:
width
height
^javax.swing.SpinnerModel
canvas
add!
thanks for making my life easier with ui.
cheers
For example, (make-widget "hi")
returns a JLabel
with no metadata so config!
and friend won't work on it.
Stack overflow occurs when applying text function to combobox. I know I must use selection instead, but I still think it is an error. I think It should show something like "Unable to apply text to combobox" instead of confusing stack overflow.
user=> (text (combobox :model [1 2 3]))
StackOverflowError seesaw.core/eval2730/fn--2731/G--2719--2736 (core.clj:599)
user=> (try (text (combobox :model [1 2 3])) (catch Error e (.printStackTrace e)))
java.lang.StackOverflowError
at seesaw.to_widget$eval369$fn__370$G__360__375.invoke(to_widget.clj:16)
at seesaw.core$to_widget.invoke(core.clj:188)
at seesaw.core$eval2790$fn__2791.invoke(core.clj:606)
at seesaw.core$eval2730$fn__2731$G__2719__2736.invoke(core.clj:599)
at seesaw.core$eval2790$fn__2791.invoke(core.clj:606)
at seesaw.core$eval2730$fn__2731$G__2719__2736.invoke(core.clj:599)
at seesaw.core$eval2790$fn__2791.invoke(core.clj:606)
at seesaw.core$eval2730$fn__2731$G__2719__2736.invoke(core.clj:599)
at seesaw.core$eval2790$fn__2791.invoke(core.clj:606)
......
@actsasgeek put together some notional OSX app support for stuff like the dock name, and various OSX-specific menus here: https://gist.github.com/2720254. Integrate it as an optional Seesaw module or something. Some random thoughts:
config!
supportlisten
center-frame!
should be part of Seesaw core, possibly as a variant of move!
.at seesaw-1.3.0
(ns seesawbug.core
(:use seesaw.core))
(defn -main []
(-> (dialog
:type :plain
:option-type :ok-cancel
:content "press ESC key!")
pack! show!))
When I pressed ESC key, the following exception to console:
Exception occurred during event dispatching:
java.lang.IndexOutOfBoundsException
at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:106)
at clojure.lang.PersistentVector.nth(PersistentVector.java:110)
at clojure.lang.APersistentVector.invoke(APersistentVector.java:249)
at seesaw.core$dialog$reify__3918.propertyChange(core.clj:3097)
at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:298)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:292)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:229)
at java.awt.Component.firePropertyChange(Component.java:8148)
at javax.swing.JOptionPane.setValue(JOptionPane.java:1964)
at javax.swing.plaf.basic.BasicOptionPaneUI$Actions.actionPerformed(BasicOptionPaneUI.java:1396)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1660)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2851)
at javax.swing.KeyboardManager.fireBinding(KeyboardManager.java:285)
at javax.swing.KeyboardManager.fireKeyboardAction(KeyboardManager.java:234)
at javax.swing.JComponent.processKeyBindingsForAllComponents(JComponent.java:2928)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2920)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2814)
at java.awt.Component.processEvent(Component.java:6045)
at java.awt.Container.processEvent(Container.java:2045)
at java.awt.Component.dispatchEventImpl(Component.java:4629)
at java.awt.Container.dispatchEventImpl(Container.java:2103)
at java.awt.Component.dispatchEvent(Component.java:4455)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1881)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:759)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1035)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:902)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:724)
at java.awt.Component.dispatchEventImpl(Component.java:4499)
at java.awt.Container.dispatchEventImpl(Container.java:2103)
at java.awt.Window.dispatchEventImpl(Window.java:2517)
at java.awt.Component.dispatchEvent(Component.java:4455)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:649)
at java.awt.EventQueue.access$000(EventQueue.java:96)
at java.awt.EventQueue$1.run(EventQueue.java:608)
at java.awt.EventQueue$1.run(EventQueue.java:606)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
at java.awt.EventQueue$2.run(EventQueue.java:622)
at java.awt.EventQueue$2.run(EventQueue.java:620)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:619)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:194)
at java.awt.Dialog$1.run(Dialog.java:1072)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
at java.awt.EventQueue.access$000(EventQueue.java:96)
at java.awt.EventQueue$1.run(EventQueue.java:608)
at java.awt.EventQueue$1.run(EventQueue.java:606)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:116)
at java.awt.EventQueue$2.run(EventQueue.java:622)
at java.awt.EventQueue$2.run(EventQueue.java:620)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:619)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
REPL started; server listening on localhost port 61281
$ (:use 'seesaw.core)
$ nil
$ (invoke-later nil)
$ java.lang.IllegalArgumentException: Wrong number of args (1) passed to: invoke$invoke-later (NO_SOURCE_FILE:0)
$ (seesaw.invoke/invoke-later nil)
$ nil
Is this stack trace a seesaw issue?
When running the clojure/seesaw project https://github.com/macourtney/Dark-Exchange and pressing a UI button, a RejectedExecutionExcetion is thrown
2011-09-06 19:25:49,038 ERROR [darkexchange.uncaught-exception-handler]: Uncaught Exception: java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1768) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:92) at clojure.core$future_call.invoke(core.clj:5396) at darkexchange.controller.login.create_user$create_user.invoke(create_user.clj:55) at darkexchange.controller.login.create_user$create_user_action.invoke(create_user.clj:60) at seesaw.event$fire.invoke(event.clj:206) at seesaw.event$eval1216$fn$reify__1218.actionPerformed(event.clj:233) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
Need functions to insert, remove, and replace widgets. Must take care of hierarchy validation and repaint. This is very layout dependent, so it should probably be a protocol dispatched on layout type or something.
When you apply update-at! on a table and the backing data has more fields than the columns specified in the table model, the extra data is lost (only the keys specified in the columns are retained). The behavior is unexpected.
user=> (def test-table (table :id :test-table :model [ :columns
[:name :phone :email] :rows [{:name "S" :phone 12345 :email
"[email protected]" :twitter "@s"}]]))
user=> (table/value-at test-table 0)
{:name "S", :phone 12345, :email "[email protected]", :twitter "@s"}
user=> (table/update-at! test-table 0 {:email "[email protected]"})
$a79ba523[,
0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=251658568,maxim umSize=,minimumSize=,preferredSize=,autoCreateColumnsFromModel=true,autoRes izeMode=AUTO_RESIZE_SUBSEQUENT_COLUMNS,cellSelectionEnabled=false,editingCo lumn=-1,editingRow=-1,gridColor=javax.swing.plaf.ColorUIResource[r=255,g=25 5,b=255],preferredViewportSize=java.awt.Dimension[width=450,height=400],row Height=16,rowMargin=1,rowSelectionAllowed=true,selectionBackground=com.appl e.laf.AquaImageFactory
$SystemColorProxy[r=41,g=90,b=209],selectionForeground=com.apple.laf.AquaIm ageFactory
$SystemColorProxy[r=255,g=255,b=255],showHorizontalLines=true,showVerticalL ines=true]>
user=> (table/value-at test-table 0)
{:phone 12345, :name "S", :email "[email protected]"}
The data for :twitter is gone.
The current work around is to grab the backing data for the row, merge changes into it and then use update-at! on the new data rather than do a partial update:
(table/update-at! test-table 0 (merge (table/value-at table 0) {:email "[email protected]"}))
Cheers,
Steve
As I sit here in my chair, approximately 20 minutes after rolling out of bed, the word 'applet' popped into my head. Could be an idea.
I'm getting the following exception when trying to remove the only row in a table using remove-at!:
ERROR [darkexchange.uncaught-exception-handler]: Uncaught Exception:
java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong number of
args (1) passed to: core$conj
at clojure.lang.AFn.run(AFn.java:28)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown
Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: Wrong number of args (1) passed t
o: core$conj
at clojure.lang.AFn.throwArity(AFn.java:437)
at clojure.lang.RestFn.invoke(RestFn.java:412)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invoke(core.clj:542)
at seesaw.table$remove_at.invoke(table.clj:32)
at clojure.lang.Atom.swap(Atom.java:51)
at clojure.core$swap_BANG_.invoke(core.clj:1791)
at seesaw.table$proxy_table_model$fn__1396.invoke(table.clj:49)
at seesaw.table.proxy$javax.swing.table.DefaultTableModel$0.removeRow(Un
known Source)
at seesaw.table$remove_at_BANG_.invoke(table.clj:258)
at darkexchange.controller.main.home.open_trade_panel$trade_delete_liste
ner$fn__6400.invoke(open_trade_panel.clj:82)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.core$apply.invoke(core.clj:540)
at seesaw.invoke$invoke_later_STAR_$fn__431.invoke(invoke.clj:14)
at clojure.lang.AFn.run(AFn.java:24)
... 14 more
The line at open_trade_panel.clj:82 looks like: "(seesaw-table/remove-at! open-trade-table trade-index)))))". Through logging, I know open-trade-table is not null and the correct table, and trade-index is 0. The row I'm trying to remove is the only row in the table.
Compiling my project with lein and Seesaw 1.4.0 and Clojure 1.4.0 I get the following error:
java.lang.ClassNotFoundException: seesaw.core.Showable
I don't get see this error compiling with Seesaw 1.4.0 and Clojure 1.3.0
When trying to mutually bind a slider and a spinner it seems like the default should be to support this:
(bind/bind slider spinner)
(bind/bind spinner slider)
But it seems the spinner isn't automatically bindable, so it requires the use of selection:
(bind/bind
(bind/selection spinner)
slider)
Just a suggestion
I prefer to create a frame and attach all listeners and load data before showing it. The way seesaw is written now, you basically have to show the frame before adding listeners and such. It would be nice if the frame function was split into two functions, one to create the frame and another to show it.
(text)
, to contained widgetI tried this one in a fresh project (Clojure/seesaw 1.3):
lein repl
:
(use 'seesaw.core) ; => nil
(invoke-later nil) ; => ArityException Wrong number of args (1) passed to: invoke$invoke-later clojure.lang.AFn.throwArity (AFn.java:437)
(seesaw.invoke/invoke-later ni) ; => nil
Then:
(def #^{:macro true} foo #'seesaw.invoke/invoke-later) ; => #'test.core/foo
(foo nil) ; => nil
No idea what's wrong, I'm very new to Clojure. But this works:
(use '[seesaw.invoke :only (invoke-later)]) ; => nil
(invoke-later nil) ; => nil
Am I making a mistake?
If you're going to store your data in a default table model, it would be nice to store non-visible data as well.
I'd like to have the ability to write dialogs (i.e. modal windows for custom user input). Is there already something like that in progress? If not, would it be appropriate to add a (dialog ... options ...) fn or should it instead be an option of frame (e.g.: (frame :modal? true ... options ...)?
It would be nice if tables would return the full map passed to it as a row instead of just the part of the map with columns in the table.
For example, let's say I have a table with just a name column, and I give it the row map: { :id 1, :name "blah" }. When I pull that row back out of the table, I will only get the map: { :name "blah" } instead of the original map. This could be a problem if I need the id from the original map to do some calculations.
Currently, you can get the selected items from comboboxes, sliders, radiobuttons and etc. using the selection function. However, the selection function does not support tables. It would be nice if the selection function could return the value at the selected row of a table.
This was kinda unexpected :)
soc.ui=> (vertical-panel :id :test)
#<JPanel javax.swing.JPanel[,0,0,0x0,invalid,layout=javax.swing.BoxLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]>
soc.ui=> (mig-panel :id :test)
IllegalArgumentException Unknown option :id seesaw.util/illegal-argument (util.clj:19)
Now that you are adding swingx support, you could add substance as well.
It seems like, with Clojure 1.3, the parsing of :mnemoric doesn't cast the Long to an Integer, so usage of :mnemonic will cause a ClassCastException.
Say you've got a subclass of a Swing component (like JPasswordField), but you'd like to pass it through a Seesaw constructor function for the superclass. It would be nice to have a way to give an existing widget to a constructor function. Something like:
(with-widget (JPasswordField.)
(text :id :my-password :font "ARIAL-18-BOLD"))
So (text)
would operate on the JPasswordField
instance rather than creating its own JTextField
.
Helper function that creates a cell renderer (for listbox, combobox, etc) that just calls a client-supplied function to get the string to display. Otherwise, you have to create a full renderer, or wrap in a record with toString overridden. Something like:
(seesaw.cells/string-renderer :name)
where :name
is the function in this case. Then you can just drop maps or whatever in the model, e.g. [{:name "Dave" ...} {:name "Bob" ...}]
.
I like Miglayout and therefore demand it be supported.
Alas, I might do this one myself if I get a little time.
Ability to change cursor for a widget, restore it, as well as load custom cursors.
Hello,
I get the mentioned error in seesaw.examples.dialog after clicking the Cancel-Button in the "Show Dialog with custom :success-fn"-dialog (which is labeled "Abbrechen" in german).
The buttons in "Show Dialog with custom option buttons" all work fine. So I guess it's a i18n-thing.
best,
Steffen
There is already support for alerts with alert
, why not go all the way? Not only is it annoying to have to bring in JOptionPane just for showConfirmDialog, but it's insanely bothersome having to type out JOptionPane/showConfirmDialog
.
Edit: This also happens when I just try to do lein compile
followed by running ./lazytest.sh
like your Travis build does.
Pulled down latest from master, tried lein run :examples
and got the following stacktrace. I then tried a lein compile
followed by lein run :examples
and got the same thing. Also got the same thing using Leiningen 1 and Leiningen 2.
Exception in thread "main" java.lang.ClassNotFoundException: seesaw.ExceptionHandler (dev.clj:71)
at clojure.lang.Compiler.analyze(Compiler.java:5205)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$MapExpr.parse(Compiler.java:2498)
at clojure.lang.Compiler.analyze(Compiler.java:5194)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:437)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.access$100(Compiler.java:35)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:4921)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5369)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.analyze(Compiler.java:5151)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:4670)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:4328)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3173)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5367)
at clojure.lang.Compiler.analyze(Compiler.java:5190)
at clojure.lang.Compiler.eval(Compiler.java:5421)
at clojure.lang.Compiler.load(Compiler.java:5857)
at clojure.lang.RT.loadResourceScript(RT.java:340)
at clojure.lang.RT.loadResourceScript(RT.java:331)
at clojure.lang.RT.load(RT.java:409)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4511.invoke(core.clj:4905)
at clojure.core$load.doInvoke(core.clj:4904)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$load_lib.doInvoke(core.clj:4766)
at clojure.lang.RestFn.applyTo(RestFn.java:143)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$load_libs.doInvoke(core.clj:4800)
at clojure.lang.RestFn.applyTo(RestFn.java:138)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$require.doInvoke(core.clj:4869)
at clojure.lang.RestFn.invoke(RestFn.java:422)
at seesaw.test.examples.launcher$eval5$loading__4410__auto____6.invoke(launcher.clj:11)
at seesaw.test.examples.launcher$eval5.invoke(launcher.clj:11)
at clojure.lang.Compiler.eval(Compiler.java:5424)
at clojure.lang.Compiler.eval(Compiler.java:5415)
at clojure.lang.Compiler.load(Compiler.java:5857)
at clojure.lang.RT.loadResourceScript(RT.java:340)
at clojure.lang.RT.loadResourceScript(RT.java:331)
at clojure.lang.RT.load(RT.java:409)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4511.invoke(core.clj:4905)
at clojure.core$load.doInvoke(core.clj:4904)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.core$load_one.invoke(core.clj:4729)
at clojure.core$load_lib.doInvoke(core.clj:4766)
at clojure.lang.RestFn.applyTo(RestFn.java:143)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$load_libs.doInvoke(core.clj:4800)
at clojure.lang.RestFn.applyTo(RestFn.java:138)
at clojure.core$apply.invoke(core.clj:542)
at clojure.core$require.doInvoke(core.clj:4869)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at user$eval1.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:5424)
at clojure.lang.Compiler.eval(Compiler.java:5414)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$eval_opt.invoke(main.clj:235)
at clojure.main$initialize.invoke(main.clj:254)
at clojure.main$null_opt.invoke(main.clj:279)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:422)
at clojure.lang.Var.invoke(Var.java:369)
at clojure.lang.AFn.applyToHelper(AFn.java:165)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
Caused by: java.lang.ClassNotFoundException: seesaw.ExceptionHandler
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:58)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.classForName(RT.java:1566)
at clojure.lang.Compiler.resolveIn(Compiler.java:5658)
at clojure.lang.Compiler.resolve(Compiler.java:5621)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:5584)
at clojure.lang.Compiler.analyze(Compiler.java:5172)
... 70 more
Any thoughts?
Currently you have to do a setTitle
and repaint on the containing widget.
Hello,
Currently there is a need to write fairly big amount of boilerplate code if we want to do many things with many components at once (e.g. establish listeners on them, create bindings, lay them out etc). Namely, we have to write something like
(let [component-id-1 (select form [:#component-id-1])
component-id-2 (select form [:#component-id-2])
...]
...)
when we want to use existing components, and something like
(let [component-id-1 (component-1 :id component-id-1 :text "Text")
component-id-2 (component-2 :id component-id-2 :model [1 2 3])
...]
...)
when we want to create new components.
I haven't found facilities to ease this in the library by default so I had to write them myself.
Here are the macros which target the cases described above.
1.
(defmacro bind-components [form components & body]
`(let [~@(mapcat #(vector % `(seesaw.core/select ~form [~(keyword (str \# %))])) components)]
~@body))
(defmacro with-components [components & body]
`(let [~@(mapcat #(let [[id form] %
[comp & args] form]
[id `(~comp :id ~(keyword id) ~@args)]) (partition 2 components))]
~@body))
bind-components
macro targets the first situation, so these forms are equivalent:
(bind-components form
[comp1 comp2 comp3]
...)
(let [comp1 (select form [:#comp1])
comp2 (select form [:#comp2])
comp3 (select form [:#comp3])]
...)
while with-components
tries to solve second problem, so these forms are equivalent too:
(with-components [comp1 (component-1 :text "abcd")
comp2 (component-2 :model [1 2 3])]
...)
(let [comp1 (component-1 :id :comp1 :text "abcd")
comp2 (component-2 :id :comp2 :model [1 2 3])]
...)
As you can see, these macros work on assumption that components identifiers are the same as the symbols to which all these components are bound. I think it is the most convenient and obvious way to use seesaw - it greatly reduces the need to remember lots of things at once. These macros go even further - you don't have to type the same identifier twice, first as identifier, second as keyword.
I'd be very grateful if something like these macros would be added to the library.
Best regards,
Vladimir.
Seesaw loves reflection at the moment. This will be an ongoing battle, but for performance and good applet support is a worthy goal.
Add type hints to eliminate reflection.
Spurred by issue 10 (#10), need to work out associating Seesaw metadata with wrapped Swing classes. JComponent has client data, Action has keys, but things like JFrame, table models, etc don't. Note that Clojure's metadata can't be applied to Java classes. Where it would be useful now:
Issues to be concerned about:
I would like to see JPasswordField support. I've used JPasswordField in a dialog in my project in the login view file at: https://github.com/macourtney/Dark-Exchange/blob/master/src/darkexchange/view/login/login.clj
I think JPasswordField has most of the fields the JTextField has.
I had trouble setting the :font on a styled-text.
It looks like core.clj:1455
:font (.addAttribute style StyleConstants/FontFamily (seesaw.font/to-font v))
is sending a Font where addAttribute expects a String.
Sorry for reporting such a trivial thing, love the library!
For some reason adding an event listener to a frame does not work for me. When evaluating:
(invoke-now
(listen (frame :title "lala" :content "None")
:window-closed (fn [e] e)))
I get:
java.lang.IllegalArgumentException: No matching method found: getClientProperty for class javax.swing.JFrame
[Thrown class java.lang.RuntimeException]
Restarts:
0: [QUIT] Quit to the SLIME top level
1: [CAUSE1] Invoke debugger on cause No matching method found: getClientProperty for class javax.swing.JFrame [Thrown class java.lang.IllegalArgumentException]
Backtrace:
0: clojure.lang.AFn.run(AFn.java:28)
1: java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:216)
2: java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
3: java.awt.EventQueue.access$000(EventQueue.java:96)
4: java.awt.EventQueue$1.run(EventQueue.java:608)
5: java.awt.EventQueue$1.run(EventQueue.java:606)
6: java.security.AccessController.doPrivileged(Native Method)
7: java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
8: java.awt.EventQueue.dispatchEvent(EventQueue.java:617)
9: java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
--more--
I assume this happens inside get-handlers_, though I have no clue as to why. From what I can figure out, putClientProperty inside install-group-handlers is *not_ being called.
I'm using seesaw from clojars on clojure-1.3-alpha7 and java:
java version "1.6.0_22"
OpenJDK Runtime Environment (IcedTea6 1.10.1) (6b22-1.10.1-0ubuntu1)
OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode)
Any ideas how to fix this?
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.