
I am working through creation of a GUI app and am stuck on a something hopefully simple. My goal is to display text (around 15 lines) that the user can copy, but not edit. A message%
is non-editable, but also appears to be non-copyable. A text%
, such as below, is copyable, but user-editable. Is their either (a) a third option or (b) a way to make a text%
non-editable, while keeping its copyability? Thank you very much.
#lang racket/gui
(define f (new frame% [label "Simple Edit"]
[width 200]
[height 200]))
(define c (new editor-canvas% [parent f]))
(define t (new text%))
(send c set-editor t)
(send t insert "Money, get away\n")
(send t insert "Get a good job with more pay and you're okay\n")
(send f show #t)

Quick question- why do some packages have a separate package for documentation? (Also separate -lib & -tests packages in some cases)

@spdegabrielle to avoid test and doc build dependencies. I’d recommend against doing it though

@ghoetker (send t lock #t)
can lock edit operations. However, I can’t find how to make text%
copy-able

frame:text%
seems to have implemented everything, but it is a frame.. #lang racket/gui
(require framework)
(define f (new frame:text%
[width 200]
[height 200]))
(define c (send f get-editor))
(send c insert "Money, get away\n")
(send c insert "Get a good job with more pay and you're okay\n")
(send c lock #t)
(send f show #t)

@shu—hung Thank you very much. I had not found lock
. A bit of experimenting showed me how to combine it with the ability to copy. Adding a menu with editor operations menu items (see below), provides the ability to copy a locked editor%
with either the menu or Cmd-C (or Ctrl-C, depending on your platform.
In investigating lock
, I came up with a related question. Section 5.9, Internal Editor Locks, of The Racket Graphical Interface Toolkit discusses three levels of internal locking, locked-for-write?
, locked-for-flow?
and locked-for-read?
. I see how I can check is an editor is locked-for-write, etc. But, I’m not clear: are these states are something that I can set? If not, what determines the internal locking state of an editor?
#lang racket/gui
(define f (new frame% [label "Simple Edit"]
[width 200]
[height 200]))
(define c (new editor-canvas% [parent f]))
(define t (new text%))
(send c set-editor t)
(send t insert "Money, it's a gas\n")
(send t insert "Grab that cash with both hands and make a stash")
(send t lock #t)
(send f show #t)
(define mb (new menu-bar% [parent f]))
(define m-edit (new menu% [label "Edit"] [parent mb]))
(append-editor-operation-menu-items m-edit #f)

@ghoetker I’m new to Racket GUI too. The doc of lock
says > This method does not affect internal locks, as discussed in Internal Editor Locks. so I guess they are not related (maybe)?

I am very much not a GUI expert, but I develop an internal tool used by some of collaborators for which I wanted this feature. I also used lock
in my initial implementation, but there were problems with that. (Unfortunately I don’t remember what they were.) The approach I found is to define a subclass of text%
that augments the can-delete?
and can-insert?
methods. The overview in the docs (http://docs.racket-lang.org/gui/editor-overview.html\|docs.racket-lang.org/gui/editor-overview.html) talks a bit about this in the context of implementing an append-only editor.

@ghoetker Here a class that I use for this. It takes a string or list of strings for its content
arg, inserts that during initialization, then forbids any insertion/deletion. I’m not sure everything I’ve done here is ideal, but it works. #lang racket/gui
(define t%
(class text%
(init [content '()]
[auto-wrap #t])
(super-new [auto-wrap auto-wrap])
(inherit insert
begin-edit-sequence
end-edit-sequence)
(define initializing? #t)
(begin-edit-sequence)
(if (string? content)
(insert content)
(for ([str (in-list content)])
(insert str)))
(end-edit-sequence)
(scroll-editor-to-top this)
(set! initializing? #f)
(define/augment (can-delete? start len)
#f)
(define/augment (can-insert? start len)
initializing?)
#\|END t%\|#))
(define (scroll-editor-to-top ed)
(let loop ([wait 1])
(cond
[(send ed locked-for-flow?)
(unless (> wait 5)
(sleep wait)
(loop (add1 wait)))]
[else
(send ed scroll-to-position 0)])))

@philip.mcgrath Thank you. That code actually helps me with several issues I was facing. Much appreciated.