Radio buttons and check boxes

release
Slava Pestov 2007-10-31 01:04:54 -04:00
parent 8ddad64fb5
commit 58545d5756
8 changed files with 164 additions and 41 deletions

View File

@ -2,7 +2,7 @@
! Portions copyright (C) 2007 Eduardo Cavazos. ! Portions copyright (C) 2007 Eduardo Cavazos.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types io kernel math namespaces USING: alien alien.c-types io kernel math namespaces
sequences math.vectors opengl.gl opengl.glu combinators ; sequences math.vectors math.constants math.functions opengl.gl opengl.glu combinators arrays ;
IN: opengl IN: opengl
: coordinates [ first2 ] 2apply ; : coordinates [ first2 ] 2apply ;
@ -63,6 +63,23 @@ IN: opengl
: gl-poly ( points -- ) : gl-poly ( points -- )
GL_LINE_LOOP (gl-poly) ; GL_LINE_LOOP (gl-poly) ;
: circle-steps dup length v/n 2 pi * v*n ;
: unit-circle dup [ sin ] map swap [ cos ] map ;
: adjust-points [ [ 1 + 0.5 * ] map ] 2apply ;
: scale-points 2array flip [ v* ] curry* map [ v+ ] curry* map ;
: circle-points ( loc dim steps -- points )
circle-steps unit-circle adjust-points scale-points ;
: gl-circle ( loc dim steps -- )
circle-points gl-poly ;
: gl-fill-circle ( loc dim steps -- )
circle-points gl-fill-poly ;
: prepare-gradient ( direction dim -- v1 v2 ) : prepare-gradient ( direction dim -- v1 v2 )
tuck v* [ v- ] keep ; tuck v* [ v- ] keep ;

View File

@ -7,11 +7,7 @@ HELP: button
$nl $nl
"A button's appearance can vary depending on the state of the mouse button if the " { $link gadget-interior } " or " { $link gadget-boundary } " slots are set to instances of " { $link button-paint } "." "A button's appearance can vary depending on the state of the mouse button if the " { $link gadget-interior } " or " { $link gadget-boundary } " slots are set to instances of " { $link button-paint } "."
$nl $nl
"A button can be selected, which is distinct from being pressed. This state is held in the " { $link button-selected? } " slot, and is used by the " { $link <radio-box> } " word to construct a row of buttons for choosing among several alternatives." } ; "A button can be selected, which is distinct from being pressed. This state is held in the " { $link button-selected? } " slot, and is used by the " { $link <toggle-buttons> } " word to construct a row of buttons for choosing among several alternatives." } ;
HELP: >label
{ $values { "obj" "a label specifier" } { "gadget" "a new " { $link gadget } } }
{ $description "Convert the object into a gadget suitable for use as the label of a button. If " { $snippet "obj" } " is already a gadget, does nothing. Otherwise creates a " { $link label } " gadget if it is a string and an empty gadget if " { $snippet "obj" } " is " { $link f } "." } ;
HELP: <button> HELP: <button>
{ $values { "gadget" gadget } { "quot" "a quotation with stack effect " { $snippet "( button -- )" } } { "button" "a new " { $link button } } } { $values { "gadget" gadget } { "quot" "a quotation with stack effect " { $snippet "( button -- )" } } { "button" "a new " { $link button } } }
@ -35,20 +31,20 @@ HELP: button-paint
{ { $link button-paint-plain } " - the button is inactive" } { { $link button-paint-plain } " - the button is inactive" }
{ { $link button-paint-rollover } " - the button is under the mouse" } { { $link button-paint-rollover } " - the button is under the mouse" }
{ { $link button-paint-pressed } " - the button is under the mouse and a mouse button is held down" } { { $link button-paint-pressed } " - the button is under the mouse and a mouse button is held down" }
{ { $link button-paint-selected } " - the button is selected (see " { $link <radio-box> } } { { $link button-paint-selected } " - the button is selected (see " { $link <toggle-buttons> } }
} }
"The " { $link <roll-button> } " and " { $link <bevel-button> } " words create " { $link button } " instances with specific " { $link button-paint } "." } ; "The " { $link <roll-button> } " and " { $link <bevel-button> } " words create " { $link button } " instances with specific " { $link button-paint } "." } ;
HELP: <radio-control> HELP: <toggle-button>
{ $values { "model" model } { "value" object } { "label" "a label specifier" } { "gadget" gadget } } { $values { "model" model } { "value" object } { "label" "a label specifier" } { "gadget" gadget } }
{ $description { $description
"Creates a " { $link <bevel-button> } " which sets the model's value to " { $snippet "value" } " when pressed. After being pressed, the button becomes selected until the value of the model changes again." "Creates a " { $link <bevel-button> } " which sets the model's value to " { $snippet "value" } " when pressed. After being pressed, the button becomes selected until the value of the model changes again."
} }
{ $notes "Typically a row of radio controls should be built together using " { $link <radio-box> } "." } ; { $notes "Typically a row of radio controls should be built together using " { $link <toggle-buttons> } "." } ;
HELP: <radio-box> HELP: <toggle-buttons>
{ $values { "model" model } { "assoc" "an association list mapping labels to objects" } { "gadget" gadget } } { $values { "model" model } { "assoc" "an association list mapping labels to objects" } { "gadget" gadget } }
{ $description "Creates a row of labelled " { $link <radio-control> } " gadgets which change the value of the model." } ; { $description "Creates a row of labelled " { $link <toggle-button> } " gadgets which change the value of the model." } ;
HELP: <command-button> HELP: <command-button>
{ $values { "target" object } { "gesture" "a gesture" } { "command" "a command" } { "button" "a new " { $link button } } } { $values { "target" object } { "gesture" "a gesture" } { "command" "a command" } { "button" "a new " { $link button } } }
@ -74,11 +70,8 @@ ARTICLE: "ui.gadgets.buttons" "Button gadgets"
{ $subsection <command-button> } { $subsection <command-button> }
{ $subsection <toolbar> } { $subsection <toolbar> }
"A radio box is a row of buttons for choosing amongst several distinct possibilities:" "A radio box is a row of buttons for choosing amongst several distinct possibilities:"
{ $subsection <radio-box> } { $subsection <toggle-buttons> }
"Button appearance can be customized:" "Button appearance can be customized:"
{ $subsection button-paint } { $subsection button-paint }
"Button constructors take " { $emphasis "label specifiers" } " as input. A label specifier is either a string, an array of strings, a gadget or " { $link f } "." "Button constructors take " { $emphasis "label specifiers" } " as input. A label specifier is either a string, an array of strings, a gadget or " { $link f } "."
$nl
"A generic word used to convert label specifiers to gadgets:"
{ $subsection >label }
{ $see-also <command-button> "ui-commands" } ; { $see-also <command-button> "ui-commands" } ;

