EzDevInfo.com

seesaw

Seesaw turns the Horror of Swing into a friendly, well-documented, Clojure library seesaw-clj - Google Groups

How can I update a seesaw tree model?

I've been using seesaw.tree/simple-tree-model to create my TreeModels, the docs say that this is read only. Originally I didn't need to edit the tree structure however now I do!

There is a pull request in seesaw for adding update-tree!. Though this is 8 months old.

What is the best way to create and edit JTrees with seesaw / clojure?


Source: (StackOverflow)

Clojure - Autoupdating Listbox

here's what i'd like to do:

I've got a ref that represents a list of items. I'd like to have a listbox (seesaw?) that displays this lists contents, updating automatically (whenever i change the ref).


Source: (StackOverflow)

Advertisements

Should I use Java for a custom Swing component designed for a clojure app?

I want a simple timeline component (like in video editing software) for a clojure/seesaw app and I am wondering if it is a good approach to implement this directly with clojure and seesaw or if I should write it in java and make my clojure wrapper around it.

Or more generally: is a functional programming language optimal for writing UI widgets? I cannot imagine doing that without a lot of state involved. And wasn't OO invented for UI-development in the first place?


Source: (StackOverflow)

How to install a dependency in a Clojure project

This is a noob question, so I'm sorry if I offend somebody.

But how do I install seesaw on a *nix computer? Yes, I've read the README.MD file, but how does the project.clj know where to find the library jars (for seesaw for example)?


Source: (StackOverflow)

Is it possible to have a bulleted list with an event handler?

I'm using seesaw to program an interface in Swing.

I want to display a bulleted list of items. When an item is clicked I want an event handler to be called.

I have managed to get event handlers working for components/widgets, and I can display a bulleted list easily by inserting HTML into a Label. I figure that if nothing else is possible I may need to capture mouse click events for the parent and work out offsets.

What's the best way to have a clickable bulleted list with event handlers?


Source: (StackOverflow)

How to set an image for the panel background with seesaw?

I want to set a custom image for the panel background in my clojure app. Using seesaw I can set some color for the background:

(defn make-panel []
      (border-panel
        :north (flow-panel :align :center
                           :items [(label :text "TEXT")])
        :center (canvas :class :board
                        :background :black)
        :border 5))

but how to choose an image using its url?


Source: (StackOverflow)

Clojure Seesaw make menu of radio-menu items out of a list of files

I have a list of files like so ("File1" "File2" "File3")

I want to turn this into a of radio-menu-items like this

 (menu :text "Lists" :items [(radio-menu-item :text "File 1")(radio-menu-item :text "File 2")(radio-menu-item :text "File 3")])

I have tried looping like this

