/[eiffelstudio]/trunk/Src/Eiffel/interface/graphical/tools/event_list_service/common/es_event_list_tool_panel_base.e
ViewVC logotype

Contents of /trunk/Src/Eiffel/interface/graphical/tools/event_list_service/common/es_event_list_tool_panel_base.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: 33202 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 : "[
3 An EiffelStudio base implementation for all tools implementing a derviation of an event list tool. The tool is based on the
4 ecosystem event list service {EVENT_LIST_S}.
5 ]"
6 legal: "See notice at end of class."
7 status: "See notice at end of class."
8 date : "$Date$"
9 revision : "$Revision$"
10 author : "Arnaud PICHERY [ aranud@mail.dotcom.fr ]"
11
12 deferred class
13 ES_EVENT_LIST_TOOL_PANEL_BASE
14
15 inherit
16 ES_DOCKABLE_TOOL_PANEL [ES_GRID]
17 rename
18 user_widget as grid_events
19 redefine
20 on_before_initialize,
21 on_after_initialized,
22 internal_recycle
23 end
24
25 feature {NONE} -- Initialization
26
27 on_before_initialize
28 -- Use to perform additional creation initializations, before the UI has been created.
29 local
30 l_service: EVENT_LIST_S
31 do
32 Precursor {ES_DOCKABLE_TOOL_PANEL}
33
34 -- Retrieve event list service
35 if event_list.is_service_available then
36 l_service := event_list.service
37 l_service.item_added_events.subscribe (agent on_event_added)
38 l_service.item_changed_events.subscribe (agent on_event_changed)
39 l_service.item_removed_events.subscribe (agent on_event_removed)
40 end
41 end
42
43 on_after_initialized
44 -- Use to perform additional creation initializations, after the UI has been created.
45 do
46 Precursor {ES_DOCKABLE_TOOL_PANEL}
47 if not surpress_synchronization then
48 synchronize_event_list_items
49 end
50 update_content_applicable_widgets (item_count > 0)
51 end
52
53 feature {NONE} -- Clean up
54
55 internal_recycle
56 -- Recycle tool.
57 local
58 l_agent: PROCEDURE [ANY, TUPLE [service: EVENT_LIST_S; event_item: EVENT_LIST_ITEM_I]]
59 l_service: EVENT_LIST_S
60 do
61 if event_list.is_service_available then
62 l_service := event_list.service
63
64 l_agent := agent on_event_added
65 if l_service.item_added_events.is_subscribed (l_agent) then
66 l_service.item_added_events.unsubscribe (l_agent)
67 end
68 l_agent := agent on_event_removed
69 if l_service.item_removed_events.is_subscribed (l_agent) then
70 l_service.item_removed_events.unsubscribe (l_agent)
71 end
72 l_agent := agent on_event_changed
73 if l_service.item_changed_events.is_subscribed (l_agent) then
74 l_service.item_changed_events.unsubscribe (l_agent)
75 end
76 end
77 internal_grid_wrapper := Void
78
79 Precursor {ES_DOCKABLE_TOOL_PANEL}
80 ensure then
81 internal_grid_wrapper_deatched: internal_grid_wrapper = Void
82 end
83
84 feature {NONE} -- Access
85
86 frozen item_count: NATURAL
87 -- Number of items currently managed by the list
88
89 maximum_item_count: NATURAL
90 -- Maximum number of items displayable by the list.
91 -- Note: Use 0 to indicate no maximum.
92 do
93 Result := 0
94 end
95
96 frozen grid_wrapper: EVS_GRID_WRAPPER [EV_GRID_ROW]
97 -- A grid helper class
98 do
99 Result := internal_grid_wrapper
100 if Result = Void then
101 create Result.make (grid_events)
102 internal_grid_wrapper := Result
103 auto_recycle (internal_grid_wrapper)
104 end
105 ensure
106 result_attached: Result /= Void
107 result_consistent: Result = Result
108 end
109
110 feature {NONE} -- Helpers
111
112 frozen event_list: SERVICE_CONSUMER [EVENT_LIST_S]
113 -- Access to an event list service {EVENT_LIST_S} consumer
114 once
115 create Result
116 ensure
117 result_attached: Result /= Void
118 end
119
120 feature -- Status report
121
122 scroll_list_automatically: BOOLEAN
123 -- Indicates if the list should automatically scroll to
124 -- the last item when a new item is added.
125 local
126 l_grid: like grid_events
127 do
128 Result := maximum_item_count = 0
129 if Result then
130 -- Permits automatic scrolling if the user did not scroll the last added
131 -- item out of view.
132 l_grid := grid_events
133 Result := l_grid.row_count = 0 or else
134 (l_grid.is_displayed and then l_grid.last_visible_row = l_grid.row (l_grid.row_count))
135 end
136 end
137
138 destory_old_items_automatically: BOOLEAN
139 -- Indicates if old event items should be destroyed automatically in a FIFO fashion.
140 do
141 Result := maximum_item_count > 0
142 end
143
144 surpress_synchronization: BOOLEAN
145 -- State to indicate if synchonization with the event list service should be suppressed
146 -- when initializing.
147 do
148 -- By default for list that destory items automatically
149 -- there will be not synchronization, because the will typically be logging tools.
150 Result := destory_old_items_automatically
151 end
152
153 feature {NONE} -- Basic operations
154
155 find_event_row (a_event_item: EVENT_LIST_ITEM_I): EV_GRID_ROW
156 -- Attempts to locate a grid row for event `a_event_item'
157 require
158 a_event_attached: a_event_item /= Void
159 a_event_is_appliable_event: is_appliable_event (a_event_item)
160 local
161 l_grid: like grid_events
162 l_row: EV_GRID_ROW
163 l_count, i: INTEGER
164 do
165 l_grid := grid_events
166 from
167 i := 1
168 l_count := l_grid.row_count
169 until
170 i > l_count or Result /= Void
171 loop
172 l_row := l_grid.row (i)
173 if l_row.data = a_event_item then
174 Result := l_row
175 else
176 i := i + 1
177 end
178 end
179 end
180
181 do_default_action (a_row: EV_GRID_ROW) is
182 -- Performs a default actions for a given row.
183 --
184 -- `a_row': The row the user requested an action to be performed on.
185 require
186 a_row_attached: a_row /= Void
187 a_row_has_parent: a_row.parent /= Void
188 a_row_is_in_grid_events: a_row.index <= grid_events.row_count and then
189 grid_events.row (a_row.index) = a_row
190 deferred
191 end
192
193 selected_text: STRING_8
194 -- Retrieves selected row's text
195 local
196 l_grid: like grid_events
197 l_rows: LIST [EV_GRID_ROW]
198 l_items: LIST [EV_GRID_ITEM]
199 l_text: STRING_8
200 do
201 create Result.make_empty
202 l_grid := grid_events
203 if l_grid.is_multiple_row_selection_enabled or l_grid.is_single_row_selection_enabled then
204 l_rows := l_grid.selected_rows
205 if not l_rows.is_empty then
206 from l_rows.start until l_rows.after loop
207 l_text := row_text (l_rows.item)
208 if not l_text.is_empty then
209 Result.append (l_text)
210 Result.append_character ('%N')
211 end
212 l_rows.forth
213 end
214 Result.prune_all_trailing ('%N')
215 end
216 else
217 l_items := l_grid.selected_items
218 if not l_items.is_empty then
219 from l_items.start until l_items.after loop
220 l_text := row_item_text (l_items.item)
221 if not l_text.is_empty then
222 Result.append (l_text)
223 Result.append_character ('%T')
224 end
225 l_items.forth
226 end
227 end
228 end
229 ensure
230 result_attached: Result /= Void
231 end
232
233 synchronize_event_list_items
234 -- Synchronized the event list items already pushed to the service before the tool was shown
235 require
236 is_initialized: is_initialized
237 not_surpress_synchronization: not surpress_synchronization
238 do
239 if event_list.is_service_available then
240 event_list.service.all_items.do_all (agent on_event_added (event_list.service, ?))
241 end
242 end
243
244 feature {NONE} -- Navigation
245
246 move_next (a_query_action: FUNCTION [ANY, TUPLE [EVENT_LIST_ITEM_I], BOOLEAN])
247 -- Moves to the next item in the errors and warnings list based on some fundamental conditions.
248 --
249 -- `a_query_function': The function to determine if a matched event list item is applicable.
250 require
251 a_query_action_attached: a_query_action /= Void
252 local
253 l_grid: like grid_events
254 l_row_count: INTEGER
255 l_index: INTEGER
256 l_stop_index: INTEGER
257 l_row: EV_GRID_ROW
258 l_item: EVENT_LIST_ITEM_I
259 l_found: BOOLEAN
260 l_valid_rows: BOOLEAN
261 do
262 l_grid := grid_events
263 l_row_count := l_grid.row_count
264 if l_row_count > 0 then
265 -- Check there are visible and selectable items
266 l_valid_rows := False
267 from l_index := 1 until l_index >= l_row_count or l_valid_rows loop
268 l_row := l_grid.row (l_index)
269 l_valid_rows := l_row.is_show_requested and l_row.is_selectable
270 l_index := l_index + l_row.subrow_count_recursive + 1
271 end
272
273 if l_valid_rows then
274 -- There are selectable rows
275 if l_grid.selected_rows.is_empty then
276 -- Fetch last row's root row
277 l_row := l_grid.row (l_row_count)
278 if l_row.parent_row /= Void then
279 l_row := l_row.parent_row_root
280 end
281 else
282 -- Fetch selected row's root row (as child may be selected)
283 l_row := l_grid.selected_rows.last
284 if l_row.parent_row /= Void then
285 l_row := l_row.parent_row_root
286 end
287 end
288
289 -- Ensure row is visible
290 if not l_row.is_show_requested and l_row.is_selectable then
291 -- Located row is not shown, find previous shown row
292 l_stop_index := l_row.index
293 from until l_row.is_show_requested and l_row.is_selectable loop
294 l_index := l_row.index + l_row.subrow_count_recursive + 1
295 if l_index = l_row_count then
296 l_index := 1
297 end
298 l_row := l_grid.row (l_index)
299 end
300 end
301
302 -- Set selected index and stop-index
303 l_index := l_row.index
304 l_stop_index := l_index
305 check
306 l_stop_index_is_root_row: l_grid.row (l_index).parent_row = Void
307 end
308
309 -- Shift index
310 l_index := l_index + l_row.subrow_count_recursive + 1
311 if l_index > l_row_count then
312 -- Cycle index
313 l_index := 1
314 end
315
316 -- Iterate through the rows forwards
317 from
318 l_row := Void
319 until
320 l_found or
321 l_index = l_stop_index
322 loop
323 l_found := False
324
325 l_row := l_grid.row (l_index)
326 check
327 l_row_is_root: l_row.parent_row_root = Void or l_row.parent_row_root = l_row
328 end
329 if l_row.is_show_requested and l_row.is_selectable then
330 l_item ?= l_row.data
331 l_found := l_item /= Void and then a_query_action.item ([l_item])
332 end
333
334 if not l_found then
335 -- Increment index
336 l_index := l_index + l_row.subrow_count_recursive + 1
337 if l_index > l_row_count then
338 -- Cycle, if requested
339 l_index := 1
340 end
341
342 -- Retrieve index of root row
343 l_row := l_grid.row (l_index)
344 end
345 end
346
347 if not l_found and then l_stop_index > 0 then
348 -- The stopping index row might be the only selectable row, so we fake a match to ensure the move actions
349 -- are performed.
350 l_row := l_grid.row (l_stop_index)
351 check
352 l_row_is_root_row: l_row.parent_row = Void
353 end
354 l_found := True
355 end
356
357 if l_found then
358 check l_row_attached: l_row /= Void end
359 move_to_row (l_row)
360 end
361 end
362 end
363 end
364
365 move_previous (a_query_action: FUNCTION [ANY, TUPLE [EVENT_LIST_ITEM_I], BOOLEAN])
366 -- Moves to the previous item in the errors and warnings list based on some fundamental conditions.
367 --
368 -- `a_query_function': The function to determine if a matched event list item is applicable.
369 require
370 a_query_action_attached: a_query_action /= Void
371 local
372 l_grid: like grid_events
373 l_row_count: INTEGER
374 l_index: INTEGER
375 l_stop_index: INTEGER
376 l_row: EV_GRID_ROW
377 l_item: EVENT_LIST_ITEM_I
378 l_found: BOOLEAN
379 l_valid_rows: BOOLEAN
380 do
381 l_grid := grid_events
382 l_row_count := l_grid.row_count
383 if l_row_count > 0 then
384 -- Check there are visible and selectable items
385 l_valid_rows := False
386 from l_index := 1 until l_index >= l_row_count or l_valid_rows loop
387 l_row := l_grid.row (l_index)
388 l_valid_rows := l_row.is_show_requested and l_row.is_selectable
389 l_index := l_index + l_row.subrow_count_recursive + 1
390 end
391
392 if l_valid_rows then
393 -- There are selectable rows
394
395 if l_grid.selected_rows.is_empty then
396 -- Fetch last row's root row
397 l_row := l_grid.row (1)
398 else
399 -- Fetch selected row's root row (as child may be selected)
400 l_row := l_grid.selected_rows.first
401 if l_row.parent_row /= Void then
402 -- There is parent row, which means the child was selected, skip to the next row (or first)
403 -- so the selected row's root row will be choosen as the previous row.
404 l_row := l_row.parent_row_root
405 if l_row.index + l_row.subrow_count_recursive + 1 <= l_row_count then
406 l_row := l_grid.row (l_row.index + l_row.subrow_count_recursive + 1)
407 else
408 l_row := l_grid.row (1)
409 end
410 end
411 end
412
413 -- Ensure row is visible
414 if not l_row.is_show_requested and l_row.is_selectable then
415 -- Located row is not shown, find previous shown row
416 l_stop_index := l_row.index
417 from until l_row.is_show_requested and l_row.is_selectable loop
418 l_index := l_row.index - 1
419 if l_index = 0 then
420 l_index := l_row_count
421 end
422 l_row := l_grid.row (l_index)
423 if l_row.parent_row /= Void then
424 l_row := l_row.parent_row_root
425 end
426 end
427 end
428
429 -- Set selected index and stop-index
430 l_index := l_row.index
431 l_stop_index := l_index
432 check
433 l_stop_index_is_root_row: l_grid.row (l_index).parent_row = Void
434 end
435
436 -- Shift index
437 l_index := l_index - 1
438 if l_index = 0 then
439 -- Cycle index
440 l_index := l_row_count
441 end
442
443 -- Retrieve index of root row
444 l_row := l_grid.row (l_index)
445 if l_row.parent_row /= Void then
446 l_index := l_row.parent_row_root.index
447 end
448
449 -- Iterate through the rows backwacks
450 from
451 l_row := Void
452 until
453 l_found or
454 l_index = l_stop_index
455 loop
456 l_found := False
457
458 l_row := l_grid.row (l_index)
459 check
460 l_row_is_root: l_row.parent_row_root = Void or l_row.parent_row_root = l_row
461 end
462 if l_row.is_show_requested and l_row.is_selectable then
463 l_item ?= l_row.data
464 l_found := l_item /= Void and then a_query_action.item ([l_item])
465 end
466
467 if not l_found then
468 -- Increment index
469 l_index := l_index - 1
470 if l_index = 0 then
471 -- Cycle, if requested
472 l_index := l_row_count
473 end
474
475 -- Retrieve index of root row
476 l_row := l_grid.row (l_index)
477 if l_row.parent_row_root /= Void then
478 l_row := l_row.parent_row_root
479 l_index := l_row.index
480 end
481 end
482 end
483
484 if not l_found and then l_stop_index > 0 then
485 -- The stopping index row might be the only selectable row, so we fake a match to ensure the move actions
486 -- are performed.
487 l_row := l_grid.row (l_stop_index)
488 check
489 l_row_is_root_row: l_row.parent_row = Void
490 end
491 l_found := True
492 end
493
494 if l_found then
495 -- Perform row actions
496 check l_row_attached: l_row /= Void end
497 move_to_row (l_row)
498 end
499 end
500 end
501 end
502
503 move_to_row (a_row: EV_GRID_ROW)
504 -- Navigates to a row
505 --
506 -- `a_row': A row to navigate to, and process default actions for
507 require
508 a_row_attached: a_row /= Void
509 a_row_has_parent: a_row.parent /= Void
510 a_row_is_in_grid_events: a_row.index <= grid_events.row_count and then grid_events.row (a_row.index) = a_row
511 do
512 -- Select the row to indicate the error moved to
513 grid_events.selected_rows.do_all (agent {EV_GRID_ROW}.disable_select)
514 a_row.enable_select
515
516 -- Perform default action on row, which should open it in an editor
517 do_default_action (a_row)
518 end
519
520 feature {NONE} -- Sort handling
521
522 frozen enable_sorting_on_columns (a_columns: ARRAY [EV_GRID_COLUMN])
523 -- Enables sorting on a selected set of columns
524 --
525 -- `a_columns': The columns to enable sorting on.
526 require
527 a_columns_attached: a_columns /= Void
528 local
529 l_wrapper: like grid_wrapper
530 l_sort_info: EVS_GRID_TWO_WAY_SORTING_INFO [EV_GRID_ROW]
531 l_column: EV_GRID_COLUMN
532 l_upper, i: INTEGER
533 do
534 l_wrapper := grid_wrapper
535 l_wrapper.enable_auto_sort_order_change
536 if l_wrapper.sort_action = Void then
537 l_wrapper.set_sort_action (agent sort_handler)
538 end
539
540 from
541 i := a_columns.lower
542 l_upper := a_columns.upper
543 until i > l_upper loop
544 l_column := a_columns [i]
545 check l_column_attached: l_column /= Void end
546 if l_column /= Void then
547 create l_sort_info.make (agent sorting_row_comparer (?, ?, ?, l_column.index), {EVS_GRID_TWO_WAY_SORTING_ORDER}.ascending_order)
548 l_sort_info.enable_auto_indicator
549 l_wrapper.set_sort_info (l_column.index, l_sort_info)
550 end
551 i := i + 1
552 end
553 end
554
555 frozen enable_copy_to_clipboard
556 -- Enables copying of grid items to the clipboard
557 do
558 grid_wrapper.set_selection_function (agent selected_text)
559 grid_wrapper.enable_copy
560 end
561
562 frozen sorting_row_comparer (a_row, a_other_row: EV_GRID_ROW; a_order: INTEGER_32; a_column: INTEGER): BOOLEAN is
563 -- Agent function used to determine row order.
564 --
565 -- `a_row': The primary row to check.
566 -- `a_row': The secondary row to check.
567 -- `a_order': An order determined by order constants from {EVS_GRID_TWO_WAY_SORTING_ORDER}.
568 -- `a_column': The column index requested to be sorted.
569 -- `Result': True to indicate `a_row' is less than `a_other_row', False otherwise.
570 require
571 row_a_valid: a_row /= Void
572 row_b_valid: a_other_row /= Void
573 a_order_is_valid: a_order = {EVS_GRID_TWO_WAY_SORTING_ORDER}.ascending_order or a_order = {EVS_GRID_TWO_WAY_SORTING_ORDER}.descending_order
574 a_column_is_valid_index: a_column > 0 and a_column <= grid_events.column_count
575 local
576 l_res: like compare_rows
577 do
578 l_res := compare_rows (a_row, a_other_row, a_column)
579 if a_order = {EVS_GRID_TWO_WAY_SORTING_ORDER}.ascending_order then
580 Result := not l_res
581 else
582 Result := l_res
583 end
584 end
585
586 compare_rows (a_row, a_other_row: EV_GRID_ROW; a_column: INTEGER): BOOLEAN is
587 -- Compares two rows from the local grid and returns an index based on their comparative result.
588 --
589 -- Note: Basic implementation handles both string and integer string checking. Items with special
590 -- rendering should have redefined implementation in `row_item_text' to retrieve a sortable
591 -- text string.
592 --
593 -- `a_row': The primary row to check.
594 -- `a_other_row': The secondary row to check.
595 -- `a_column': The column index requested to be sorted.
596 -- `Result': True to indicate `a_row' is less than `a_other_row', False otherwise.
597 require
598 row_a_valid: a_row /= Void
599 row_b_valid: a_other_row /= Void
600 a_column_is_valid_index: a_column > 0 and a_column <= grid_events.column_count
601 local
602 l_item: EV_GRID_ITEM
603 -- Should to STRING_GENERAL, but it requires a change in elks
604 l_text: STRING_32
605 l_other_text: STRING_32
606 do
607 l_item := a_row.item (a_column)
608 if l_item /= Void then
609 l_text := row_item_text (l_item)
610 end
611 l_item := a_other_row.item (a_column)
612 if l_item /= Void then
613 l_other_text := row_item_text (l_item)
614 end
615 if l_text /= Void and l_other_text /= Void then
616 if l_text.is_integer_64 and l_other_text.is_integer_64 then
617 Result := l_text.to_integer_64 < l_other_text.to_integer_64
618 else
619 Result := l_text < l_other_text
620 end
621 elseif l_text = Void then
622 Result := True
623 end
624 ensure
625 asymmetric: Result implies not compare_rows (a_other_row, a_row, a_column)
626 end
627
628 frozen sort_handler (a_column_list: LIST [INTEGER]; a_comparator: AGENT_LIST_COMPARATOR [EV_GRID_ROW]) is
629 -- Action to be performed when sort `a_column_list' using `a_comparator'.
630 require
631 a_column_list_attached: a_column_list /= Void
632 not_a_column_list_is_empty: not a_column_list.is_empty
633 a_comparator_attached: a_comparator /= Void
634 local
635 l_grid: like grid_events
636 l_sorter: DS_QUICK_SORTER [EV_GRID_ROW]
637 l_rows: DS_ARRAYED_LIST [EV_GRID_ROW]
638 l_row: EV_GRID_ROW
639 l_count, i: INTEGER
640 l_event_items: DS_ARRAYED_LIST [TUPLE [event_item: EVENT_LIST_ITEM_I; expand: BOOLEAN]]
641 l_event_item: EVENT_LIST_ITEM_I
642 do
643 create l_sorter.make (a_comparator)
644
645 l_grid := grid_events
646 l_count := l_grid.row_count
647
648 -- Retrieve top level grid items
649 create l_rows.make ((l_count / 2).truncated_to_integer)
650
651 from i := 1 until i > l_count loop
652 l_row := l_grid.row (i)
653 l_rows.force_last (l_row)
654 i := i + l_row.subrow_count_recursive + 1
655 end
656
657 -- Perform sort
658 l_sorter.sort (l_rows)
659
660 -- Extract all event item data for repopulation
661 create l_event_items.make (l_rows.count)
662 from l_rows.start until l_rows.after loop
663 l_row := l_rows.item_for_iteration
664 l_event_item ?= l_row.data
665 check l_event_item_attached: l_event_item /= Void end
666 l_event_items.force_last ([l_event_item, l_row.is_expanded])
667 l_rows.forth
668 end
669
670 -- Repopulate grid
671 l_grid.lock_update
672 l_grid.remove_and_clear_all_rows
673
674 from i := 1; l_event_items.start until l_event_items.after loop
675 l_grid.set_row_count_to (i)
676 l_row := l_grid.row (i)
677 l_event_item := l_event_items.item_for_iteration.event_item
678
679 l_row.set_data (l_event_item)
680 populate_event_grid_row_items (l_event_item, l_row)
681 l_grid.grid_row_fill_empty_cells (l_row)
682 if l_event_items.item_for_iteration.expand then
683 l_row.expand
684 end
685
686 i := i + 1 + l_row.subrow_count_recursive
687 l_event_items.forth
688 end
689
690 l_grid.unlock_update
691 end
692
693 feature {NONE} -- UI manipulation
694
695 update_content_applicable_widgets (a_enable: BOOLEAN)
696 -- Updates widgets on tool that require content to exist
697 --
698 -- `a_enable': True to indicate there is content available, False otherwise
699 require
700 item_count_positive: a_enable implies item_count > 0
701 item_count_is_zero: not a_enable implies item_count = 0
702 do
703 end
704
705 feature {NONE} -- Query
706
707 is_appliable_event (a_event_item: EVENT_LIST_ITEM_I): BOOLEAN
708 -- Determines if event `a_event_item' can be shown with the current event list tool
709 do
710 Result := True
711 end
712
713 row_item_text (a_item: EV_GRID_ITEM): STRING_32
714 -- Extracts a string representation of a grid row's cell item.
715 --
716 -- `a_item': Grid item to retrieve string representation for.
717 -- `Result': A string representation of the item or Void if not string representation could be created.
718 require
719 a_item_attached: a_item /= Void
720 not_a_item_is_destroyed: not a_item.is_destroyed
721 a_item_is_parented: a_item.is_parented
722 local
723 l_label_item: EV_GRID_LABEL_ITEM
724 l_string: STRING_GENERAL
725 do
726 l_label_item ?= a_item
727 if l_label_item /= Void then
728 Result := l_label_item.text
729 end
730 if Result = Void or else Result.is_empty then
731 -- There might be string information in the item data, use that.
732 l_string ?= a_item.data
733 if l_string /= Void then
734 Result := l_string.to_string_32
735 end
736 end
737 if Result = Void then
738 create Result.make_empty
739 end
740 ensure
741 result_attached: Result /= Void
742 end
743
744 row_text (a_row: EV_GRID_ROW): STRING_32
745 -- Retrieves text for a given row.
746 --
747 -- `a_row': A row to retrieve a textual representation of.
748 -- `Result': The textual representation of `a_row'.
749 require
750 a_row_attached: a_row /= Void
751 not_a_row_is_destroyed: not a_row.is_destroyed
752 local
753 l_text: STRING_32
754 l_item: EV_GRID_ITEM
755 l_count, i: INTEGER
756 do
757 create Result.make_empty
758 l_count := a_row.count
759 from i := 1 until i > l_count loop
760 l_item := a_row.item (i)
761 if l_item /= Void then
762 l_text := row_item_text (l_item)
763 end
764 if l_text /= Void and then not l_text.is_empty then
765 Result.append (l_text)
766 Result.append_character ('%T')
767 end
768 i := i + 1
769 end
770 if not Result.is_empty then
771 Result.prune_all_trailing ('%T')
772 end
773 ensure
774 result_attached: Result /= Void
775 end
776
777 category_icon_from_event_item (a_event_item: EVENT_LIST_ITEM_I): EV_PIXMAP
778 -- Retrieves a pixmap associated with a event item's category.
779 --
780 -- `a_event_item': The event item to query a category of.
781 -- `a_pixmap': The pixmap representing the event item's category.
782 require
783 a_event_item_attached: a_event_item /= Void
784 do
785 inspect a_event_item.category
786 when {ENVIRONMENT_CATEGORIES}.compilation then
787 Result := stock_pixmaps.compile_animation_7_icon
788 when {ENVIRONMENT_CATEGORIES}.refactoring then
789 Result := stock_pixmaps.refactor_rename_icon
790 when {ENVIRONMENT_CATEGORIES}.editor then
791 Result := stock_pixmaps.general_document_icon
792 when {ENVIRONMENT_CATEGORIES}.debugger then
793 Result := stock_pixmaps.debugger_environment_force_debug_mode_icon
794 else
795 -- No matching category
796 end
797 end
798
799 priority_icon_from_event_item (a_event_item: EVENT_LIST_ITEM_I): EV_PIXMAP
800 -- Retrieves a pixmap associated with a event item's priority.
801 --
802 -- `a_event_item': The event item to query a category of.
803 -- `a_pixmap': The pixmap representing the event items's priority.
804 require
805 a_event_item_attached: a_event_item /= Void
806 do
807 inspect a_event_item.priority
808 when {PRIORITY_LEVELS}.low then
809 Result := stock_pixmaps.priority_low_icon
810 when {PRIORITY_LEVELS}.normal then
811 --| Just return Void
812 when {PRIORITY_LEVELS}.high then
813 Result := stock_pixmaps.priority_high_icon
814 end
815 end
816
817 feature {NONE} -- Events
818
819 on_event_added (a_service: EVENT_LIST_S; a_event_item: EVENT_LIST_ITEM_I)
820 -- Called when a event item is added to the event service.
821 --
822 -- `a_service': Event service where event was added.
823 -- `a_event_item': The event item added to the service.
824 require
825 a_service_attached: a_service /= Void
826 a_event_attached: a_event_item /= Void
827 a_service_contains_a_event: a_service.all_items.has (a_event_item)
828 local
829 l_add: BOOLEAN
830 l_event_item: EVENT_LIST_ITEM_I
831 l_grid: like grid_events
832 l_row: EV_GRID_ROW
833 l_count: INTEGER
834 do
835 if is_initialized and then is_appliable_event (a_event_item) then
836 l_grid := grid_events
837 l_count := l_grid.row_count
838
839 l_add := maximum_item_count = 0 or else item_count < maximum_item_count
840 if not l_add and then destory_old_items_automatically and then l_count > 0 then
841 -- Remove top grid item
842 l_event_item ?= l_grid.row (1).data
843 check
844 l_event_attached: l_event_item /= Void
845 end
846 on_event_removed (a_service, l_event_item)
847 end
848
849 check
850 item_count_small_enough: maximum_item_count = 0 or else item_count < maximum_item_count
851 end
852
853 -- Add grid item
854 l_count := l_grid.row_count + 1
855 l_grid.set_row_count_to (l_count)
856 l_row := l_grid.row (l_count)
857 -- Set row information and items
858 l_row.set_data (a_event_item)
859 populate_event_grid_row_items (a_event_item, l_row)
860 l_grid.grid_row_fill_empty_cells (l_row)
861
862 item_count := item_count + 1
863
864 if scroll_list_automatically then
865 l_row.ensure_visible
866 end
867
868 if item_count = 1 then
869 -- First item to be added
870 update_content_applicable_widgets (True)
871 end
872 end
873 ensure then
874 a_event_find_event_row: is_initialized and then is_appliable_event (a_event_item) implies find_event_row (a_event_item) /= Void
875 item_count_increased: (is_initialized and then is_appliable_event (a_event_item) and not destory_old_items_automatically) implies item_count = old item_count + 1
876 item_count_small_enought: destory_old_items_automatically implies item_count <= maximum_item_count
877 end
878
879 on_event_removed (a_service: EVENT_LIST_S; a_event_item: EVENT_LIST_ITEM_I) is
880 -- Called after a event item has been removed from the service `a_service'
881 --
882 -- `a_service': Event service where the event was removed.
883 -- `a_event_item': The event item removed from the service.
884 require
885 a_service_attached: a_service /= Void
886 a_event_attached: a_event_item /= Void
887 not_a_service_contains_a_event: not a_service.all_items.has (a_event_item)
888 local
889 l_grid: like grid_events
890 l_row: EV_GRID_ROW
891 l_row_count: INTEGER
892 l_index: INTEGER
893 l_selected: BOOLEAN
894 do
895 if is_initialized and then is_appliable_event (a_event_item) then
896 l_row := find_event_row (a_event_item)
897 if l_row /= Void then
898 check
899 item_count_big_enough: item_count >= 1
900 end
901
902 item_count := item_count - 1
903
904 l_selected := l_row.is_selected
905
906 l_grid := grid_events
907 l_index := l_row.index
908 l_grid.remove_row (l_index)
909
910 if item_count > 0 and then l_selected then
911 -- The row was selected so we need to change the selection
912 l_row := Void
913
914 l_row_count := l_grid.row_count
915 if l_row_count > 0 then
916 if l_index > l_row_count then
917 l_index := l_row_count
918 end
919
920 from until
921 l_index = 0 or (l_row /= Void and then l_row.is_show_requested and l_row.is_selectable)
922 loop
923 l_row := l_grid.row (l_index)
924 if l_row.parent_row_root /= Void then
925 -- Select top most rows only
926 l_row := l_row.parent_row_root
927 l_index := l_row.index
928 end
929 l_index := l_index - 1
930 end
931
932 if l_row /= Void and then l_row.is_show_requested and then l_row.is_selectable then
933 check l_row_visible: l_row.is_show_requested end
934 -- Select most applicable row
935 l_grid.select_row (l_row.index)
936 end
937 end
938 end
939
940 if item_count = 0 then
941 -- Last item to be removed
942 update_content_applicable_widgets (False)
943 end
944 end
945 end
946 ensure then
947 not_a_event_find_event_row: is_initialized and then is_appliable_event (a_event_item) implies find_event_row (a_event_item) = Void
948 item_count_increased: is_initialized and then is_appliable_event (a_event_item) implies item_count = old item_count - 1
949 end
950
951 on_event_changed (a_service: EVENT_LIST_S; a_event_item: EVENT_LIST_ITEM_I)
952 -- Called after a event item has been changed.
953 --
954 -- `a_service': Event service where the event was changed.
955 -- `a_event_item': The event item that was changed.
956 require
957 a_service_attached: a_service /= Void
958 a_event_attached: a_event_item /= Void
959 a_service_contains_a_event: a_service.all_items.has (a_event_item)
960 local
961 l_row: EV_GRID_ROW
962 do
963 if is_initialized and then is_appliable_event (a_event_item) then
964 l_row := find_event_row (a_event_item)
965 if l_row /= Void then
966 -- Re-creates event row
967 populate_event_grid_row_items (a_event_item, l_row)
968 grid_events.grid_row_fill_empty_cells (l_row)
969 end
970 end
971 ensure then
972 a_event_find_event_row: is_initialized and then is_appliable_event (a_event_item) implies find_event_row (a_event_item) /= Void
973 end
974
975 on_grid_events_item_pointer_double_press (a_x: INTEGER; a_y: INTEGER; a_button: INTEGER; a_item: EV_GRID_ITEM) is
976 -- Called when the user double clicks the grid
977 do
978 if a_item /= Void and then a_item.row /= Void then
979 -- Row can be void because the header raises the double press events.
980 do_default_action (a_item.row)
981 end
982 end
983
984 feature {NONE} -- Factory
985
986 create_widget: ES_GRID is
987 -- Create a new container widget upon request
988 do
989 create Result
990 Result.enable_single_row_selection
991 Result.enable_column_separators
992 Result.enable_row_separators
993 Result.set_separator_color (colors.grid_line_color)
994 Result.enable_default_tree_navigation_behavior (True, True, True, True)
995 Result.disable_vertical_scrolling_per_item
996 Result.set_focused_selection_color (colors.grid_focus_selection_color)
997 Result.set_non_focused_selection_color (colors.grid_unfocus_selection_color)
998
999 Result.pointer_double_press_item_actions.extend (agent on_grid_events_item_pointer_double_press)
1000 end
1001
1002 populate_event_grid_row_items (a_event_item: EVENT_LIST_ITEM_I; a_row: EV_GRID_ROW)
1003 -- Populates a grid row's item on a given row using the event `a_event_item'.
1004 --
1005 -- `a_event_item': A event to base the creation of a grid row on.
1006 -- `a_row': The row to create items on.
1007 require
1008 a_event_attached: a_event_item /= Void
1009 a_event_is_appliable_event: is_appliable_event (a_event_item)
1010 a_row_attached: a_row /= Void
1011 grid_events_has_row: a_row.index <= grid_events.row_count and then grid_events.row (a_row.index) = a_row
1012 a_row_has_event_item_data: a_row.data = a_event_item
1013 deferred
1014 ensure
1015 a_row_has_event_item_data: a_row.data = a_event_item
1016 end
1017
1018 feature {NONE} -- Internal implementation cache
1019
1020 internal_grid_wrapper: like grid_wrapper
1021 -- Cached version of `grid_wrapper'
1022 -- Note: Do not use directly!
1023
1024 invariant
1025 grid_events_attached: is_initialized implies grid_events /= Void
1026
1027 indexing
1028 copyright: "Copyright (c) 1984-2006, Eiffel Software"
1029 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
1030 licensing_options: "http://www.eiffel.com/licensing"
1031 copying: "[
1032 This file is part of Eiffel Software's Eiffel Development Environment.
1033
1034 Eiffel Software's Eiffel Development Environment is free
1035 software; you can redistribute it and/or modify it under
1036 the terms of the GNU General Public License as published
1037 by the Free Software Foundation, version 2 of the License
1038 (available at the URL listed under "license" above).
1039
1040 Eiffel Software's Eiffel Development Environment is
1041 distributed in the hope that it will be useful, but
1042 WITHOUT ANY WARRANTY; without even the implied warranty
1043 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1044 See the GNU General Public License for more details.
1045
1046 You should have received a copy of the GNU General Public
1047 License along with Eiffel Software's Eiffel Development
1048 Environment; if not, write to the Free Software Foundation,
1049 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1050 ]"
1051 source: "[
1052 Eiffel Software
1053 356 Storke Road, Goleta, CA 93117 USA
1054 Telephone 805-685-1006, Fax 805-685-6869
1055 Website http://www.eiffel.com
1056 Customer support http://support.eiffel.com
1057 ]"
1058
1059 end

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23