Text not centering on message% in Racket - scheme

I have following simple GUI code:
#lang racket/gui
(define myfr (new frame% [label ""] [width 200] [height 100]))
(define mymsg (new message% [label "See text position here."][parent myfr]))
(define mytf (new text-field% [label "Enter some text here."][parent myfr]))
(define bt (new button% [parent myfr] [label "Reset text"]
[callback (lambda (b e)
(send mymsg set-label
(send mytf get-value)))]))
(send myfr show #t)
Initially, the text position on message% is well centralized. However, when I change the text, it is no more well-centered. Why is this happening and how can this be corrected so that the new text is also well centered?

Add [auto-resize #t] to your message:
(define mymsg (new message% [label "See text position here."] [parent myfr] [auto-resize #t]))

Related

How to avoid circular definition in racket language

I tried to write simple gui to modify it’s text then copy it's content to text2.
But the call function can't be defined because its owner (text) is not defined yet.
This is the warning :
"cannot reference an identifier before its definition"
Is there anyway I could either:
assign callback later?
avoid circular reference?
Below is the code :
#lang racket/gui
(define toplevel (new frame% [label "MD View"] [width 800] [height 300]))
(define canvas (new editor-canvas% [parent toplevel] [style '(no-hscroll)]))
(define canvas2 (new editor-canvas% [parent toplevel] [style '(no-hscroll)]))
(define text2 (new text%))
(define text (new text%
[callback (send text2 insert (send text get-text)) ]
)) ;; warning here
(send canvas set-editor text)
(send canvas2 set-editor text2)
(send text auto-wrap #t)
(send text set-padding 10 10 10 10)
(send text2 auto-wrap #t)
(send text2 set-padding 10 10 10 10)
(new button% [parent toplevel]
[label "write"]
; Callback procedure for a button click:
[callback (lambda (button event)
(send text2 insert "written"))])
(new button% [parent toplevel]
[label "copy"]
; Callback procedure for a button click:
[callback (lambda (button event)
(send text2 insert (send text get-text)))])
(send toplevel show #t)

Racket GUI Toolkit: How to embed a link

Say we have a frame
(define my-frame (new frame% [parent #f] [label "test"]))
and a message, that should link to google.
(new message%
[parent my-frame]
[label "https://www.google.com"])
(send my-frame show #t)
The above does not work. How does one embed a link in the Racket GUI toolkit?
You can use the button, but I guess that isn't link-like so you don't want it, the following code shows how to use editor clickback to create a link-like text.
(require net/sendurl)
(define f (new frame% [parent #f]
[label "test"]
[width 300]
[height 300]))
(define editor (new text%))
(new editor-canvas% [parent f]
[editor editor])
(define t "https://www.google.com")
(send editor insert t)
(send editor set-clickback 0 (string-length t)
(λ (text start end)
(send-url t)))
(send* f
[show #t]
[center])

Non-resizable frame in Racket

I am trying to create a non-resizable frame to give a message:
#lang racket/gui
(define (non_resizable_frame)
(define myframe (new frame%
[label "MyFrame"]
[style (list 'no-resize-border)] ; does not work.
))
(new message% [parent myframe][label "This is just for testing."])
(new message% [parent myframe][label "I am trying to create a non-resizable frame."])
(send myframe show #t))
(non_resizable_frame)
However, the frame still is resizable. Where is the problem and how can I solve this?
Set the stretchable-width and stretchable-height init arguments to #f when constructing the frame.

Racket GUI tab-panel dynamic content

I am looking into GUI development with Racket. I would like to create a tab-panel%, with multiple tabs. The documentation says, that a switch of tab does only call a procedure and does not make a content change happen automatically. I think this is quite clever behavior, but I have a problem implementing an initially empty tab-panel, which only gets content (children) when I select one of the tabs.
This is the code I already have:
#lang racket/gui
(require racket/gui/base)
(define nil '())
(define application-frame
(new frame%
[label "Example"]
[width 400]
[height 300]))
(define menu-bar
(new menu-bar%
[parent application-frame]))
(define file-menu
(new menu%
[label "&File"]
[parent menu-bar]))
(new menu%
[label "&Edit"]
[parent menu-bar])
(new menu%
[label "&Help"]
[parent menu-bar])
(new menu-item%
[label "E&xit"]
[parent file-menu]
[callback
(λ (m event)
(exit nil))])
(define tab-panel
(new tab-panel%
[parent application-frame]
[choices '("&Lookup" "&Training")]
[callback
(λ (tp event)
(case (send tp get-item-label (send tp get-selection))
[("&Lookup")
(send tp change-children
(λ (children)
(list lookup-panel)))]
[("&Training")
(send tp change-children
(λ (children)
(list training-panel)))]))]))
(define get-lookup-panel
(lambda (children)
(let
[(lookup-panel (new panel% [parent tab-panel]))]
[(new message%
[parent lookup-panel]
[label "The content of the lookup panel for the lookup tab."])
lookup-panel])))
(define lookup-panel (new panel% [parent tab-panel]))
(define lookup-panel-content
(new message%
[parent lookup-panel]
[label "The content of the lookup panel for the lookup tab."]))
(define training-panel (new panel% [parent tab-panel]))
(define training-panel-content
(new message%
[parent training-panel]
[label "The content of the training panel for the training tab."]))
(define status-message
(new message%
[parent application-frame]
[label "No events so far..."]
[auto-resize #t]))
(send application-frame show #t)
The problem here is, that initially both children of the tab-panel are visible, although (naturally) only one tab is selected. When I change tab, the behavior is corrected by the lambdas inside the case form.
However, I cannot simply give those panels, which I set as children no parent, because racket will tell me, that I need to specify the required initial argument parent. This means they will be initially added to the tab-panel. Is it necessary to create the panels and then again remove them from the tab-panel? That would seem a bit dirty. I think there is probably a better way.
I already tried to dynamically create the panel, as can be seen in the get-lookup-panel procedure, but I couldn't get that to work in the case form.
What is the correct way to implement it?
edit1
I found a way to define a procedure, which can be used in the way I want to use it:
(define (get-lookup-panel4 children)
(define lookup-panel (new panel% [parent tab-panel]))
(define lookup-panel-message (new message% [parent lookup-panel] [label "LOOKUP"]))
(list lookup-panel))
Which can be used as follows:
(define tab-panel
(new tab-panel%
[parent application-frame]
[choices '("&Lookup" "&Training")]
[callback
(λ (tp event)
(case (send tp get-item-label (send tp get-selection))
[("&Lookup")
(send tp change-children get-lookup-panel4)]
[("&Training")
(send tp change-children
(λ (children)
(list training-panel)))]))]))
But I don't understand what the difference between this procedure and the other one with the let expression is and another problem with this approach is, that I cannot afterwards modify the created panel or message, because their scope is the procedure.

Why text in text% not getting deleted?

I want to delete existing text from a text-area and insert new text but it is not working. I have following code:
#lang racket/gui
(define myframe (new frame%
[label "testing"]
[width 600]
[height 400]))
(define mytextarea (new text% ))
(new editor-canvas%
[parent myframe]
[editor mytextarea])
(define (button_fn button event)
(begin
(send mytextarea delete ; does not work;
(send mytextarea get-start-position)
(send mytextarea get-end-position))
(send mytextarea insert "New string inserted" 0) ; works;
))
(define mybutton (new button% [parent myframe]
[label "delete"]
[callback button_fn ]))
(send myframe show #t)
There is no error message. Where is the problem and how can it be solved?
The get-start-position and get-end-position return the start and end of the current selection; if there's no selection, then they both return the position of the cursor.
If you want to delete the whole contents of the text area, use last-position:
(send mytextarea delete 0 (send mytextarea last-position))
or you could use the erase method:
(send mytextarea erase) ;; deletes everything

Resources