View File

@ -4,7 +4,7 @@ USING: arrays ui.commands ui.gadgets ui.gadgets.borders
ui.gadgets.controls ui.gadgets.labels ui.gadgets.theme ui.gadgets.controls ui.gadgets.labels ui.gadgets.theme
ui.gadgets.tracks ui.gadgets.packs ui.gadgets.worlds ui.gestures ui.gadgets.tracks ui.gadgets.packs ui.gadgets.worlds ui.gestures
ui.render kernel math models namespaces sequences strings ui.render kernel math models namespaces sequences strings
quotations assocs combinators classes colors ; quotations assocs combinators classes colors tuples ;
IN: ui.gadgets.buttons IN: ui.gadgets.buttons
TUPLE: button pressed? selected? quot ; TUPLE: button pressed? selected? quot ;
@ -38,12 +38,6 @@ button H{
{ T{ mouse-enter } [ button-update ] } { T{ mouse-enter } [ button-update ] }
} set-gestures } set-gestures
GENERIC: >label ( obj -- gadget )
M: string >label <label> ;
M: array >label <label> ;
M: object >label ;
M: f >label drop <gadget> ;
: <button> ( gadget quot -- button ) : <button> ( gadget quot -- button )
button construct-empty button construct-empty
[ set-button-quot ] keep [ set-button-quot ] keep
@ -53,12 +47,14 @@ TUPLE: button-paint plain rollover pressed selected ;
C: <button-paint> button-paint C: <button-paint> button-paint
: find-button [ [ button? ] is? ] find-parent ;
: button-paint ( button paint -- button paint ) : button-paint ( button paint -- button paint )
{ over find-button {
{ [ over button-pressed? ] [ button-paint-pressed ] } { [ dup button-pressed? ] [ drop button-paint-pressed ] }
{ [ over button-selected? ] [ button-paint-selected ] } { [ dup button-selected? ] [ drop button-paint-selected ] }
{ [ over button-rollover? ] [ button-paint-rollover ] } { [ dup button-rollover? ] [ drop button-paint-rollover ] }
{ [ t ] [ button-paint-plain ] } { [ t ] [ drop button-paint-plain ] }
} cond ; } cond ;
M: button-paint draw-interior M: button-paint draw-interior
@ -99,14 +95,78 @@ repeat-button H{
repeat-button construct-empty repeat-button construct-empty
[ >r <bevel-button> r> set-gadget-delegate ] keep ; [ >r <bevel-button> r> set-gadget-delegate ] keep ;
: <radio-control> ( model value label -- gadget ) : checkmark-theme ( gadget -- )
over [ swap set-control-value ] curry <bevel-button> f
swap [ swap >r = r> set-button-selected? ] curry <control> ; f
black <solid>
black <checkmark-paint>
<button-paint>
over set-gadget-interior
black <solid>
swap set-gadget-boundary ;
: <radio-box> ( model assoc -- gadget ) : <checkmark> ( -- gadget )
[ <gadget>
swap [ -rot <radio-control> gadget, ] curry assoc-each dup checkmark-theme
] make-shelf ; { 14 14 } over set-gadget-dim ;
: toggle-model ( model -- )
[ not ] change-model ;
: checkbox-theme
f over set-gadget-interior
{ 5 5 } over set-pack-gap
1/2 swap set-pack-align ;
: <checkbox> ( model label -- checkbox )
<checkmark>
label-on-right
over [ toggle-model drop ] curry <button>
[ set-button-selected? ] <control>
dup checkbox-theme ;
: radio-knob-theme ( gadget -- )
f
f
black <radio-paint>
black <radio-paint>
<button-paint>
over set-gadget-interior
black <radio-paint>
swap set-gadget-boundary ;
: <radio-knob> ( -- gadget )
<gadget>
dup radio-knob-theme
{ 16 16 } over set-gadget-dim ;
: <radio-control> ( model value gadget quot -- control )
>r dupd [ set-control-value ] curry* r> call
[ >r = r> set-button-selected? ] curry* <control> ; inline
: <radio-controls> ( model assoc quot -- gadget )
swapd [ >r -rot r> call gadget, ] 2curry assoc-each ; inline
: radio-button-theme
{ 5 5 } over set-pack-gap 1/2 swap set-pack-align ;
: <radio-button> ( model value label -- gadget )
<radio-knob> label-on-right
[ <button> ] <radio-control>
dup radio-button-theme ;
: radio-buttons-theme
{ 5 5 } swap set-pack-gap ;
: <radio-buttons> ( model assoc -- gadget )
[ [ <radio-button> ] <radio-controls> ] make-filled-pile
dup radio-buttons-theme ;
: <toggle-button> ( model value label -- gadget )
[ <bevel-button> ] <radio-control> ;
: <toggle-buttons> ( model assoc -- gadget )
[ [ <toggle-button> ] <radio-controls> ] make-shelf ;
: command-button-quot ( target command -- quot ) : command-button-quot ( target command -- quot )
[ invoke-command drop ] 2curry ; [ invoke-command drop ] 2curry ;

View File

@ -34,6 +34,15 @@ TUPLE: loc-monitor editor ;
dup init-editor-locs dup init-editor-locs
dup editor-theme ; dup editor-theme ;
: field-theme ( gadget -- )
gray <solid> swap set-gadget-boundary ;
: <field> ( model -- )
drop
<editor>
2 <border>
dup field-theme ;
: construct-editor ( class -- tuple ) : construct-editor ( class -- tuple )
>r <editor> { set-gadget-delegate } r> >r <editor> { set-gadget-delegate } r>
(construct-control) ; inline (construct-control) ; inline

View File

@ -30,6 +30,12 @@ ARTICLE: "ui.gadgets.labels" "Label gadgets"
{ $subsection <label> } { $subsection <label> }
{ $subsection <label-control> } { $subsection <label-control> }
{ $subsection label-string } { $subsection label-string }
{ $subsection set-label-string } ; { $subsection set-label-string }
"Label specifiers are used by buttons, checkboxes and radio buttons:"
{ $subsection >label } ;
ABOUT: "ui.gadgets.labels" ABOUT: "ui.gadgets.labels"
HELP: >label
{ $values { "obj" "a label specifier" } { "gadget" "a new " { $link gadget } } }
{ $description "Convert the object into a gadget suitable for use as the label of a button. If " { $snippet "obj" } " is already a gadget, does nothing. Otherwise creates a " { $link label } " gadget if it is a string and an empty gadget if " { $snippet "obj" } " is " { $link f } "." } ;

View File

@ -2,8 +2,8 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays hashtables io kernel math namespaces USING: arrays hashtables io kernel math namespaces
opengl sequences io.streams.lines strings splitting opengl sequences io.streams.lines strings splitting
ui.gadgets ui.gadgets.controls ui.gadgets.theme ui.render ui.gadgets ui.gadgets.controls ui.gadgets.packs ui.gadgets.theme
colors ; ui.render colors ;
IN: ui.gadgets.labels IN: ui.gadgets.labels
! A label gadget draws a string. ! A label gadget draws a string.
@ -47,3 +47,15 @@ M: label gadget-text* label-string % ;
: reverse-video-theme ( label -- ) : reverse-video-theme ( label -- )
white over set-label-color white over set-label-color
black solid-interior ; black solid-interior ;
GENERIC: >label ( obj -- gadget )
M: string >label <label> ;
M: array >label <label> ;
M: object >label ;
M: f >label drop <gadget> ;
: label-on-left ( gadget label -- button )
[ >label gadget, gadget, ] make-shelf ;
: label-on-right ( label gadget -- button )
[ gadget, >label gadget, ] make-shelf ;

View File

@ -140,6 +140,33 @@ M: polygon draw-interior
>r <polygon> <gadget> r> over set-rect-dim >r <polygon> <gadget> r> over set-rect-dim
[ set-gadget-interior ] keep ; [ set-gadget-interior ] keep ;
! Checkbox and radio button pens
TUPLE: checkmark-paint color ;
C: <checkmark-paint> checkmark-paint
M: checkmark-paint draw-interior
checkmark-paint-color gl-color
origin get [
rect-dim
{ 0 0 } over gl-line
dup { 0 1 } v* swap { 1 0 } v* gl-line
] with-translation ;
TUPLE: radio-paint color ;
C: <radio-paint> radio-paint
M: radio-paint draw-interior
radio-paint-color gl-color
origin get { 4 4 } v+ swap rect-dim { 8 8 } v- 12 gl-fill-circle ;
M: radio-paint draw-boundary
radio-paint-color gl-color
origin get { 1 1 } v+ swap rect-dim { 2 2 } v- 12 gl-circle ;
! Font rendering
SYMBOL: font-renderer SYMBOL: font-renderer
HOOK: open-font font-renderer ( font -- open-font ) HOOK: open-font font-renderer ( font -- open-font )

View File

@ -9,7 +9,7 @@ ui.gadgets.books ui.gadgets.buttons ui.gadgets.controls
ui.gadgets.labelled ui.gadgets.scrollers ui.gadgets.tracks ui.gadgets.labelled ui.gadgets.scrollers ui.gadgets.tracks
ui.gadgets.worlds ui.gadgets.presentations ui.gestures words ui.gadgets.worlds ui.gadgets.presentations ui.gestures words
vocabs.loader tools.test ui.gadgets.buttons vocabs.loader tools.test ui.gadgets.buttons
ui.gadgets.status-bar ; ui.gadgets.status-bar mirrors ;
IN: ui.tools IN: ui.tools
: workspace-tabs ( -- seq ) : workspace-tabs ( -- seq )
@ -24,9 +24,8 @@ IN: ui.tools
: <workspace-tabs> ( -- tabs ) : <workspace-tabs> ( -- tabs )
g control-model g control-model
"tool-switching" workspace command-map "tool-switching" workspace command-map
[ command-string ] { } assoc>map [ command-string ] { } assoc>map <enum> >alist
[ length ] keep 2array flip <toggle-buttons> ;
<radio-box> ;
: <workspace-book> ( -- gadget ) : <workspace-book> ( -- gadget )
workspace-tabs [ execute ] map g control-model <book> ; workspace-tabs [ execute ] map g control-model <book> ;