factor/basis/ui/gadgets/tables/tables.factor

319 lines
8.4 KiB
Factor
Raw Normal View History

! Copyright (C) 2008, 2009 Slava Pestov.
2008-12-19 03:37:40 -05:00
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays colors fry kernel math
2008-12-19 03:37:40 -05:00
math.geometry.rect math.order math.vectors namespaces opengl
sequences ui.gadgets ui.gadgets.scrollers ui.gadgets.status-bar
ui.gadgets.worlds ui.gadgets.theme ui.gestures ui.render ui.text
ui.gadgets.menus models math.ranges sequences combinators fonts ;
2008-12-19 03:37:40 -05:00
IN: ui.gadgets.tables
! Row rendererer protocol
GENERIC: row-columns ( row renderer -- columns )
GENERIC: row-value ( row renderer -- object )
2008-12-19 03:37:40 -05:00
SINGLETON: trivial-renderer
M: trivial-renderer row-columns drop ;
M: object row-value drop ;
2008-12-19 03:37:40 -05:00
TUPLE: table < gadget
2009-01-16 17:39:32 -05:00
renderer filled-column column-alignment action hook
column-widths total-width
font text-color selection-color focus-border-color
mouse-color column-line-color selection-required?
selected-index selected-value
mouse-index
focused? ;
2008-12-19 03:37:40 -05:00
: <table> ( rows -- table )
table new-gadget
swap >>model
trivial-renderer >>renderer
[ drop ] >>action
2009-01-16 17:39:32 -05:00
[ ] >>hook
2008-12-19 03:37:40 -05:00
f <model> >>selected-value
sans-serif-font >>font
selection-color >>selection-color
focus-border-color >>focus-border-color
2009-01-08 01:04:44 -05:00
dark-gray >>column-line-color
2008-12-19 03:37:40 -05:00
black >>mouse-color
black >>text-color ;
<PRIVATE
2008-12-19 03:37:40 -05:00
: line-height ( table -- n )
font>> "" text-height ;
2008-12-19 03:37:40 -05:00
2009-01-12 20:32:10 -05:00
CONSTANT: table-gap 6
2008-12-19 03:37:40 -05:00
: table-rows ( table -- rows )
[ control-value ] [ renderer>> ] bi '[ _ row-columns ] map ;
: (compute-column-widths) ( font rows -- total widths )
2008-12-19 03:37:40 -05:00
[ drop 0 { } ] [
2009-01-25 18:55:27 -05:00
[ nip first length 0 <repetition> ] 2keep
[ [ text-width ] with map vmax ] with each
[ [ sum ] [ length 1 [-] table-gap * ] bi + ] keep
2008-12-19 03:37:40 -05:00
] if-empty ;
: compute-column-widths ( table -- total-width column-widths )
[ font>> ] [ table-rows ] bi (compute-column-widths) ;
2008-12-19 03:37:40 -05:00
: update-cached-widths ( table -- )
dup compute-column-widths
[ >>total-width ] [ >>column-widths ] bi*
drop ;
: filled-column-width ( table -- n )
[ dim>> first ] [ total-width>> ] bi [-] ;
: update-filled-column ( table -- )
[ filled-column-width ]
[ filled-column>> ]
[ column-widths>> ] tri
2dup empty? not and
[ [ + ] change-nth ] [ 3drop ] if ;
2008-12-19 03:37:40 -05:00
M: table layout*
[ update-cached-widths ] [ update-filled-column ] bi ;
2008-12-19 03:37:40 -05:00
: row-rect ( table row -- rect )
[ [ line-height ] dip * 0 swap 2array ]
[ drop [ dim>> first ] [ line-height ] bi 2array ] 2bi <rect> ;
: highlight-row ( table row color quot -- )
[ [ row-rect rect-bounds ] dip gl-color ] dip
'[ _ @ ] with-translation ; inline
: draw-selected-row ( table row -- )
over selection-color>> [ gl-fill-rect ] highlight-row ;
: draw-focused-row ( table row -- )
over focused?>> [
over focus-border-color>> [ gl-rect ] highlight-row
2008-12-19 03:37:40 -05:00
] [ 2drop ] if ;
: draw-selected ( table -- )
dup selected-index>> dup
[ [ draw-selected-row ] [ draw-focused-row ] 2bi ]
[ 2drop ]
if ;
2008-12-19 03:37:40 -05:00
: draw-moused ( table -- )
dup mouse-index>> dup [
over mouse-color>> [ gl-rect ] highlight-row
] [ 2drop ] if ;
2008-12-19 03:37:40 -05:00
2009-01-12 20:32:10 -05:00
: column-offsets ( table -- xs )
0 [ table-gap + + ] accumulate nip ;
: column-line-offsets ( table -- xs )
2009-01-13 20:08:49 -05:00
column-offsets
[ f ] [ rest-slice [ table-gap 2/ - ] map ] if-empty ;
2009-01-08 01:04:44 -05:00
: draw-columns ( table -- )
[ column-line-color>> gl-color ]
[
2009-01-12 20:32:10 -05:00
[ column-widths>> column-line-offsets ] [ dim>> second ] bi
2009-01-08 01:04:44 -05:00
'[ [ 0 2array ] [ _ 2array ] bi gl-line ] each
] bi ;
2008-12-19 03:37:40 -05:00
: y>row ( y table -- n )
line-height /i ;
: validate-row ( m table -- n )
control-value [ drop f ] [ length 1- min 0 max ] if-empty ;
2008-12-19 03:37:40 -05:00
: visible-row ( table quot -- n )
'[
[ clip get @ origin get [ second ] bi@ - ] dip
2008-12-19 03:37:40 -05:00
y>row
] keep validate-row ; inline
: first-visible-row ( table -- n )
[ loc>> ] visible-row ;
2008-12-19 03:37:40 -05:00
: last-visible-row ( table -- n )
[ rect-extent nip ] visible-row 1+ ;
2008-12-19 03:37:40 -05:00
: column-loc ( font column width align -- loc )
[ [ text-width ] dip swap - ] dip
* 0 2array ;
: draw-column ( font column width align -- )
over [
[ 2dup ] 2dip column-loc draw-text
] dip table-gap + 0 2array gl-translate ;
: draw-row ( columns widths align font -- )
'[ [ _ ] 3dip draw-column ] 3each ;
2008-12-19 03:37:40 -05:00
: each-slice-index ( from to seq quot -- )
[ [ <slice> ] [ drop [a,b) ] 3bi ] dip 2each ; inline
: column-alignment ( table -- seq )
dup column-alignment>>
[ ] [ column-widths>> length 0 <repetition> ] ?if ;
: draw-rows ( table -- )
{
[ text-color>> gl-color ]
[ first-visible-row ]
[ last-visible-row ]
[ control-value ]
[ line-height ]
[ renderer>> ]
[ column-widths>> ]
[ column-alignment ]
[ font>> ]
} cleave '[
[ 0 ] dip _ * 2array [
_ row-columns _ _ _ draw-row
2008-12-19 03:37:40 -05:00
] with-translation
] each-slice-index ;
M: table draw-gadget*
dup control-value empty? [ drop ] [
origin get [
2009-01-08 01:04:44 -05:00
{
[ draw-selected ]
[ draw-columns ]
[ draw-moused ]
[ draw-rows ]
} cleave
2008-12-19 03:37:40 -05:00
] with-translation
] if ;
M: table pref-dim*
[ compute-column-widths drop ] keep
[ font>> "" text-height ]
[ control-value length ]
bi * 2array ;
2008-12-19 03:37:40 -05:00
: nth-row ( row table -- value/f ? )
over [ control-value nth t ] [ 2drop f f ] if ;
2008-12-19 03:37:40 -05:00
PRIVATE>
: (selected-row) ( table -- value/f ? )
[ selected-index>> ] keep nth-row ;
: selected-row ( table -- value/f ? )
[ (selected-row) ] keep
swap [ renderer>> row-value t ] [ 2drop f f ] if ;
<PRIVATE
2008-12-19 03:37:40 -05:00
: update-selected-value ( table -- )
[ selected-row drop ] [ selected-value>> ] bi set-model ;
2008-12-19 03:37:40 -05:00
: initial-selected-index ( model table -- n/f )
[ value>> length 1 >= ] [ selection-required?>> ] bi* and 0 f ? ;
: show-row-summary ( table n -- )
over nth-row
[ swap [ renderer>> row-value ] keep show-summary ]
[ 2drop ]
if ;
2008-12-19 03:37:40 -05:00
M: table model-changed
2009-01-25 18:55:27 -05:00
[ nip ] [ initial-selected-index ] 2bi {
[ >>selected-index drop ]
[ show-row-summary ]
[ drop update-selected-value ]
[ drop relayout ]
} 2cleave ;
2008-12-19 03:37:40 -05:00
: thin-row-rect ( table row -- rect )
row-rect [ { 0 1 } v* ] change-dim ;
2009-01-09 18:58:22 -05:00
: (select-row) ( table n -- )
[ dup [ [ thin-row-rect ] [ drop ] 2bi scroll>rect ] [ 2drop ] if ]
[ >>selected-index relayout-1 ]
2008-12-19 03:37:40 -05:00
2bi ;
: mouse-row ( table -- n )
[ hand-rel second ] keep y>row ;
: table-button-down ( table -- )
2008-12-19 03:37:40 -05:00
dup request-focus
dup control-value empty? [ drop ] [
dup [ mouse-row ] keep validate-row
[ >>mouse-index ] [ (select-row) ] bi
] if ;
2009-01-13 17:22:07 -05:00
PRIVATE>
: row-action ( table -- )
dup selected-row [ swap action>> call ] [ 2drop ] if ;
2009-01-13 17:22:07 -05:00
<PRIVATE
: table-button-up ( table -- )
hand-click# get 2 =
[ row-action ] [ update-selected-value ] if ;
2008-12-19 03:37:40 -05:00
2009-01-09 18:58:22 -05:00
: select-row ( table n -- )
over validate-row
[ (select-row) ]
[ drop update-selected-value ]
[ show-row-summary ]
2tri ;
2008-12-19 03:37:40 -05:00
: prev/next-row ( table n -- )
[ dup selected-index>> ] dip '[ _ + ] [ 0 ] if* select-row ;
2008-12-19 03:37:40 -05:00
: prev-row ( table -- )
-1 prev/next-row ;
2008-12-19 03:37:40 -05:00
: next-row ( table -- )
1 prev/next-row ;
2008-12-19 03:37:40 -05:00
: first-row ( table -- )
0 select-row ;
: last-row ( table -- )
dup control-value length 1- select-row ;
: hide-mouse-help ( table -- )
f >>mouse-index [ hide-status ] [ relayout-1 ] bi ;
: valid-row? ( row table -- ? )
control-value length 1- 0 swap between? ;
: if-mouse-row ( table true false -- )
[ [ mouse-row ] keep 2dup valid-row? ]
[ ] [ '[ nip @ ] ] tri* if ; inline
2008-12-19 03:37:40 -05:00
: show-mouse-help ( table -- )
[
swap
[ >>mouse-index relayout-1 ]
[ show-row-summary ]
2bi
] [ hide-mouse-help ] if-mouse-row ;
2009-01-16 17:39:32 -05:00
: show-table-menu ( table -- )
[
2009-01-16 17:39:32 -05:00
tuck [ nth-row drop ] [ renderer>> row-value ] [ hook>> ] tri
show-operations-menu
] [ drop ] if-mouse-row ;
2008-12-19 03:37:40 -05:00
table H{
{ mouse-enter [ show-mouse-help ] }
{ mouse-leave [ hide-mouse-help ] }
{ motion [ show-mouse-help ] }
{ T{ button-down } [ table-button-down ] }
2009-01-16 17:39:32 -05:00
{ T{ button-down f f 3 } [ show-table-menu ] }
{ T{ button-up } [ table-button-up ] }
{ gain-focus [ t >>focused? drop ] }
{ lose-focus [ f >>focused? drop ] }
{ T{ drag } [ table-button-down ] }
2009-01-06 17:53:01 -05:00
{ T{ key-down f f "RET" } [ row-action ] }
2008-12-19 03:37:40 -05:00
{ T{ key-down f f "UP" } [ prev-row ] }
{ T{ key-down f f "DOWN" } [ next-row ] }
{ T{ key-down f f "HOME" } [ first-row ] }
{ T{ key-down f f "END" } [ last-row ] }
} set-gestures
PRIVATE>