/[eiffelstudio]/branches/Eiffel_57_docking/Src/Eiffel/interface/new_graphical/managers/eb_history_manager.e
ViewVC logotype

Contents of /branches/Eiffel_57_docking/Src/Eiffel/interface/new_graphical/managers/eb_history_manager.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 61937 - (show annotations)
Sun Jul 30 05:59:02 2006 UTC (13 years, 4 months ago) by manus
File size: 15310 byte(s)
EiffelStudio docking branch. It only contains modified classes needed to get the docking version of EiffelStudio.
1 indexing
2 description : "Facilities to manage the history of a development window."
3 legal: "See notice at end of class."
4 status: "See notice at end of class."
5 date : "$Date$"
6 revision : "$Revision $"
7
8 class
9 EB_HISTORY_MANAGER
10
11 inherit
12 EB_RECYCLABLE
13
14 EB_RECYCLER
15 rename
16 destroy as recycle
17 redefine
18 recycle
19 end
20
21 EB_SHARED_PREFERENCES
22
23 create
24 make
25
26 feature {NONE} -- Initialization
27
28 make (a_owner: EB_HISTORY_OWNER) is
29 -- Initialization
30 local
31 max_size: INTEGER
32 do
33 create history.make (10)
34 index_active := 1
35 target := a_owner
36 create back_command.make (a_owner)
37 create forth_command.make (a_owner)
38 max_size := max_display_size
39 create class_display_list.make (max_size)
40 create cluster_display_list.make (max_size)
41 create feature_display_list.make (max_size)
42 -- Register the recyclable command
43 add_recyclable (back_command)
44 add_recyclable (forth_command)
45
46 -- register itself as recyclable to parent
47 a_owner.add_recyclable (Current)
48 end
49
50 feature -- Access
51
52 active: STONE is
53 -- Active item. Void if history is empty or current stone is invalid.
54 do
55 if not is_empty then
56 Result := history.i_th (index_active)
57 if Result /= Void and then not Result.is_valid then
58 Result := Void
59 end
60 end
61 ensure
62 return_only_valid_stones: (Result /= Void) implies Result.is_valid
63 -- Does not hold for invalid stones.
64 -- not_empty_iff_result_not_void: (not is_empty) = (Result /= Void)
65 end
66
67 count: INTEGER is
68 -- Number of elements in the history
69 do
70 Result := history.count
71 end
72
73 list: LIST [STONE] is
74 -- Linear representation of the history.
75 do
76 Result := history
77 end
78
79 class_display_list: ARRAYED_LIST [CELL2 [CLASSI_STONE, INTEGER]]
80 -- Representation of the class history without repeating classes.
81
82 cluster_display_list: ARRAYED_LIST [CELL2 [CLUSTER_STONE, INTEGER]]
83 -- Representation of the class history without repeating classes.
84
85 feature_display_list: ARRAYED_LIST [CELL2 [FEATURE_STONE, INTEGER]]
86 -- Representation of the feature history without repeating features.
87
88 target: EB_HISTORY_OWNER
89 -- Target for current history.
90
91 back_command: EB_HISTORY_BACK_COMMAND
92 -- Command to go back in the history
93
94 forth_command: EB_HISTORY_FORTH_COMMAND
95 -- Command to go forth in the history
96
97 new_menu: EB_HISTORY_MANAGER_MENU is
98 -- Menu representing the history, automatically
99 -- recycled when Current will be recycled.
100 do
101 create Result.make (Current)
102 add_recyclable (Result)
103 end
104
105 feature -- Status report
106
107 is_empty: BOOLEAN is
108 -- Is the history empty?
109 do
110 Result := (history.count = 0)
111 end
112
113 is_back_possible: BOOLEAN is
114 -- Is the operation `back' possible?
115 -- Yes iff `active_index' > 1 and there is one stone before that is not `Void'.
116 local
117 valid_found: BOOLEAN
118 cur: INTEGER
119 do
120 if not history.is_empty then
121 from
122 cur := index_active - 1
123 until
124 valid_found or cur <= 0
125 loop
126 valid_found := history.i_th (cur) /= Void
127 cur := cur - 1
128 end
129 Result := valid_found
130 else
131 Result := False
132 end
133 ensure
134 --| `cur + 1' because in the loop we decrement `cur'.
135 -- This means there is a valid stone before `active' in the history.
136 -- found: Result implies (cur + 1 < index_active and history.i_th (cur + 1) /= void)
137 end
138
139 is_forth_possible: BOOLEAN is
140 -- Is the operation `forth' possible?
141 local
142 valid_found: BOOLEAN
143 cur: INTEGER
144 do
145 if not history.is_empty then
146 from
147 cur := index_active + 1
148 until
149 valid_found or cur > history.count
150 loop
151 valid_found := history.i_th (cur) /= Void
152 cur := cur + 1
153 end
154 Result := valid_found
155 else
156 Result := False
157 end
158 ensure
159 --| `cur - 1' because in the loop we increment `cur'.
160 -- This means there is a valid stone after `active' in the history.
161 -- found: Result implies (cur - 1 > index_active and history.i_th (cur - 1) /= void)
162 end
163
164 is_go_i_th_possible (i: INTEGER): BOOLEAN is
165 -- Is the operation `go_i_th (i)' possible?
166 do
167 Result := (not is_empty) and (i >= 1) and (i <= count)
168 end
169
170 feature -- Element change
171
172 back is
173 -- go back in the history
174 require
175 operation_possible: is_back_possible
176 local
177 valid_found: BOOLEAN
178 initial: INTEGER
179 do
180 initial := index_active
181 fresh_active_position
182 from
183 index_active := index_active - 1
184 until
185 valid_found
186 loop
187 check
188 valid_index: index_active >= 1
189 -- Because of the precondition
190 end
191 valid_found := history.i_th (index_active) /= Void
192 index_active := index_active - 1
193 end
194 index_active := index_active + 1
195 notify_observers (notify_move, Void, index_active)
196 target.advanced_set_stone (active)
197 if not target.stone.is_equal (active) then
198 -- The user cancelled the set_stone.
199 -- We must go back to our previous position.
200 index_active := initial
201 notify_observers (notify_move, Void, index_active)
202 end
203 end
204
205 forth is
206 -- go forward in the history
207 require
208 operation_possible: is_forth_possible
209 local
210 valid_found: BOOLEAN
211 initial: INTEGER
212 do
213 initial := index_active
214 fresh_active_position
215 from
216 index_active := index_active + 1
217 until
218 valid_found
219 loop
220 check
221 valid_index: index_active <= history.count
222 -- Because of the precondition
223 end
224 valid_found := history.i_th (index_active) /= Void
225 index_active := index_active + 1
226 end
227
228 index_active := index_active - 1
229 notify_observers (notify_move, Void, index_active)
230 target.advanced_set_stone (active)
231 if not target.stone.is_equal (active) then
232 -- The user cancelled the set_stone.
233 -- We must go back to our previous position.
234 index_active := initial
235 notify_observers (notify_move, Void, index_active)
236 end
237 end
238
239 go_i_th (i: INTEGER) is
240 -- Go to level `i' of history. 1 stands for the begginning
241 -- of the history, `count' for the most recently stone added
242 -- to history.
243 -- Warning: This may position the history on an invalid stone (a Void one).
244 require
245 operation_possible: is_go_i_th_possible (i)
246 local
247 initial: INTEGER
248 do
249 initial := index_active
250 fresh_active_position
251 index_active := i
252 notify_observers (notify_move, Void, index_active)
253 target.advanced_set_stone (active)
254 if not target.stone.is_equal (active) then
255 -- The user cancelled the set_stone.
256 -- We must go back to our previous position.
257 index_active := initial
258 notify_observers (notify_move, Void, index_active)
259 end
260 end
261
262 extend (a_stone: STONE) is
263 -- Add `a_stone' to the right of `active'. Remove everything
264 -- after `active'.
265 local
266 history_item: STONE
267 fst, fst2: FEATURE_STONE
268 cst: CLASSI_STONE
269 active_is_cst: BOOLEAN
270 i: INTEGER
271 do
272 cst ?= active
273 fst ?= active
274 active_is_cst := cst /= Void and fst = Void
275 if active_is_cst then
276 fst ?= a_stone
277 else
278 fst := Void
279 end
280 if
281 -- We do not want the same stone twice in the history...
282 (active /= Void and then
283 a_stone /= Void and then
284 not (active.same_as (a_stone)) or else
285 active = Void or else
286 a_stone = Void) or else
287 -- ...Unless it is a feature stone following a class stone.
288 fst /= Void and then
289 not fst.same_as (active)
290 --| Useless test: if fst /= Void, then active is not Void and a classi_stone.
291 --active_is_cst
292 then
293 fresh_active_position
294 if is_forth_possible then
295 -- Wipe out everything after `active'
296 from
297 history.go_i_th (index_active)
298 history.forth
299 i := index_active + 1
300 until
301 history.after
302 loop
303 history_item := history.item
304 history.remove
305 notify_observers (notify_remove, history_item, i)
306 i := i + 1
307 end
308 end
309
310 -- Add the new stone at the end of the history.
311 fst := Void
312 fst2 ?= a_stone
313 if fst2 /= Void then
314 create fst.make (fst2.e_feature)
315 history.extend (fst)
316 else
317 history.extend (a_stone)
318 end
319
320 -- Set the new stone to be the active one.
321 index_active := history.count
322
323 build_display_lists
324
325 if fst = Void then
326 notify_observers (notify_add, a_stone, index_active)
327 else
328 notify_observers (notify_add, fst, index_active)
329 end
330 notify_observers (notify_move, Void, index_active)
331 end
332 ensure
333 --| Does not hold for call_Stack_stones, which are converted into feature stones.
334 -- stone_is_active: equal (a_stone, active)
335 end
336
337 synchronize is
338 -- Replace all invalid stones with `Void' in the history.
339 -- Should be called after each compilation.
340 local
341 cur: CURSOR
342 do
343 from
344 cur := history.cursor
345 history.start
346 until
347 history.after
348 loop
349 if history.item /= Void then
350 history.replace (history.item.synchronized_stone)
351 end
352 history.forth
353 end
354 history.go_to (cur)
355 build_display_lists
356 notify_observers (notify_changed, Void, 0)
357 end
358
359 feature {EB_HISTORY_MANAGER_OBSERVER} -- Observer pattern / Registration
360
361 add_observer (an_observer: EB_HISTORY_MANAGER_OBSERVER) is
362 -- Add `an_observer' to the list of observers for Current.
363 require
364 valid_observer: an_observer /= Void
365 do
366 if observers = Void then
367 create observers.make (2)
368 end
369 observers.extend (an_observer)
370 end
371
372 remove_observer (an_observer: EB_HISTORY_MANAGER_OBSERVER) is
373 -- Remove `an_observer' to the list of observers for Current.
374 require
375 valid_observer: an_observer /= Void
376 do
377 if observers /= Void then
378 observers.prune_all (an_observer)
379 end
380 end
381
382 feature -- Recyclable
383
384 recycle is
385 -- Recycle
386 do
387 target := Void
388 end
389
390 feature {NONE} -- Observer pattern / Implementation
391
392 notify_observers (a_notification_code: INTEGER; a_stone: STONE; a_position: INTEGER) is
393 -- The history or the active position has changed.
394 do
395 if observers /= Void then
396 from
397 observers.start
398 until
399 observers.after
400 loop
401 inspect a_notification_code
402 when notify_move then
403 observers.item.on_position_changed
404 when notify_add then
405 observers.item.on_item_added (a_stone, a_position)
406 when notify_remove then
407 observers.item.on_item_removed (a_stone, a_position)
408 when notify_changed then
409 observers.item.on_update
410 end
411 observers.forth
412 end
413 end
414 end
415
416 observers: ARRAYED_LIST [EB_HISTORY_MANAGER_OBSERVER]
417 -- All observers for Current.
418
419 notify_move: INTEGER is 0
420 notify_add: INTEGER is 1
421 notify_remove: INTEGER is 2
422 notify_changed: INTEGER is 3
423
424 feature {NONE} -- Implementation
425
426 history: ARRAYED_LIST [STONE]
427 -- History
428
429 index_active: INTEGER
430 -- Index of the active item.
431
432 build_display_lists is
433 -- Generate the *_display_list according to the history state.
434 local
435 already_displayed: BOOLEAN
436 conv_cl: CLASSI_STONE
437 conv_clu: CLUSTER_STONE
438 conv_f: FEATURE_STONE
439 max_size: INTEGER
440 do
441 feature_display_list.wipe_out
442 class_display_list.wipe_out
443 cluster_display_list.wipe_out
444 max_size := max_display_size
445 from
446 history.finish
447 until
448 history.before
449 loop
450 --| First find the first valid item.
451 from
452 until
453 history.before or else
454 history.item /= Void
455 loop
456 history.back
457 end
458
459 already_displayed := False
460 if not history.before then
461 --| Is it a feature?
462 conv_f ?= history.item
463 if conv_f /= Void then
464 if feature_display_list.count < max_size then
465 from
466 feature_display_list.start
467 until
468 feature_display_list.after
469 loop
470 if feature_display_list.item.item1.same_as (history.item) then
471 already_displayed := True
472 feature_display_list.finish
473 end
474 feature_display_list.forth
475 end
476 if not already_displayed then
477 feature_display_list.extend (create {CELL2 [FEATURE_STONE, INTEGER]}.make (conv_f, history.index))
478 feature_display_list.finish
479 end
480 end
481 else
482 --| Is it a class?
483 conv_cl ?= history.item
484 if conv_cl /= Void then
485 if class_display_list.count < max_size then
486 from
487 class_display_list.start
488 until
489 class_display_list.after
490 loop
491 if class_display_list.item.item1.same_as (history.item) then
492 already_displayed := True
493 class_display_list.finish
494 end
495 class_display_list.forth
496 end
497 if not already_displayed then
498 class_display_list.extend (create {CELL2 [CLASSI_STONE, INTEGER]}.make (conv_cl, history.index))
499 class_display_list.finish
500 end
501 end
502 else
503 --| Is it a cluster?
504 conv_clu ?= history.item
505 if conv_clu /= Void then
506 if cluster_display_list.count < max_size then
507 from
508 cluster_display_list.start
509 until
510 cluster_display_list.after
511 loop
512 if cluster_display_list.item.item1.same_as (history.item) then
513 already_displayed := True
514 cluster_display_list.finish
515 end
516 cluster_display_list.forth
517 end
518 if not already_displayed then
519 cluster_display_list.extend (create {CELL2 [CLUSTER_STONE, INTEGER]}.make (conv_clu, history.index))
520 cluster_display_list.finish
521 end
522 end
523 end
524 end
525 end
526 history.back
527 end
528 end
529 end
530
531 max_display_size: INTEGER is
532 -- Maximum number of items displayed in the history (in the address combo boxes).
533 do
534 Result := preferences.development_window_data.max_history_size
535 end
536
537 fresh_active_position is
538 -- Fresh active stone position
539 do
540 if active /= Void then
541 if target.position >= 0 then
542 active.set_position (target.position)
543 else
544 active.set_position (0)
545 end
546 if target.pos_container /= Void then
547 active.set_pos_container (target.pos_container)
548 else
549 active.set_pos_container (Void)
550 end
551 end
552 end
553
554 indexing
555 copyright: "Copyright (c) 1984-2006, Eiffel Software"
556 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
557 licensing_options: "http://www.eiffel.com/licensing"
558 copying: "[
559 This file is part of Eiffel Software's Eiffel Development Environment.
560
561 Eiffel Software's Eiffel Development Environment is free
562 software; you can redistribute it and/or modify it under
563 the terms of the GNU General Public License as published
564 by the Free Software Foundation, version 2 of the License
565 (available at the URL listed under "license" above).
566
567 Eiffel Software's Eiffel Development Environment is
568 distributed in the hope that it will be useful, but
569 WITHOUT ANY WARRANTY; without even the implied warranty
570 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
571 See the GNU General Public License for more details.
572
573 You should have received a copy of the GNU General Public
574 License along with Eiffel Software's Eiffel Development
575 Environment; if not, write to the Free Software Foundation,
576 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
577 ]"
578 source: "[
579 Eiffel Software
580 356 Storke Road, Goleta, CA 93117 USA
581 Telephone 805-685-1006, Fax 805-685-6869
582 Website http://www.eiffel.com
583 Customer support http://support.eiffel.com
584 ]"
585
586 end -- class EB_HISTORY_MANAGER
587

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23