(def Radios (for [ item '("File1" "File2" "File3")]  (radio-menu-item  :text item)))

but this does not work.

How can this be accomplished?


Source: (StackOverflow)

wrong number of arguements clojure

I'm building a program that's meant to allow users count either the number of letters or number of words in a string, however when running the program through the cmd, I'm getting a clojure.lang.ArityException, wrong number of args (1) passed to : core/-main/counter--5333

My code is

;;Create a GUI which allows user to input a string and to select "word count" or "letter count". When "Start" is clicked pass both the string and either (wordCount [string x]) or (letterCount [string x]) to 
;;declare functions as variables
;;show function that takes functions as parameters
;;show function that returns another function
(ns firstclass.core
  (:gen-class)
  (:use seesaw.core))

(defn -main
  [& args]

(def strInput (input "Please enter a string to be evaluated"))

(def groups (button-group))
(def s (selection groups))

(def letterRadio (radio :text "Letter" :group groups))
(def wordRadio (radio :text "Word" :group groups))

(defn letterCount
  [string]
  (loop [characters string
         a-count 0]
    (if (= (first characters) \a)
      (recur (rest characters) (inc a-count))
      a-count)))

(defn wordCount
  [string]
  (loop [characters string
         a-count 0]
    (if (= (first characters) \a)
      (recur (rest characters) (inc a-count))
      a-count)))

(def counter (fn [fn x, string strInput] (x [strInput])))

(defn handler [event]
    (if-let [s letterRadio]
        (counter [letterCount, strInput]))
    (if-let [s wordRadio]
        (counter [wordCount, strInput])))

(def start (button :text "Start Count" :listen [:action handler] ))

(def panel
  (flow-panel :items [strInput, letterRadio, wordRadio, start]))

(invoke-later
  (-> (frame :content panel :on-close :dispose) 
      pack! show!)))

Source: (StackOverflow)

How to create a MigLayout for a simple minesweeper game?

I am working on a simple clojure minesweeper game, mainly to exercise the language a bit. The "core game engine" is ready and now I'd like to add a simple UI. I had a look into seesaw and so far it worked quite nicely.

The only thing I am struggling with is the mig layout which I'd like to use. My idea is to have kind of the following layout:

 _______________________
[_________NORTH_________]
[   ][             ][   ]
[ W ][    FIXED    ][ E ]
[ E ][    SIZE     ][ A ]
[ S ][    BOARD    ][ S ]
[ T ][             ][ T ]
[___][_____________][___]
[_________SOUTH_________]

The north, west, east and south should grow in case the window is resized. The main panel should have a fixed size with all the buttons that represent the game board.

Before I read about mig layout I considered using a border-panel containing a grid-panel but as mentioned on the seesaw github page:

Seesaw has rudimentary support for GridBagLayout in the seesaw.core/form-panel function. I don't recommend using this because it's half-baked and not as powerful as using MigLayout (seesaw.mig) or JGoodies (seesaw.forms).

I'd like to give MigLayout a try. My first try:

(defn make-border-panel 
[]
(mig-panel 
 :constraints ["fill" "[grow][][grow]" "[grow][][grow]"]
 :items [ 
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["X"                  "shrink 0"  ]
       ["Minesweeper North"  "dock north"]
       ["W"                  "dock west" ]
       ["E"                  "dock east" ]
       ["Minesweeper South"  "dock south"]
      ]))

UPDATE 1

I'll ignore north, south, west, east for the moment and did the following to get at least the center board:

(defn make-button [x y]
   (button :id (format "cell_%d_%d" x y)
           :icon (clojure.java.io/resource "minesweeper/icons/button.png")))


(defn make-board
  [w h]
  (mig-panel 
      :constraints [(str "wrap" w) "[]" "[]" ]
      :items (for [x (range w) y (range h)]  
          (vector (make-button x y) "w 24px!, h 24px!"))))

Source: (StackOverflow)

Error on return of Clojure action in seesaw

this program opens a file read it into a list then asks the user to enter the word from the list one at a time but I get an error right after it speaks

(ns EKS.Core)
(use '[speech-synthesis.say :as say])
(use '[clojure.java.shell :only [sh]])
(use 'seesaw.core)
(use 'seesaw.dev)
(use 'seesaw.chooser)
(use 'clojure.java.io)
(import 'java.io.File)
(native!)
(defn festival [x](sh "sh" "-c" (str "echo " x " | festival --tts")))
(defn espeak [x] (sh "espeak" x))
(defn mac-say[x] (sh "say" x))
(defn check-if-installed[x] (:exit(sh "sh" "-c" (str "command -v " x " >/dev/null 2>&1 || { echo >&2 \"\"; exit 1; }"))))


(defn env
  "Returns the system property for user.<key>"
  [key]
  (System/getProperty (str "user." key)))

(defn get-lines [fname]
  (with-open [r (reader fname)]
    (doall (line-seq r))))

(defn engine-check[]
(def engines (conj["Google" ]
(if (= (check-if-installed "festival") 0)  "Festival" )
(if (= (check-if-installed "espeak") 0) "ESpeak"   )
(if (= (check-if-installed "say") 0)  "Say"  )))(remove nil? engines))
(engine-check)

(def ListDir  (str (env "home") ))
(def speak say)

(defn setup-list[ file](
 (def ListEntry (remove #{""}  (get-lines (.getAbsolutePath file))))
 (speak (str "Enter the word " (first ListEntry)))
 (.getAbsolutePath file)
 (def current 0)))


(def Open-Action (action :handler (fn [e] (choose-file :type :open :selection-mode :files-only :dir ListDir :success-fn (fn [fc file](setup-list file))))
:name "Open"
:key "menu O"
:tip "Open  list"))


(def entry-text(text :id :entry :text "" ))

(defn check-word[] ((if (= (text entry-text) (nth ListEntry current))(speak "correct")(speak "incorrect"))(def current (+ current 1))(speak (str "Enter the word " (nth ListEntry current)))))

(def Main-Panel(grid-panel :vgap 7 :hgap 20 :border "Main" :items[ (top-bottom-split  entry-text
        (left-right-split (grid-panel :vgap 7 :items[(label :text "Correct: 0") (label :text "Incorrect: 0")]) (grid-panel :vgap 7 :items[(button :text "Next"
            :mnemonic \N
            :listen [:action (fn [e] (check-word))]) 
           (button :text "Repeat!"
            :mnemonic \\
            :listen [:action (fn[e] (speak(nth ListEntry current)))])
                                           ])   :divider-location 1/3 )
          :divider-location 1/3 )]))

(def Main-Window(frame :title "??????", :on-close :exit, :size[425 :by 172]:menubar(menubar :items[(menu :text "File" :items [Open-Action ])]) :content Main-Panel ))

(show! Main-Window)

this is the error message I get when opening a file

 Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
    at clojure.lang.Var.fn(Var.java:378)
    at clojure.lang.Var.invoke(Var.java:409)
    at EKS.Core$setup_list.invoke(NO_SOURCE_FILE:38)
    at EKS.Core$fn__5794$fn__5795.invoke(NO_SOURCE_FILE:42)
    at seesaw.chooser$choose_file.doInvoke(chooser.clj:173)
    at clojure.lang.RestFn.invoke(RestFn.java:619)
    at EKS.Core$fn__5794.invoke(NO_SOURCE_FILE:42)
    at seesaw.action$action$fn__1218.invoke(action.clj:90)
    at seesaw.action.proxy$javax.swing.AbstractAction$0.actionPerformed(Unknown Source)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:713)
    at java.awt.EventQueue.access$000(EventQueue.java:104)
    at java.awt.EventQueue$3.run(EventQueue.java:672)
    at java.awt.EventQueue$3.run(EventQueue.java:670)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:686)
    at java.awt.EventQueue$4.run(EventQueue.java:684)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:683)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

this is the test file I am using

this
here
word

Source: (StackOverflow)

How do I quit application written in Clojure Seesaw?

I am aware of

(frame
     :title "Example"
     :on-close :exit)

but what I am supposed to do if I want to do some custom action after selecting Quit in the menu?

(fn [e] (System/exit 0) )

didn't work.

Edit 1

Oops, (fn [e] (System/exit 0) ) works, provided you do

:listen [:action ...

instead of :listen [:mouse-clicked..

Sorry for not noticing that before.


Source: (StackOverflow)

How do I set an image's resolution?

I am using Seesaw to interact with Swing.

I have some icons defined thus:

(def label :icon 
           (clojure.java.io/resource "some_image.png"))

I want to render "some_image.png" in a different resolution. If I simply set the bounds, I'll only get part of the image.

How do I achieve this?


Source: (StackOverflow)

Listbox (JList) Won't update dynamically from custom ListModel

I'm working on a GUI app in Clojure using Seesaw and am having trouble getting a listbox (JList in Java) to update when my custom ListModel gets updated.

Here's some of my code:

(deftype ActionHistoryListModel
  [^{:unsynchronized-mutable true} listeners
   ^{:unsynchronized-mutable true} listening-to]

  ListModel
  (addListDataListener [this listener]
    (set! listeners (conj listeners listener)))
  (removeListDataListener [this listener]
    (set! listeners (remove #(= % listener) listeners)))
  (getSize [this] 
    (get-in (deref listening-to) [:count]))
  (getElementAt [this index]
    (get-in (deref listening-to) [:actions index]))

  ActionHistoryListModelProtocol
  (listen-to [this r]
    (do
      (set! listening-to r)
      (add-watch r this (fn [_ _ _ new-state] (.notify this new-state)))))
  (notify [this new-state]
    (let [action ((meta new-state) :last-action)
          const  (cond
            (= action :create) INTERVAL_ADDED
            (= action :update) CONTENTS_CHANGED)
          index  (last ((meta new-state) :action-target))
          event  (ListDataEvent. this const index index)
          notification (cond
            (= action :create) #(.intervalAdded % event)
            (= action :update) #(.contentsChanged % event))
          ]
      (. (.. System out) print (str "Index: " index "\n" "Event: " event "\n"))
      (map #(invoke-later (notification %)) listeners)))
  )

(defn make-action-history-list-model []
  (ActionHistoryListModel. #{} nil))

(def ahlm (make-action-history-list-model))
(.listen-to ahlm action-history)

(def undo-list (listbox :model ahlm))

; then put list in frame...

where action-history is a ref.

It goes to the point where the list should be updated because the System.out.print is happening, but the listbox doesn't want to update

Any ideas on what might be going wrong? Is it something with the mix of using the EDT and watch callback?

Let me know if more code is needed.


Source: (StackOverflow)

Cannot access or update atom from within a seesaw listener function

I have a seesaw ui with a text editor. The editor content is backed by a record called 'Task' which is contained somewhere in an atom called 'state'. A key-released event on the editor should change the property :desc of the Task. I use the following code:

(def state
     (atom {:tasks []
            :interval nil
            :style (style :foreground :black :background nil)}))

(defn on-text-edited [ui listener-fn]
  (let [editor (select ui [:#editor])]  
    (listen editor :key-released
        (fn [evt] (listener-fn (text editor))))))

(defn update-task! [task text]
  (let [newtask (assoc task :desc text)
        tasks (replace {task newtask} (:tasks @state))]
  (swap! state
     #(assoc % :tasks tasks))))

(def text-updates (on-text-edited frame #(update-task! selected-task %)))

selected-task is an atom referencing the current content model of the editor. Whenever the user edits text the update-task! function is supposed to be called. But nothing happens. The function seems not to be called at all. When I call it from the repl it behaves as expected.

I tested if the function would get called by letting it do a simple println:

(defn update-task! [task text]
   (println (str task " " text)))

Now the function works fine when I edit text in the editor. Then I changed it to:

(defn update-task! [task text]
  (let [newtask (assoc task :desc text)
        tasks (replace {task newtask} (:tasks @state))]
     (println (str task " " text))))

now again, it would do nothing at all. So it seems that somehow the accessing of the atoms get in the way of the event handling. Is there maybe a conflict between the ui thread and the thread the atoms were defined in?


Source: (StackOverflow)

Clojure GUI for cropping images

I'm making a GUI for selecting regions to crop from images. I have been using Seesaw and cans select rectangular regions, but cannot find a way to set an image to the background of seesaw.canvas. This suggests using icons on labels. Can I make a label paintable and then use it as a canvas? Is there a way to overlap a label and a canvas or somehow use a panel that gives a background to its contents?

I think Quil has this functionality, but I'm not sure how to build a GUI around its draw, setup, sketch form if I want add widgets.

Existing solutions would appreciated as well, as long as I can decompose them. Using GIMP or Photoshop isn't an option for the workflow I want: multiple crops per photo, of different kinds on each page and different metadata added depending on the type of image outlined. Any suggestions for libraries for working with metadata for photos? I was planning on using a shell interface to exiftool, but a more portable option may be better.


Source: (StackOverflow)