#lang scribble/manual @(require racket/base scribble/core (for-label racket/base racket/string net/url json "../private/menu.rkt")) @title{menu} @author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]] @defmodule[menu] Menu data structures used by the webview library. This module provides constructors, predicates, traversal helpers, mutation operations, and JSON conversion for menu trees. @section{Overview} A menu is represented as a tree. A menu consists of menu items, and a menu item may optionally contain a submenu. Menu identifiers are symbols. Menu item titles are strings. Icons are stored as strings and may be supplied either as @racket[#f], strings, or URL values. The module does not display menus itself. It provides the menu data structure used by higher layers. @section{Internal Representation} Internally, menus are represented by transparent structure values. These structure constructors and predicates are not exported directly. The public API uses constructor procedures and helper functions operating on those internal values. @section{Predicates} @defproc[(is-wv-menu? [mnu any/c]) boolean?]{ Returns @racket[#t] if @racket[mnu] is a valid menu tree and @racket[#f] otherwise. A value is recognized as a menu if it is an internal menu structure whose item list is a list of internal menu items, and every submenu recursively also satisfies @racket[is-wv-menu?]. } @section{Constructors} @defproc[(wv-menu [item-or-id any/c] ...) any/c]{ Creates a menu. If the first argument is a symbol, it is used as the menu identifier and removed from the remaining arguments. Otherwise the menu identifier is @racket[#f]. If the first remaining argument is itself a list, that list is used as the item list. Otherwise all remaining arguments are treated as menu items. This means the following forms are accepted: @racketblock[ (wv-menu item ...) (wv-menu 'some-id item ...) (wv-menu (list item ...)) (wv-menu 'some-id (list item ...)) ] The result is a value satisfying @racket[is-wv-menu?]. } @defproc[(wv-menu-item [id symbol?] [title string?] [#:icon-url icon-url (or/c boolean? string? url?) #f] [#:callback callback procedure? (λ args #t)] [#:submenu submenu (or/c boolean? any/c) #f] [#:separator separator boolean? #f]) any/c]{ Creates a menu item. @racket[id] must be a symbol and @racket[title] must be a string. @racket[icon-url] must be @racket[#f], a string, or a URL value. If it is a URL value, it is converted to a string using @racket[url->string] before being stored. @racket[submenu] must be @racket[#f] or a value satisfying @racket[is-wv-menu?]. @racket[separator] must be a boolean. If any argument does not satisfy these conditions, an exception is raised. } @section{Traversal and Lookup} @defproc[(wv-menu-for-each [menu any/c] [cb procedure?]) boolean?]{ Traverses @racket[menu] depth-first and calls @racket[cb] for each menu item. If a menu item contains a submenu, that submenu is traversed recursively. The callback is invoked only for menu items that are reached by the traversal. The function returns @racket[#t]. } @defproc[(with-wv-menu-item [menu any/c] [id symbol?] [cb procedure?]) any/c]{ Finds the menu item identified by @racket[id] and applies @racket[cb] to it. If @racket[menu] does not satisfy @racket[is-wv-menu?], an exception is raised. If @racket[id] is not a symbol, an exception is raised. If no item with the given id can be found, an exception is raised. After the callback has been applied, the original @racket[menu] value is returned. } @section{Mutation} @defproc[(wv-menu-set-title! [menu any/c] [id symbol?] [title string?]) any/c]{ Sets the title of the menu item identified by @racket[id]. @racket[title] must be a string. The function returns the original @racket[menu] value. } @defproc[(wv-menu-set-icon! [menu any/c] [id symbol?] [icon-url (or/c boolean? string? url?)]) any/c]{ Sets the icon URL of the menu item identified by @racket[id]. @racket[icon-url] must be @racket[#f], a string, or a URL value. If it is a URL value, it is converted to a string using @racket[url->string] before being stored. The function returns the original @racket[menu] value. } @defproc[(wv-menu-set-callback! [menu any/c] [id symbol?] [cb procedure?]) any/c]{ Sets the callback of the menu item identified by @racket[id]. @racket[cb] must be a procedure. The function returns the original @racket[menu] value. } @section{Conversion} @defproc[(wv-menu->json [menu any/c]) string?]{ Converts @racket[menu] to a JSON string. The conversion first builds a hash-based representation of the menu and then writes that representation with @racket[write-json]. In the JSON representation: @itemlist[#:style 'compact @item{the top-level object contains the keys @racket['menu] and @racket['id]} @item{menu item identifiers are converted to strings} @item{menu item titles are written under the key @racket['name]} @item{an icon is written only if it is not @racket[#f]} @item{a submenu is written recursively only if it is not @racket[#f]} @item{a separator flag is written only if it is not @racket[#f]}] The @racket['id] field of the top-level menu is also converted to a string in the JSON output. } @section{Accessors} @defproc[(wv-menu-id [m any/c]) any/c]{ Returns the identifier of @racket[m]. } @defproc[(wv-menu-item-id [mi any/c]) symbol?]{ Returns the identifier of the menu item @racket[mi]. } @defproc[(wv-menu-item-callback [mi any/c]) procedure?]{ Returns the callback associated with the menu item @racket[mi]. }