/[eiffelstudio]/trunk/Src/Eiffel/interface/new_graphical/shared/editor_token_utility/eb_editor_token_text.e
ViewVC logotype

Contents of /trunk/Src/Eiffel/interface/new_graphical/shared/editor_token_utility/eb_editor_token_text.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71346 - (show annotations)
Mon Dec 3 19:25:51 2007 UTC (12 years, 1 month ago) by paulb
File size: 33198 byte(s)
Supported optional selection exclusion for EB_GRID_EDITOR_TOKEN_ITEM to mirror that of the same functionality in EV_GRID_LABEL_ITEM.
Supported setting of selection background colors on EB_EDITOR_TOKEN_TEXT.
Updated the error list (and base implementation) tool to set correct grid selection colors and to disable selection for non applicable areas.
Error list is now-multiple select.
1 indexing
2 description: "Object that represents an editor token text block (may be multi-line) which is not used in an editor"
3 legal: "See notice at end of class."
4 status: "See notice at end of class."
5 author: ""
6 date: "$Date$"
7 revision: "$Revision$"
8
9 class
10 EB_EDITOR_TOKEN_TEXT
11
12 inherit
13 SHARED_EDITOR_FONT
14
15 EVS_SETTING_CHANGE_ACTIONS
16
17 EB_CONSTANTS
18
19 create
20 default_create,
21 make_from_editor_line
22
23 feature{NONE} -- Initialization
24
25 make_from_editor_line (a_line: EIFFEL_EDITOR_LINE) is
26 -- Initialize `tokens' with `a_line'.
27 require
28 a_line_attached: a_line /= Void
29 do
30 set_tokens (a_line.content)
31 end
32
33 feature -- Token operation
34
35 set_tokens (a_tokens: LIST [EDITOR_TOKEN]) is
36 -- Set `tokens' with `a_tokens'.
37 require
38 a_tokens_attached: a_tokens /= Void
39 local
40 l_tokens: like tokens
41 l_token: EDITOR_TOKEN
42 do
43 lock_update
44 l_tokens := tokens
45 l_tokens.wipe_out
46 from
47 a_tokens.start
48 until
49 a_tokens.after
50 loop
51 l_token := a_tokens.item
52 if l_token /= Void then
53 l_tokens.extend (l_token)
54 end
55 a_tokens.forth
56 end
57 is_position_up_to_date := False
58 is_required_width_up_to_date := False
59 unlock_update
60 try_call_setting_change_actions
61 ensure
62 tokens_set: tokens.count = a_tokens.count
63 end
64
65 feature -- Setting
66
67 enable_text_wrap is
68 -- Enable text wrap.
69 do
70 lock_update
71 is_text_wrap_enabled := True
72 is_position_up_to_date := False
73 unlock_update
74 try_call_setting_change_actions
75 ensure
76 text_wrap_enabled: is_text_wrap_enabled
77 end
78
79 disable_text_wrap is
80 -- disable text wrap.
81 do
82 lock_update
83 is_text_wrap_enabled := False
84 is_position_up_to_date := False
85 unlock_update
86 try_call_setting_change_actions
87 ensure
88 text_wrap_disabled: not is_text_wrap_enabled
89 end
90
91 set_overriden_font (a_font: like overriden_fonts; a_height: INTEGER) is
92 -- Set `overriden_fonts' with `a_font' and the according height in pixel.
93 require
94 a_font_attached: a_font /= Void
95 do
96 lock_update
97 overriden_fonts := a_font
98 is_position_up_to_date := False
99 is_required_width_up_to_date := False
100 set_overriden_line_height (a_height)
101 unlock_update
102 try_call_setting_change_actions
103 ensure
104 overriden_font_set: overriden_fonts = a_font
105 end
106
107 remove_overriden_font is
108 -- Remove `overriden_fonts'.
109 do
110 lock_update
111 overriden_fonts := Void
112 is_position_up_to_date := False
113 is_required_width_up_to_date := False
114 remove_overriden_line_height
115 unlock_update
116 try_call_setting_change_actions
117 ensure
118 overriden_font_removed: overriden_fonts = Void
119 end
120
121 set_overriden_line_height (a_line_height: like overriden_line_height) is
122 -- Set `overriden_line_height' with `a_line_height'.
123 require
124 a_line_height_positive: a_line_height > 0
125 do
126 lock_update
127 overriden_line_height := a_line_height
128 is_overriden_line_height_set := True
129 is_position_up_to_date := False
130 unlock_update
131 try_call_setting_change_actions
132 ensure
133 overriden_line_height_set: overriden_line_height = a_line_height and is_overriden_line_height_set
134 end
135
136 remove_overriden_line_height is
137 -- Remove `overriden_line_height'.
138 do
139 lock_update
140 overriden_line_height := 0
141 is_overriden_line_height_set := False
142 is_position_up_to_date := False
143 unlock_update
144 try_call_setting_change_actions
145 ensure
146 overriden_line_height_removed: overriden_line_height = 0 and not is_overriden_line_height_set
147 end
148
149 set_overriden_selection_colors (a_focus_color, a_unfocus_color: EV_COLOR)
150 -- Set override background colors for selection
151 require
152 a_focus_color_attached: a_focus_color /= Void
153 not_a_focus_color_is_destoryed: not a_focus_color.is_destroyed
154 a_unfocus_color_attached: a_unfocus_color /= Void
155 not_a_unfocus_color_is_destoryed: not a_unfocus_color.is_destroyed
156 do
157 focused_selection_color := a_focus_color
158 unfocused_selection_color := a_unfocus_color
159 ensure
160 focused_selection_color_set: focused_selection_color = a_focus_color
161 unfocused_selection_color_set: unfocused_selection_color = a_unfocus_color
162 end
163
164 remove_overriden_selection_colors
165 -- Removed any set overriden selection background colors
166 do
167 focused_selection_color := Void
168 unfocused_selection_color := Void
169 ensure
170 focused_selection_color_detached: focused_selection_color = Void
171 unfocused_selection_color_detached: unfocused_selection_color = Void
172 end
173
174 set_maximum_width (a_width: INTEGER) is
175 -- Set `maximum_width' with `a_width'.
176 require
177 a_width_positive: a_width > 0
178 do
179 lock_update
180 maximum_width := a_width
181 is_position_up_to_date := False
182 unlock_update
183 try_call_setting_change_actions
184 ensure
185 maximum_width_set: maximum_width = a_width
186 end
187
188 set_maximum_height (a_height: INTEGER) is
189 -- Set `maximum_height' with `a_height'.
190 require
191 a_height_positive: a_height > 0
192 do
193 lock_update
194 maximum_height := a_height
195 is_position_up_to_date := False
196 unlock_update
197 try_call_setting_change_actions
198 ensure
199 maximum_height_set: maximum_height = a_height
200 end
201
202 set_maximum_size (a_width: INTEGER; a_height: INTEGER) is
203 -- Set `maximum_width' with `a_width' and `maximum_height' with `a_height'.
204 require
205 a_width_non_negative: a_width >= 0
206 a_height_non_negative: a_height >= 0
207 do
208 lock_update
209 maximum_width := a_width
210 maximum_height := a_height
211 is_position_up_to_date := False
212 unlock_update
213 try_call_setting_change_actions
214 ensure
215 maximum_width_set: maximum_width = a_width
216 maximum_tooltip_height_set: maximum_height = a_height
217 end
218
219 set_x_offset (a_offset: INTEGER) is
220 -- Set `x_offset' with `a_offset'.
221 do
222 lock_update
223 x_offset := a_offset
224 is_position_up_to_date := False
225 unlock_update
226 try_call_setting_change_actions
227 ensure
228 x_offset_set: x_offset = a_offset
229 end
230
231 set_y_offset (a_offset: INTEGER) is
232 -- Set `y_offset' with `a_offset'.
233 do
234 lock_update
235 y_offset := a_offset
236 is_position_up_to_date := False
237 unlock_update
238 try_call_setting_change_actions
239 ensure
240 y_offset_set: y_offset = a_offset
241 end
242
243 set_x_y_offset (a_x_offset, a_y_offset: INTEGER) is
244 -- Set `x_offset' with `a_x_offset' and `y_offset' with `a_y_offset'.
245 do
246 lock_update
247 x_offset := a_x_offset
248 y_offset := a_y_offset
249 is_position_up_to_date := False
250 unlock_update
251 try_call_setting_change_actions
252 ensure
253 x_offset_set: x_offset = a_x_offset
254 y_offset_set: y_offset = a_y_offset
255 end
256
257 invalidate is
258 -- Invalidate current so position recalculation is forced.
259 do
260 is_position_up_to_date := False
261 ensure
262 not_is_position_up_to_date: not is_position_up_to_date
263 end
264
265 feature -- Status report
266
267 is_overriden_font_set: BOOLEAN is
268 -- Will `overriden_fonts' be used instead of those fonts which are stored in editor tokens?
269 do
270 Result := overriden_fonts /= Void
271 ensure
272 good_result: (Result implies overriden_fonts /= Void) and (not Result implies overriden_fonts = Void)
273 end
274
275 is_overriden_line_height_set: BOOLEAN
276 -- Will `overriden_line_height' be used?
277
278 is_text_wrap_enabled: BOOLEAN
279 -- Is text wrap enabled?
280 -- Has effect if `maximum_width' is set and some lines in `tokens' needs more room than `maximum_width'.
281
282 is_maximum_width_set: BOOLEAN is
283 -- Is `maximum_width' set?
284 do
285 Result := maximum_width > 0
286 ensure
287 good_result: (Result implies maximum_width > 0) and (not Result implies maximum_width = 0)
288 end
289
290 is_maximum_height_set: BOOLEAN is
291 -- Is `maximum_height' set?
292 do
293 Result := maximum_height > 0
294 ensure
295 good_result: (Result implies maximum_height > 0) and (not Result implies maximum_height = 0)
296 end
297
298 is_text_truncated: BOOLEAN
299 -- Was text of current truncated because of lack of space the last time when it is displayed?
300
301 feature -- Display
302
303 display_within_region (x, y, a_width, a_height: INTEGER; a_drawable: EV_DRAWABLE; a_selected_token_index: INTEGER; a_focus: BOOLEAN) is
304 -- Dispaly only `tokens' which intersect with region defined by `x', `y', `a_width' and `a_height' using `a_drawable'.
305 -- `a_selected_token_index' indicates that token should be displayed in its selected status.
306 -- `a_focus' indicates whether `tokens' has focus or not.
307 require
308 a_drawable_attached: a_drawable /= Void
309 local
310 l_tokens: like tokens
311 l_pos: like token_position
312 l_token: EDITOR_TOKEN
313 l_cursor: CURSOR
314 l_pos_cursor: CURSOR
315 l_index: INTEGER
316 l_rec: EV_RECTANGLE
317 l_max_height: INTEGER
318 l_last_available_line: INTEGER
319 l_need_ell: BOOLEAN
320 done: BOOLEAN
321 l_line_height: INTEGER
322 do
323 if not is_position_up_to_date then
324 update_position
325 end
326 l_tokens := adapted_tokens
327 if not l_tokens.is_empty then
328 l_pos := token_position
329 l_cursor := l_tokens.cursor
330 l_pos_cursor := l_pos.cursor
331 l_line_height := actual_line_height
332 if is_maximum_height_set then
333 l_max_height := maximum_height
334 l_last_available_line := maximum_height - l_line_height
335 from
336 l_pos.finish
337 until
338 l_pos.before or l_need_ell
339 loop
340 if l_pos.item.y > l_last_available_line then
341 l_need_ell := True
342 end
343 l_pos.back
344 end
345 end
346 create l_rec.make (x, y, a_width, a_height)
347 from
348 l_tokens.start
349 l_pos.start
350 l_index := 1
351 until
352 l_tokens.after or done
353 loop
354 l_token := l_tokens.item
355 if l_pos.item.intersects (l_rec) then
356 if l_need_ell then
357 if l_pos.item.y + l_line_height > l_last_available_line then
358 display_token (l_pos.item.x, l_pos.item.y, create{EDITOR_TOKEN_TEXT}.make ("..."), a_drawable)
359 done := True
360 end
361 end
362 if not done then
363 if l_index = a_selected_token_index then
364 display_selected_token (l_pos.item.x, l_pos.item.y, l_token, a_focus, a_drawable)
365 else
366 display_token (l_pos.item.x, l_pos.item.y, l_token, a_drawable)
367 end
368 end
369 end
370 l_index := l_index + 1
371 l_tokens.forth
372 l_pos.forth
373 end
374 l_tokens.go_to (l_cursor)
375 l_pos.go_to (l_pos_cursor)
376 end
377 end
378
379 display (x, y: INTEGER; a_drawable: EV_DRAWABLE; a_selected_token_index: INTEGER; a_focus: BOOLEAN) is
380 -- Display `tokens' at position (x, y) using `a_drawable'.
381 -- `a_selected_token_index' indicates that token should be displayed in its selected status.
382 -- `a_focus' indicates whether `tokens' has focus or not.
383 require
384 a_drawable_attached: a_drawable /= Void
385 a_selected_token_index_non_negative: a_selected_token_index >= 0
386 local
387 l_tokens: like tokens
388 l_pos: like token_position
389 l_token: EDITOR_TOKEN
390 l_cursor: CURSOR
391 l_pos_cursor: CURSOR
392 l_index: INTEGER
393 do
394 if not is_position_up_to_date then
395 update_position
396 end
397 l_tokens := adapted_tokens
398 if not l_tokens.is_empty then
399 l_pos := token_position
400 l_cursor := l_tokens.cursor
401 l_pos_cursor := l_pos.cursor
402 from
403 l_tokens.start
404 l_pos.start
405 l_index := 1
406 until
407 l_tokens.after
408 loop
409 l_token := l_tokens.item
410 if a_selected_token_index < 0 or l_index = a_selected_token_index then
411 display_selected_token (x + l_pos.item.x, y + l_pos.item.y, l_token, a_focus, a_drawable)
412 else
413 display_token (x + l_pos.item.x, y + l_pos.item.y, l_token, a_drawable)
414 end
415 l_index := l_index + 1
416 l_tokens.forth
417 l_pos.forth
418 end
419 l_tokens.go_to (l_cursor)
420 l_pos.go_to (l_pos_cursor)
421 end
422 end
423
424 display_selected (x, y: INTEGER; a_drawable: EV_DRAWABLE; a_focus: BOOLEAN) is
425 -- Display `tokens' at position (x, y) using `a_drawable' in selected mode.
426 -- `a_selected_token_index' indicates that token should be displayed in its selected status.
427 -- `a_focus' indicates whether `tokens' has focus or not.
428 require
429 a_drawable_attached: a_drawable /= Void
430 local
431 l_tokens: like tokens
432 l_pos: like token_position
433 l_token: EDITOR_TOKEN
434 l_cursor: CURSOR
435 l_pos_cursor: CURSOR
436 l_index: INTEGER
437 do
438 if not is_position_up_to_date then
439 update_position
440 end
441 l_tokens := adapted_tokens
442 if not l_tokens.is_empty then
443 l_pos := token_position
444 l_cursor := l_tokens.cursor
445 l_pos_cursor := l_pos.cursor
446 from
447 l_tokens.start
448 l_pos.start
449 l_index := 1
450 until
451 l_tokens.after
452 loop
453 l_token := l_tokens.item
454 display_selected_token (x + l_pos.item.x, y + l_pos.item.y, l_token, a_focus, a_drawable)
455 l_index := l_index + 1
456 l_tokens.forth
457 l_pos.forth
458 end
459 l_tokens.go_to (l_cursor)
460 l_pos.go_to (l_pos_cursor)
461 end
462 end
463
464 feature -- Position status
465
466 is_position_up_to_date: BOOLEAN
467 -- Is `token_position' update to date?
468
469 is_required_width_up_to_date: BOOLEAN
470 -- Is `required_width' up to date?
471
472 feature -- Measure
473
474 maximum_width: INTEGER
475 -- Maximum width in pixel of `tokens'
476 -- Default value is 0, meaning maximum width is not set, `tokens' will be displayed
477 -- in actually required width.
478
479 maximum_height: INTEGER
480 -- Maxiumu height in pixel of `tokens'
481 -- Default value is 0, meaning maximum height is not set, `tokens' will be displayed
482 -- in actually required height.
483
484 x_offset: INTEGER
485 -- X offset in pixel to display `tokens'
486
487 y_offset: INTEGER
488 -- Y offset in pixel to display `tokens'
489
490 feature -- Access
491
492 overriden_fonts: SPECIAL [EV_FONT]
493 -- Overriden fonts.
494 -- If it's Void, default fonts which are defined in editor tokens will be used to display tokens.
495 -- If it's not Void, given an editor token `a_token', font at position `a_token.font_id' will be used
496 -- to display that token.
497
498 overriden_line_height: INTEGER
499 -- Line height in pixel
500
501 focused_selection_color: EV_COLOR
502 -- Overriden focused selection color
503
504 unfocused_selection_color: EV_COLOR
505 -- Overriden unfocused selection color
506
507 tokens: LINKED_LIST [EDITOR_TOKEN] is
508 -- `tokens' stored in list
509 do
510 if internal_tokens = Void then
511 create internal_tokens.make
512 end
513 Result := internal_tokens
514 ensure
515 result_attached: Result /= Void
516 end
517
518 token_position: LINKED_LIST [EV_RECTANGLE] is
519 -- Position information of every token in `tokens'
520 do
521 if internal_token_position = Void then
522 create internal_token_position.make
523 end
524 Result := internal_token_position
525 ensure
526 result_attached: Result /= Void
527 end
528
529 string_representation: STRING is
530 -- String representation of current
531 local
532 l_cursor: CURSOR
533 l_tokens: like tokens
534 l_eol: EDITOR_TOKEN_EOL
535 do
536 l_tokens := tokens
537 l_cursor := l_tokens.cursor
538 create Result.make (20)
539 from
540 l_tokens.start
541 until
542 l_tokens.after
543 loop
544 l_eol ?= l_tokens.item
545 if l_eol = Void then
546 Result.append (l_tokens.item.image)
547 else
548 Result.append_character ('%N')
549 end
550 l_tokens.forth
551 end
552 if l_cursor /= Void then
553 l_tokens.go_to (l_cursor)
554 end
555 ensure
556 result_attached: Result /= Void
557 end
558
559 feature -- Measure
560
561 actual_line_height: INTEGER is
562 -- Actual line height
563 -- It takes both `line_height' and `overriden_line_height' into account.
564 do
565 if is_overriden_line_height_set then
566 Result := overriden_line_height
567 else
568 Result := line_height
569 end
570 ensure
571 good_result:
572 (is_overriden_line_height_set implies Result = overriden_line_height) and
573 (not is_overriden_line_height_set implies Result = line_height)
574 end
575
576 required_width: INTEGER is
577 -- Required width in pixel to fully display `tokens'
578 require
579 tokens_attached: tokens /= Void
580 local
581 l_cur_line_width: INTEGER
582 l_max_line_width: INTEGER
583 l_cursor: CURSOR
584 l_tokens: like tokens
585 l_token: EDITOR_TOKEN
586 do
587 if not is_required_width_up_to_date then
588 l_tokens := tokens
589 if not l_tokens.is_empty then
590 l_cursor := l_tokens.cursor
591 from
592 l_tokens.start
593 until
594 l_tokens.after
595 loop
596 l_token := l_tokens.item
597 if l_token.is_new_line then
598 if l_cur_line_width > l_max_line_width then
599 l_max_line_width := l_cur_line_width
600 end
601 l_cur_line_width := 0
602 else
603 l_cur_line_width := l_cur_line_width + token_width (l_token, l_token.image)
604 end
605 l_tokens.forth
606 end
607 if l_cur_line_width > l_max_line_width then
608 l_max_line_width := l_cur_line_width
609 end
610 internal_required_width := l_max_line_width
611 is_required_width_up_to_date := True
612 end
613 end
614 Result := internal_required_width
615 end
616
617 required_height: INTEGER is
618 -- Required width in pixel to fully display `tokens'
619 require
620 tokens_attached: tokens /= Void
621 local
622 l_tokens: like tokens
623 l_token: EDITOR_TOKEN
624 l_cursor: CURSOR
625 x, y: INTEGER
626 l_wrapped: BOOLEAN
627 l_width: INTEGER
628 l_line_height: INTEGER
629 l_token_in_current_line: INTEGER
630 l_is_max_width_set: BOOLEAN
631 l_is_text_wrapped: BOOLEAN
632 l_max_width: INTEGER
633 l_should_go_forward: BOOLEAN
634 do
635 l_tokens := tokens
636 if not l_tokens.is_empty then
637 l_cursor := l_tokens.cursor
638 l_wrapped := is_text_wrap_enabled
639 l_line_height := actual_line_height
640 l_is_max_width_set := is_maximum_width_set
641 l_is_text_wrapped := is_text_wrap_enabled
642 l_max_width := maximum_width
643 from
644 x := x_offset
645 y := y_offset
646 l_tokens.start
647 l_token_in_current_line := 0
648 until
649 l_tokens.after
650 loop
651 l_token := l_tokens.item
652 l_width := token_width (l_token, l_token.image)
653 if l_token.is_new_line or else (l_is_max_width_set and then x + l_width > l_max_width and then l_wrapped) then
654 x := 0
655 y := y + l_line_height
656 l_should_go_forward := l_token.is_new_line or else l_token_in_current_line = 0
657 l_token_in_current_line := 0
658 else
659 x := x + l_width
660 l_token_in_current_line := l_token_in_current_line + 1
661 l_should_go_forward := True
662 end
663 if l_should_go_forward then
664 l_tokens.forth
665 end
666 end
667 l_tokens.go_to (l_cursor)
668 end
669 Result := y
670 if l_token_in_current_line > 0 then
671 Result := Result + l_line_height
672 end
673 end
674
675 token_index_at_position (x, y: INTEGER): INTEGER is
676 -- Index of item in `tokens' whose region contains position (x, y)
677 -- 0 if no item in `tokens' satisfies this condition.
678 local
679 l_pos: like token_position
680 l_cursor: CURSOR
681 done: BOOLEAN
682 do
683 if not is_position_up_to_date then
684 update_position
685 end
686 l_pos := token_position
687 l_cursor := l_pos.cursor
688 from
689 l_pos.start
690 until
691 l_pos.after or done
692 loop
693 if l_pos.item.has_x_y (x, y) then
694 Result := l_pos.index
695 done := True
696 end
697 l_pos.forth
698 end
699 l_pos.go_to (l_cursor)
700 ensure
701 result_non_negative: Result >= 0
702 result_correct: Result > 0 implies (Result <= token_position.count and then token_position.i_th (Result).has_x_y (x, y))
703 end
704
705 pebble (a_index: INTEGER): ANY is
706 -- Pebble of item at position `a_index'.
707 do
708 if a_index >= 1 and a_index <= adapted_tokens.count then
709 Result := adapted_tokens.i_th (a_index).pebble
710 end
711 end
712
713 feature{NONE} -- Display
714
715 display_token (x, y: INTEGER; a_token: EDITOR_TOKEN; a_drawable: EV_DRAWABLE) is
716 -- Display `a_token' at position (x, y) using `a_drawable'.
717 require
718 a_token_attached: a_token /= Void
719 a_drawable_attached: a_drawable /= Void
720 do
721 a_drawable.set_font (actual_token_font (a_token))
722 a_drawable.set_foreground_color (a_token.text_color)
723 a_drawable.draw_text_top_left (x, y, a_token.image)
724 end
725
726 display_selected_token (x, y: INTEGER; a_token: EDITOR_TOKEN; a_focus: BOOLEAN; a_drawable: EV_DRAWABLE) is
727 -- Display `a_token' at position (x, y) in its selected state.
728 -- `a_focus' indicates whether `a_token' has focus or not.
729 require
730 a_token_attached: a_token /= Void
731 a_drawable_attached: a_drawable /= Void
732 local
733 l_font: EV_FONT
734 l_color: EV_COLOR
735 do
736 if a_focus then
737 l_color := focused_selection_color
738 if l_color = Void then
739 a_drawable.set_background_color (a_token.selected_background_color)
740 else
741 a_drawable.set_background_color (l_color)
742 end
743 a_drawable.set_foreground_color (a_token.selected_text_color)
744 else
745 l_color := unfocused_selection_color
746 if l_color = Void then
747 a_drawable.set_background_color (a_token.focus_out_selected_background_color)
748 else
749 a_drawable.set_background_color (l_color)
750 end
751 a_drawable.set_foreground_color (a_token.text_color)
752 end
753 l_font := actual_token_font (a_token)
754 a_drawable.set_font (l_font)
755 a_drawable.clear_rectangle (x, y, l_font.string_width (a_token.image), actual_line_height)--l_font.height)
756 a_drawable.draw_text_top_left (x, y, a_token.image)
757 end
758
759 feature{NONE} -- Implementation
760
761 actual_token_font (a_token: EDITOR_TOKEN): EV_FONT is
762 -- Actual used font for `a_token'.
763 -- Will take `overriden_fonts' into account.
764 require
765 a_token_attached: a_token /= Void
766 overriden_font_valid: is_overriden_font_set implies (a_token.font_id >=0 and then a_token.font_id < overriden_fonts.count and then overriden_fonts.item (a_token.font_id) /= Void)
767 do
768 if is_overriden_font_set then
769 check
770 a_token.font_id >= 0
771 a_token.font_id < overriden_fonts.count
772 overriden_fonts.item (a_token.font_id) /= Void
773 end
774 Result := overriden_fonts.item (a_token.font_id)
775 else
776 Result := a_token.font
777 end
778 ensure
779 result_set:
780 (is_overriden_font_set implies Result = overriden_fonts.item (a_token.font_id)) and
781 (not is_overriden_font_set implies Result = a_token.font)
782 end
783
784 internal_tokens: like tokens
785 -- Internal tokens
786
787 internal_token_position: like token_position
788 -- Internal token position list
789
790 internal_required_width: INTEGER
791 -- Internal `required_width'
792
793 adapted_tokens: like tokens is
794 -- Adapted tokesn for ellipsis display
795 do
796 if adapted_tokens_internal = Void then
797 create adapted_tokens_internal.make
798 end
799 Result := adapted_tokens_internal
800 ensure
801 result_attached: Result /= Void
802 end
803
804 adapted_tokens_internal: like adapted_tokens
805 -- Implementation of `adapted_tokens'
806
807 update_position is
808 -- Update width information and relative position in every token in `tokens'.
809 local
810 l_tokens: like tokens
811 l_adapted_tokens: like adapted_tokens
812 l_position: like token_position
813 l_cursor: CURSOR
814 x, y: INTEGER
815 l_is_max_width_set: BOOLEAN
816 l_is_max_height_set: BOOLEAN
817 l_max_width: INTEGER
818 l_max_height: INTEGER
819 l_is_text_wrap_enabled: BOOLEAN
820 l_line_height: INTEGER
821 l_width_left: INTEGER
822 l_token: EDITOR_TOKEN
823 l_ellipsis_width: INTEGER
824 l_width: INTEGER
825 l_token_in_current_line: INTEGER
826 l_should_go_forward: BOOLEAN
827 l_done: BOOLEAN
828 l_split_token: EDITOR_TOKEN
829 l_split_token_pos: EV_RECTANGLE
830 l_splited: TUPLE [a_splited_token: EDITOR_TOKEN; a_splited_token_position: EV_RECTANGLE; a_ellipsis_position: EV_RECTANGLE]
831 l_finished: BOOLEAN
832 l_ell_pos: EV_RECTANGLE
833 l_x_offset: INTEGER
834 l_ellipsis_token: like ellipsis_token
835 do
836 l_tokens := tokens
837 is_text_truncated := False
838 if not l_tokens.is_empty then
839 -- Clean tokens calculated before.
840 l_adapted_tokens := adapted_tokens
841 l_adapted_tokens.wipe_out
842
843 -- Clean positions calculated before.
844 l_position := token_position
845 l_position.wipe_out
846
847 -- Flags setup.
848 l_ellipsis_token := ellipsis_token
849 l_ellipsis_width := token_width (l_ellipsis_token, l_ellipsis_token.image)
850 l_is_text_wrap_enabled := is_text_wrap_enabled
851 l_line_height := actual_line_height
852 l_is_max_width_set := is_maximum_width_set
853 l_is_max_height_set := is_maximum_height_set
854 l_x_offset := x_offset
855 if l_is_max_height_set then
856 l_max_height := maximum_height
857 end
858 if l_is_max_width_set then
859 l_max_width := maximum_width
860 end
861 l_is_text_wrap_enabled := is_text_wrap_enabled
862
863 -- Update positions.
864 l_cursor := l_tokens.cursor
865 from
866 x := l_x_offset
867 y := y_offset
868 l_width_left := l_max_width - l_x_offset
869 l_tokens.start
870 l_should_go_forward := False
871 until
872 l_tokens.after or l_finished
873 loop
874 l_token := l_tokens.item
875 l_width := token_width (l_token, l_token.image)
876
877 if is_maximum_width_set and then l_width > l_width_left then
878 is_text_truncated := True
879 check not l_token.is_new_line end
880 if
881 l_is_text_wrap_enabled and then
882 (l_token_in_current_line > 0 and then (l_is_max_height_set implies ((y + 2 * l_line_height) <= l_max_height)))
883 then
884 -- Place current token `l_token' in a new line.
885 y := y + l_line_height
886 x := l_x_offset
887 l_token_in_current_line := 0
888 l_width_left := l_max_width - l_x_offset
889
890 -- Because current token `l_token' has not been positioned, we dont' step forward.
891 l_should_go_forward := False
892 else
893 -- Current token `l_token' must be placed in current line.
894 if x + l_ellipsis_width > l_max_width and then l_token_in_current_line > 0 then
895 -- If there is not enough space for display any part of current token plus ellipsis,
896 -- we search backward to find a token to adapt.
897 from
898 l_position.finish
899 l_adapted_tokens.finish
900 l_done := False
901 until
902 l_done or else l_position.before
903 loop
904 l_split_token_pos := l_position.item
905 if l_position.item.x + l_ellipsis_width <= l_max_width or else l_position.item.x = 0 then
906 -- We found the token which will be splited.
907 l_split_token := l_adapted_tokens.item
908 l_done := True
909 end
910 l_position.back
911 l_adapted_tokens.back
912 l_adapted_tokens.remove_right
913 l_position.remove_right
914 end
915 else
916 -- If left space is enough for display part of current token and ellipsis, or current token
917 -- is the only token in that line, we just chop current token apart and display ellipsis after the left part.
918 l_split_token := l_token
919 create l_split_token_pos.make (x, y, l_width, l_line_height)
920 end
921 -- Insert splited token and ellipsis.
922 l_splited := splited_token_with_ellipsis (l_split_token, l_split_token_pos, l_max_width)
923 l_ell_pos := l_splited.a_ellipsis_position
924 if l_splited.a_splited_token /= Void then
925 l_adapted_tokens.extend (l_splited.a_splited_token)
926 l_position.extend (l_splited.a_splited_token_position)
927 end
928 l_adapted_tokens.extend (ellipsis_token)
929 l_position.extend (l_ell_pos)
930 if l_is_text_wrap_enabled and then (l_is_max_height_set implies (y + 2 * l_line_height <= l_max_height)) then
931 x := l_x_offset
932 y := y + l_line_height
933 l_token_in_current_line := 0
934 l_width_left := l_max_width - l_x_offset
935 else
936 x := x + l_ell_pos.x + l_ell_pos.width - 1
937 l_finished := not (l_is_max_height_set implies (y + 2 * l_line_height <= l_max_height))
938 end
939 l_should_go_forward := True
940 end
941 else
942 l_adapted_tokens.extend (l_token)
943 l_position.extend (create {EV_RECTANGLE}.make (x, y, l_width, l_line_height))
944 l_should_go_forward := True
945 if l_token.is_new_line then
946 if l_is_max_height_set implies (y + 2 * l_line_height <= l_max_height) then
947 x := l_x_offset
948 y := y + l_line_height
949 l_token_in_current_line := 0
950 l_width_left := l_max_width - l_x_offset
951 else
952 l_finished := True
953 end
954 else
955 x := x + l_width
956 l_width_left := l_width_left - l_width
957 l_token_in_current_line := l_token_in_current_line + 1
958 end
959 end
960 if l_should_go_forward then
961 l_tokens.forth
962 end
963 end
964 l_tokens.go_to (l_cursor)
965 end
966 is_position_up_to_date := True
967 ensure
968 position_is_up_to_date: is_position_up_to_date
969 data_valid: token_position.count = adapted_tokens.count
970 end
971
972 splited_token_with_ellipsis (a_token: EDITOR_TOKEN; a_position: EV_RECTANGLE; a_max_width: INTEGER): TUPLE [splited_token: EDITOR_TOKEN; splited_token_position: EV_RECTANGLE; ellipsis_token_positon: EV_RECTANGLE] is
973 -- Split `a_token' into former part and latter part, and remove the latter part
974 -- so there is enough space to display ellipsis "..." after the former part
975 -- according to position `a_position' for `a_token' and max width allowed `a_max_width'.
976 -- Return the former part in `splited_token', its position in `splited_token_position',
977 -- and position for ellipsis in `ellipsis_token_positon'.
978 require
979 a_token_attached: a_token /= Void
980 a_position_attached: a_position /= Void
981 local
982 l_editor_token: EDITOR_TOKEN_TEXT
983 l_splited_token_position: EV_RECTANGLE
984 l_ellipsis_position: EV_RECTANGLE
985 l_image: STRING
986 l_min_count: INTEGER
987 l_image_count: INTEGER
988 l_start_x: INTEGER
989 l_ellipsis_width: INTEGER
990 l_line_height: INTEGER
991 l_x_offset: INTEGER
992 l_token_width: INTEGER
993 l_ellipsis_token: like ellipsis_token
994 do
995 l_editor_token ?= a_token.twin
996 l_start_x := a_position.x
997 l_line_height := actual_line_height
998 l_ellipsis_token := ellipsis_token
999 l_ellipsis_width := token_width (l_ellipsis_token, l_ellipsis_token.image)
1000 if l_editor_token /= Void and then not l_editor_token.image.is_empty then
1001 -- For text editor token
1002 from
1003 l_x_offset := x_offset
1004 l_image := l_editor_token.image.twin
1005 l_image_count := l_image.count
1006 if a_position.x = l_x_offset then
1007 l_min_count := 1
1008 end
1009 l_token_width := token_width (l_editor_token, l_image)
1010 until
1011 l_image_count = l_min_count or else l_start_x + l_token_width + l_ellipsis_width <= a_max_width
1012 loop
1013 l_image_count := l_image_count - 1
1014 l_image.keep_head (l_image_count)
1015 l_token_width := token_width (l_editor_token, l_image)
1016 end
1017 l_editor_token.set_image (l_image)
1018 create l_splited_token_position.make (l_start_x, a_position.y, l_token_width, l_line_height)
1019 create l_ellipsis_position.make (l_start_x + l_token_width, a_position.y, l_ellipsis_width, l_line_height)
1020 else
1021 l_editor_token := Void
1022 create l_ellipsis_position.make (l_start_x, a_position.y, l_ellipsis_width, l_line_height)
1023 end
1024 Result := [l_editor_token, l_splited_token_position, l_ellipsis_position]
1025 ensure
1026 result_attached: Result /= Void
1027 result_valid: (Result.splited_token /= Void implies Result.splited_token_position /= Void) and then
1028 (Result.splited_token = Void implies Result.splited_token_position = Void) and then
1029 (Result.ellipsis_token_positon /= Void)
1030 end
1031
1032 ellipsis_token: EDITOR_TOKEN_SYMBOL is
1033 -- Editor token for "..."
1034 do
1035 create Result.make (interface_names.l_ellipsis)
1036 ensure
1037 result_attached: Result /= Void
1038 end
1039
1040 token_width (a_token: EDITOR_TOKEN; a_image: STRING): INTEGER
1041 -- Width in pixel of `a_image' using font in `a_token' or `overriden_fonts' if `is_overriden_font_set'.
1042 require
1043 a_token_attached: a_token /= Void
1044 a_image_attached: a_image /= Void
1045 do
1046 if is_overriden_font_set then
1047 check
1048 a_token.font_id >= 0
1049 a_token.font_id < overriden_fonts.count
1050 overriden_fonts.item (a_token.font_id) /= Void
1051 end
1052 Result := overriden_fonts.item (a_token.font_id).string_width (a_image)
1053 else
1054 Result := a_token.font.string_width (a_image)
1055 end
1056 end
1057
1058 indexing
1059 copyright: "Copyright (c) 1984-2006, Eiffel Software"
1060 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1061 licensing_options: "http://www.eiffel.com/licensing"
1062 copying: "[
1063 This file is part of Eiffel Software's Eiffel Development Environment.
1064
1065 Eiffel Software's Eiffel Development Environment is free
1066 software; you can redistribute it and/or modify it under
1067 the terms of the GNU General Public License as published
1068 by the Free Software Foundation, version 2 of the License
1069 (available at the URL listed under "license" above).
1070
1071 Eiffel Software's Eiffel Development Environment is
1072 distributed in the hope that it will be useful, but
1073 WITHOUT ANY WARRANTY; without even the implied warranty
1074 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1075 See the GNU General Public License for more details.
1076
1077 You should have received a copy of the GNU General Public
1078 License along with Eiffel Software's Eiffel Development
1079 Environment; if not, write to the Free Software Foundation,
1080 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1081 ]"
1082 source: "[
1083 Eiffel Software
1084 356 Storke Road, Goleta, CA 93117 USA
1085 Telephone 805-685-1006, Fax 805-685-6869
1086 Website http://www.eiffel.com
1087 Customer support http://support.eiffel.com
1088 ]"
1089
1090 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23