Enabling/disabling menu items

22 views
Skip to first unread message

James Platt

unread,
Jun 11, 2019, 4:45:16 PM6/11/19
to Racket list
It looks like there is not way to enable and disable (grey out) menu items the way that there is with buttons. So my question is whether the expectation is that you add and remove items from a menu instead or is this a reasonable feature request for a new version of Racket?

To illustrate what I mean with buttons, I have taken the code recently posted on this list by Matthias for the 7 GUIs task 5 (CRUD) and modified it so that the buttons enable and disable depending on whether something is selected or not. After something is selected, you can click inside the list-box but not on any item to deselect and disable the buttons. I want this kind of behavior but for menu items as well as buttons.

#! /usr/bin/env gracket
#lang at-exp racket/gui

;; a create-read-update-deleted MVC implementation

;; ---------------------------------------------------------------------------------------------------
(define *data '("Emil, Hans" "Mustermann, Max" "Tisch, Roman"))
(define *selector "")
(define *selected *data) ;; selected = (filter select data)

(define (selector! nu) (set! *selector nu) (data->selected!))
(define (select s) (string-prefix? s *selector))
(define (data->selected!) (set! *selected (if (string=? "" *selector) *data (filter select *data))))

(define-syntax-rule (def-! (name x ...) exp) (define (name x ...) (set! *data exp) (data->selected!)))
(def-! (create-entry new-entry) (append *data (list new-entry)))
(def-! (update-entry new-entry i) (operate-on i (curry cons new-entry) *data select *selected))
(def-! (delete-from i) (operate-on i values))

#; {N [[Listof X] -> [Listof X]] [Listof X] [X -> Boolean] [Listof X] -> [Listof X]}
;; traverse list to the i-th position of selected in data, then apply operator to rest (efficiency)
;; ASSUME selected = (filter selector data)
;; ASSUME i <= (length selected)
(define (operate-on i operator (data *data) (select select) (selected *selected))
(let sync ((i i) (data data) (selected selected))
(if (select (first data))
(if (zero? i)
(operator (rest data))
(cons (first data) (sync (sub1 i) (rest data) (rest selected))))
(cons (first data) (sync i (rest data) selected)))))

;; ---------------------------------------------------------------------------------------------------
(define-syntax-rule (def-cb (name x) exp ...) (define (name x _y) exp ... (send lbox set *selected)))
(def-cb (prefix-cb field) (selector! (if (string? field) field (send field get-value))))
(def-cb (Create-cb _b) (create-entry (retrieve-name)))
(def-cb (Update-cb _b) (common-cb (curry update-entry (retrieve-name))))
(def-cb (Delete-cb _b) (common-cb delete-from))

(define (common-cb f) (define i (send lbox get-selection)) (when i (f i)))
(define (retrieve-name) (string-append (send surname get-value) ", " (send name get-value)))
(define (lbox-click-action lstbox ctlevent)
(cond [(null? (send lstbox get-selections))
(send update-button enable #f)
(send delete-button enable #f)]
[else (send update-button enable #t)
(send delete-button enable #t)])
)
;; ---------------------------------------------------------------------------------------------------
(define frame (new frame% [label "CRUD"]))
(define hpane1 (new horizontal-pane% [parent frame][border 10][alignment '(left bottom)]))
(define vpane1 (new vertical-pane% [parent hpane1]))
(new text-field% [parent vpane1][label "Filter prefix: "][init-value ""][callback prefix-cb])
(define lbox (new list-box% [parent vpane1][label #f][choices '()][min-width 100][min-height 100] [callback lbox-click-action]))
(define vpane2 (new vertical-pane% [parent hpane1][alignment '(right center)]))
(define name (new text-field% [parent vpane2][label "Name: "][init-value ""][min-width 200]))
(define surname (new text-field% [parent vpane2][label "Surname: "][init-value ""][min-width 200]))
(define hpane2 (new horizontal-pane% [parent frame]))
(define create-button (new button% [label "Create"][parent hpane2][callback Create-cb]))
(define update-button (new button% [label "Update"][parent hpane2][callback Update-cb][enabled #f]))
(define delete-button (new button% [label "Delete"][parent hpane2][callback Delete-cb][enabled #f]))

(prefix-cb "" '***)
(send frame show #t)

Matthew Flatt

unread,
Jun 11, 2019, 4:54:53 PM6/11/19
to James Platt, Racket list
At Tue, 11 Jun 2019 16:45:05 -0400, James Platt wrote:
> It looks like there is not way to enable and disable (grey out) menu
> items the way that there is with buttons.

There's no `enable` initialization argument for `menu-item%`, but
there's an `enable` method the same as for `button%` instances. If
would be nice to have an `enable` initialization argument to create an
initially disabled menu item, but you can send `enable` just after
creating the menu item.

Is that what you were looking for, or do you have something else in
mind?

James Platt

unread,
Jun 11, 2019, 5:21:30 PM6/11/19
to Racket list
Thanks. I think this will work for me but, yes, it would be nice to have the initialization argument. That was what threw me off into thinking that it wasn't available.

James
Reply all
Reply to author
Forward
0 new messages