1 ! Copyright (C) 2006 Slava Pestov
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays errors freetype gadgets gadgets-borders
5 gadgets-buttons gadgets-frames gadgets-labels
6 gadgets-scrolling gadgets-theme io kernel math models namespaces
7 opengl sequences strings styles ;
10 font color caret-color selection-color
14 TUPLE: loc-monitor editor ;
16 : <loc> ( editor -- loc )
17 <loc-monitor> { 0 0 } <model> [ add-connection ] keep ;
19 : init-editor-locs ( editor -- )
20 dup <loc> over set-editor-caret
21 dup <loc> swap set-editor-mark ;
23 C: editor ( -- editor )
24 dup <document> <gadget> delegate>control
28 : activate-editor-model ( editor model -- )
29 dup activate-model swap control-model add-loc ;
31 : deactivate-editor-model ( editor model -- )
32 dup deactivate-model swap control-model remove-loc ;
35 dup dup editor-caret activate-editor-model
36 dup dup editor-mark activate-editor-model
37 dup control-self swap control-model add-connection ;
40 dup dup editor-caret deactivate-editor-model
41 dup dup editor-mark deactivate-editor-model
42 dup control-self swap control-model remove-connection ;
44 M: editor model-changed
45 control-self dup control-model
46 over editor-caret [ over validate-loc ] (change-model)
47 over editor-mark [ over validate-loc ] (change-model)
50 : editor-caret* editor-caret model-value ;
52 : editor-mark* editor-mark model-value ;
54 : change-caret ( editor quot -- )
55 over >r >r dup editor-caret* swap control-model r> call r>
56 [ control-model validate-loc ] keep
57 editor-caret set-model* ; inline
59 : mark>caret ( editor -- )
60 dup editor-caret* swap editor-mark set-model* ;
62 : change-caret&mark ( editor quot -- )
63 over >r change-caret r> mark>caret ; inline
65 : editor-line ( n editor -- str ) control-value nth ;
67 : editor-font* ( editor -- font ) editor-font lookup-font ;
69 : line-height ( editor -- n )
70 editor-font* font-height ;
72 : run-char-widths ( str editor -- wlist )
73 #! List of x co-ordinates of each character.
74 editor-font* swap >array [ char-width ] map-with
75 dup 0 [ + ] accumulate nip swap 2 v/n v+ ;
77 : x>offset ( x line# editor -- col# )
79 over >r run-char-widths [ <= ] find-with drop dup -1 =
80 [ drop r> length ] [ r> drop ] if ;
82 : y>line ( y editor -- line# )
83 [ line-height / >fixnum ] keep control-model validate-line ;
85 : point>loc ( point editor -- loc )
86 over second over y>line [
87 >r >r first r> r> swap x>offset
90 : click-loc ( editor model -- )
91 >r [ hand-rel ] keep point>loc r> set-model* ;
93 : focus-editor ( editor -- )
94 t over set-editor-focused? relayout-1 ;
96 : unfocus-editor ( editor -- )
97 f over set-editor-focused? relayout-1 ;
99 : (offset>x) ( font col# str -- x )
100 swap head-slice string-width ;
102 : offset>x ( col# line# editor -- x )
103 [ editor-line ] keep editor-font* -rot (offset>x) ;
105 : loc>x ( loc editor -- x ) >r first2 swap r> offset>x ;
107 : line>y ( lines# editor -- y )
110 : caret-loc ( editor -- loc )
111 [ editor-caret* ] keep 2dup loc>x
112 rot first rot line>y 2array ;
114 : caret-dim ( editor -- dim )
115 line-height 0 swap 2array ;
117 : scroll>caret ( editor -- )
118 dup gadget-grafted? [
119 dup caret-loc over caret-dim { 1 0 } v+ <rect>
123 M: loc-monitor model-changed
124 loc-monitor-editor control-self
125 dup relayout-1 scroll>caret ;
128 editor get editor-focused? [
130 dup editor-caret-color gl-color
131 dup caret-loc swap caret-dim over v+ gl-line
134 : translate-lines ( n -- )
135 editor get line-height * 0.0 swap 0.0 glTranslated ;
137 : draw-line ( editor str -- )
138 over editor-color gl-color
139 >r editor-font r> draw-string ;
141 : first-visible-line ( editor -- n )
142 clip get rect-loc second origin get second -
145 : last-visible-line ( editor -- n )
146 clip get rect-extent nip second origin get second -
149 : with-editor ( editor quot -- )
152 dup first-visible-line \ first-visible-line set
153 dup last-visible-line \ last-visible-line set
154 dup control-model document set
157 ] with-scope ; inline
159 : visible-lines ( editor -- seq )
160 \ first-visible-line get
161 \ last-visible-line get
162 rot control-value <slice> ;
166 \ first-visible-line get translate-lines
167 editor get dup visible-lines
168 [ draw-line 1 translate-lines ] each-with
171 : selection-start/end ( editor -- start end )
172 dup editor-mark* swap editor-caret*
173 2dup <=> 0 > [ swap ] when ;
175 : (draw-selection) ( x1 x2 -- )
177 0.0 swap editor get line-height glRectd ;
179 : draw-selected-line ( start end n -- )
180 [ start/end-on-line ] keep tuck
181 >r >r editor get offset>x r> r>
185 : draw-selection ( -- )
188 dup editor-selection-color gl-color
190 over first translate-lines
192 >r 2dup r> draw-selected-line
197 M: editor draw-gadget*
198 [ draw-selection draw-lines draw-caret ] with-editor ;
200 : editor-height ( editor -- n )
201 [ control-value length ] keep line>y ;
203 : editor-width ( editor -- n )
204 0 swap dup editor-font* swap control-value
205 [ string-width max ] each-with ;
208 dup editor-width swap editor-height 2array ;
210 M: editor gadget-selection?
211 selection-start/end = not ;
213 M: editor gadget-selection
214 [ selection-start/end ] keep control-model doc-range ;
216 : remove-editor-selection ( editor -- )
217 [ selection-start/end ] keep control-model
220 M: editor user-input*
221 [ selection-start/end ] keep control-model set-doc-range t ;
223 : editor-text ( editor -- str )
224 control-model doc-text ;
226 : set-editor-text ( str editor -- )
227 control-model set-doc-text ;
229 ! Editors support the stream output protocol
230 M: editor stream-write1 >r ch>string r> stream-write ;
232 M: editor stream-write control-self user-input ;
234 M: editor stream-close drop ;