martin
martin

Reputation: 676

Translate simple Ltk-app into Clojure seesaw / swing

I am trying to decide between Clojure and CL for an upcoming project. To get my feet wet, I was toying around with some simple GUI stuff.

Here is what I have in CL / Ltk:

(ql:quickload "ltk")

(defpackage :myed
  (:use :ltk :cl))
(in-package :myed)

(defun ed-label (fr)
  (make-instance 'label :master fr :font "Sans-Serif" :text "Editor"))

(defparameter *text-field*
  (make-instance 'text
         :font "monospaced" :takefocus :t))

(defparameter *a-tale*
  "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light")

(defun make-frame ()
  (with-ltk ()
    (let* ((f (make-instance 'frame))
       (scroll (make-instance 'scrolled-text :master f))
       (outtext (textbox scroll)))
      (pack f)
      (configure outtext :font "monospaced" :background "#aea79f" :wrap :word)
      (pack (ed-label f) :anchor :nw :side :top)
      (pack scroll :anchor :nw :expand t :fill :both)
      (pack *text-field* :anchor :sw :fill :x :ipady 10)
      (setf (text outtext) *a-tale*)
      (bind *text-field* "<KeyPress-Return>"
        (lambda (event) (format-output outtext)))
      (configure f :borderwidth 2))))

(defun format-output (target)
  "Print inputstring with newlines and > ."
  (append-text target (format nil "~%~%> ~A~%~%" (text *text-field*)))
  (clear-text *text-field*))

Two TextFields, when I input Text in the bottom window and hit Enter, newlines and a ">" get added and the text is appended in the top textfield.

In Clojure I've tried Seesaw and this:

(ns myedclj.core
  (:use [seesaw core keymap])
  (:require [seesaw.bind :as bind]))

(def outtext
    ( text
    :multi-line? true :wrap-lines? true  :editable? false))

(def ed-label (label :text "Editor"))

(def intext
  (text :multi-line? false :editable? true))

(def a-tale
  "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light")

(defn format-output
  [target]
  (.append target (str "\n\n" "> " (text intext))))

(map-key intext "ENTER" (fn [_] (format-output outtext)))

(text! outtext a-tale)

(defn make-frame []
  (frame :content (vertical-panel
                   :border 2
                   :items [ed-label
                           (scrollable outtext)
                           intext])))

(defn -main [& args]
  (-> (make-frame)
      pack!
      show!))

This is unfortunately not working. The dimensions of the windowcontents are the opposite of what I want and I don't see any scrollbars. My Swing knowledge is btw non-existent.

Any Help would be greatly appreciated.

Upvotes: 2

Views: 523

Answers (1)

Michał Marczyk
Michał Marczyk

Reputation: 84341

(Updated with a closer workalike of the CL version. See revision history for a version with a 90/10 split with a draggable divider.)

The scrollbar will appear as soon as the text no longer fits in the output text area.

The sizes could also be configured with (config! in-text :size [400 :by 20]), and similarly for out-scrollable.

(ns myedclj.core
  (:require [seesaw.core :refer :all]
            [seesaw.keymap :refer :all]
            [seesaw.bind :as bind]))

(def in-text
  (text :editable? true :multi-line? false
        :size [400 :by 20]))

(def out-text
  (text :editable? false :multi-line? true :wrap-lines? true))

(def out-scrollable
  (scrollable out-text
              :size [400 :by 180]))

(def a-tale
  "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light")

(defn format-output! [source target]
  (value! target (str (value target) "\n\n> " (value source)))
  (value! source ""))

(defn attach-listeners! []
  (map-key in-text "ENTER"
           (fn [_] (format-output! in-text out-text))
           :scope :self))

(defn make-frame []
  (frame
   :title    "Seesaw example"
   :content  (vertical-panel
              :border 2
              :items  [out-scrollable
                       in-text])
   :on-close :exit))

(defn -main [& args]
  (native!)
  (value! out-text a-tale)
  (attach-listeners!)
  (let [f (make-frame)]
    (pack! f)
    (show! f)))

Upvotes: 3

Related Questions