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 origin get v+
132 swap caret-dim over v+ gl-line
135 : line-translation ( n -- loc )
136 editor get line-height * 0.0 swap 2array ;
138 : translate-lines ( n -- )
139 line-translation gl-translate ;
141 : draw-line ( editor str -- )
142 >r dup editor-color gl-color editor-font r>
143 { 0 0 } draw-string ;
145 : first-visible-line ( editor -- n )
146 clip get rect-loc second origin get second -
149 : last-visible-line ( editor -- n )
150 clip get rect-extent nip second origin get second -
153 : with-editor ( editor quot -- )
156 dup first-visible-line \ first-visible-line set
157 dup last-visible-line \ last-visible-line set
158 dup control-model document set
161 ] with-scope ; inline
163 : visible-lines ( editor -- seq )
164 \ first-visible-line get
165 \ last-visible-line get
166 rot control-value <slice> ;
168 : with-editor-translation ( n quot -- )
169 >r line-translation origin get v+ r> with-translation ;
173 \ first-visible-line get [
174 editor get dup visible-lines
175 [ draw-line 1 translate-lines ] each-with
176 ] with-editor-translation ;
178 : selection-start/end ( editor -- start end )
179 dup editor-mark* swap editor-caret*
180 2dup <=> 0 > [ swap ] when ;
182 : (draw-selection) ( x1 x2 -- )
184 0.0 swap editor get line-height glRectd ;
186 : draw-selected-line ( start end n -- )
187 [ start/end-on-line ] keep tuck
188 >r >r editor get offset>x r> r>
192 : draw-selection ( -- )
193 editor get editor-selection-color gl-color
194 editor get selection-start/end
197 >r 2dup r> draw-selected-line
200 ] with-editor-translation ;
202 M: editor draw-gadget*
203 [ draw-selection draw-lines draw-caret ] with-editor ;
205 : editor-height ( editor -- n )
206 [ control-value length ] keep line>y ;
208 : editor-width ( editor -- n )
209 0 swap dup editor-font* swap control-value
210 [ string-width max ] each-with ;
213 dup editor-width swap editor-height 2array ;
215 M: editor gadget-selection?
216 selection-start/end = not ;
218 M: editor gadget-selection
219 [ selection-start/end ] keep control-model doc-range ;
221 : remove-editor-selection ( editor -- )
222 [ selection-start/end ] keep control-model
225 M: editor user-input*
226 [ selection-start/end ] keep control-model set-doc-range t ;
228 : editor-text ( editor -- str )
229 control-model doc-text ;
231 : set-editor-text ( str editor -- )
232 control-model set-doc-text ;
234 ! Editors support the stream output protocol
235 M: editor stream-write1 >r ch>string r> stream-write ;
237 M: editor stream-write control-self user-input ;
239 M: editor stream-close drop ;