34
35:- module(pce_toc, []). 36:- use_module(library(pce)). 37:- use_module(library(pce_unclip)). 38:- require([ default/3
39 , ignore/1
40 ]). 41
42:- pce_autoload(drag_and_drop_gesture, library(dragdrop)). 43
44resource(file, image, image('16x16/doc.xpm')).
45resource(opendir, image, image('opendir.xpm')).
46resource(closedir, image, image('closedir.xpm')).
47
90
91 94
95:- pce_begin_class(toc_window(name), window,
96 ).
97
98variable(drag_and_drop, bool := @off, get, ).
99
100initialise(TW) :->
101 ::
102 send_super(TW, initialise),
103 send(TW, scrollbars, both),
104 send(TW, hor_shrink, 0),
105 send(TW, hor_stretch, 1),
106 send(TW, display, new(toc_tree), point(10, 5)).
107
108:- pce_group(parts).
109
110tree(TW, Tree:toc_tree) :<-
111 ::
112 get(TW, member, toc_tree, Tree).
113
114
115root(TW, Root:node) :<-
116 ::
117 get(TW, member, toc_tree, Tree),
118 get(Tree, root, Root).
119
120
121selection(TW, Nodes:chain) :<-
122 ::
123 get(TW, member, toc_tree, Tree),
124 get(Tree, selection, Nodes).
125
126selection(TW, Nodes:'any|chain*') :->
127 ::
128 get(TW, member, toc_tree, Tree),
129 send(Tree, selection, Nodes).
130
131node(TW, Id:any, Node:toc_node) :<-
132 ::
133 get(TW, member, toc_tree, Tree),
134 get(Tree, nodes, Table),
135 ( get(Table, member, Id, Node)
136 -> true
137 ; send(Id, instance_of, toc_node),
138 Node = Id
139 ).
140
141:- pce_group(virtual).
142
143open_node(_TW, _Id:any) :->
144 ::
145 true.
146
147select_node(_TW, _Id:any) :->
148 ::
149 true.
150
151expand_node(TW, Id:any) :->
152 ::
153 get(TW, node, Id, Node),
154 send(Node, slot, collapsed, @off).
155
156collapse_node(TW, Id:any) :->
157 ::
158 get(TW, node, Id, Node),
159 send(Node, hide_sons).
160
161popup(_TW, _Id:any, _Popup:popup) :<-
162 ::
163 fail.
164
165:- pce_group(build).
166
167root(TW, Root:toc_folder, Relink:[bool]) :->
168 ::
169 get(TW, tree, Tree),
170 send(Tree, root, Root, Relink).
171
172son(TW, Parent:any, Son:toc_node) :->
173 ::
174 get(TW, node, Parent, Node),
175 send(Node, son, Son).
176
177delete(TW, Id:any) :->
178 ::
179 get(TW, node, Id, Node),
180 send(Node?node, delete_tree).
181
182expand_root(T) :->
183 ::
184 get(T?tree, root, Node),
185 ignore(send(Node, collapsed, @off)).
186
187clear(T) :->
188 ::
189 get(T, tree, Tree),
190 send(Tree, clear, destroy).
191
192:- pce_group(state).
193
194
195expanded_ids(T, Ids:chain) :<-
196 ::
197 new(Ids, chain),
198 ( get(T?tree, root, Root),
199 Root \== @nil
200 -> send(Root, for_all,
201 if(@arg1?collapsed == @off,
202 message(Ids, append, @arg1?identifier)))
203 ; true
204 ).
205
206expand_ids(T, Ids:chain) :->
207 ::
208 send(Ids, for_all, message(T, expand_id, @arg1)).
209
210expand_id(T, Id:any) :->
211 ::
212 get(T, node, Id, Node),
213 send(Node, collapsed, @off).
214
215:- pce_group(scroll).
216
217scroll_vertical(TW,
218 Direction:{forwards,backwards,goto},
219 Unit:{page,file,line},
220 Amount:int) :->
221 ::
222 get(TW, visible, VA),
223 get(TW, bounding_box, BB),
224 ( send(VA, inside, BB)
225 -> true
226 ; Direction == backwards,
227 get(VA, y, Y),
228 Y < 1
229 -> true
230 ; Direction == forwards,
231 get(BB, bottom_side, BBBottom),
232 get(VA, bottom_side, VABottom),
233 VABottom > BBBottom
234 -> true
235 ; send_super(TW, scroll_vertical, Direction, Unit, Amount),
236 get(TW, visible, area(_, AY, _, _)),
237 ( AY < 0
238 -> send(TW, scroll_to, point(0,0))
239 ; true
240 )
241 ).
242
243normalise_tree(TW, Id:any) :->
244 ::
245 get(TW, node, Id, Node),
246 ( get(Node, sons, Sons),
247 Sons \== @nil
248 -> send(TW, compute), 249 get(Sons, map, @arg1?image, Grs),
250 send(Grs, append, Node?image),
251 send(TW, normalise, Grs, y) 252 ; true
253 ).
254
255:- pce_group(event).
256
257:- pce_global(@toc_window_recogniser,
258 make_toc_window_recogniser). 259
260make_toc_window_recogniser(G) :-
261 new(C, click_gesture(left, '', single,
262 message(@receiver, selection, @nil))),
263 new(KB, key_binding(toc_window)),
264 send_list(KB,
265 [ function(page_up,
266 message(@receiver, scroll_vertical, backwards,
267 page, 900)),
268 function(page_down,
269 message(@receiver, scroll_vertical, forwards,
270 page, 900)),
271 function(cursor_home,
272 message(@receiver, scroll_vertical, goto,
273 file, 0)),
274 function(end,
275 message(@receiver, scroll_vertical, goto,
276 file, 1000))
277 ]),
278 new(G, handler_group(C, KB)).
279
280event(TW, Ev:event) :->
281 ::
282 ( send_super(TW, event, Ev)
283 ; send(@toc_window_recogniser, event, Ev)
284 ).
285
286
287drag_and_drop(TW, Val:bool) :->
288 ::
289 send(TW, slot, drag_and_drop, Val),
290 ( Val == @on
291 -> ( send(@toc_node_recogniser?members, member,
292 @toc_drag_and_drop_recogniser)
293 -> true
294 ; send(@toc_node_recogniser?members, append,
295 @toc_drag_and_drop_recogniser)
296 )
297 ).
298
299:- pce_end_class(toc_window).
300
301
302 305
306:- pce_begin_class(toc_tree, tree,
307 ).
308
309variable(nodes, hash_table, get, ).
310
311initialise(TC) :->
312 ::
313 send(TC, slot, nodes, new(hash_table)),
314 send_super(TC, initialise),
315 send(TC, direction, list),
316 send(TC, level_gap, 17).
317
318root(TC, Root:toc_node, Relink:[bool]) :->
319 ::
320 send_super(TC, root, Root, Relink),
321 send(TC?nodes, append, Root?identifier, Root).
322
323selection(TC, SelectedNodes:chain) :<-
324 ::
325 get(TC?contains, find_all, @arg1?selected == @on, SelectedNodes).
326
327selection(TC, Selection:'any|graphical|chain*') :->
328 ::
329 send(TC, compute),
330 ( send(Selection, instance_of, chain)
331 -> get(Selection, map, ?(TC, node_image, @arg1), Graphicals),
332 send_super(TC, selection, Graphicals)
333 ; Selection == @nil
334 -> send_super(TC, selection, Selection)
335 ; get(TC, node_image, Selection, Gr)
336 -> send_super(TC, selection, Gr)
337 ).
338
339node(TC, From:any, Node:toc_node) :<-
340 ::
341 ( send(From, instance_of, toc_node)
342 -> Node = From
343 ; get(TC?nodes, member, From, Node)
344 ).
345
346node_image(TC, From:any, Gr:graphical) :<-
347 ::
348 ( send(From, instance_of, graphical)
349 -> Gr = From
350 ; send(From, instance_of, toc_node)
351 -> get(From, image, Gr)
352 ; get(TC?nodes, member, From, Node),
353 get(Node, image, Gr)
354 ).
355
356:- pce_end_class(toc_tree).
357
358
359:- pce_begin_class(toc_node, node,
360 ).
361
362variable(identifier, [any], none, ).
363
364initialise(TN, Id:any, Image:toc_image) :->
365 send(TN, slot, identifier, Id),
366 send_super(TN, initialise, Image).
367
368
369identifier(TN, Id:any) :<-
370 ::
371 get(TN, slot, identifier, Id0),
372 ( Id0 == @default
373 -> Id = TN
374 ; Id = Id0
375 ).
376
377
378son(TN, Son:toc_node) :->
379 ::
380 send_super(TN, son, Son),
381 get(Son, identifier, Id),
382 get(TN?tree, nodes, Nodes),
383 send(Nodes, append, Id, Son).
384
385
386unlink(TN) :->
387 ( get(TN, tree, Tree),
388 Tree \== @nil,
389 get(Tree, nodes, Table),
390 get(TN, identifier, Id),
391 send(Table, delete, Id)
392 -> true
393 ; true
394 ),
395 send_super(TN, unlink).
396
397
398collapsed(Node, Val:bool*) :->
399 ::
400 ( get(Node, collapsed, Val)
401 -> true
402 ; ( Val == @on
403 -> get(Node?tree, window, TocWindow),
404 get(Node, identifier, Id),
405 send(TocWindow, collapse_node, Id)
406 ; Val == @off
407 -> get(Node?tree, window, TocWindow),
408 get(Node, identifier, Id),
409 ( get(TocWindow, display, Display)
410 -> send(Display, busy_cursor),
411 ignore(send(TocWindow, expand_node, Id)),
412 send(Display, busy_cursor, @nil)
413 ; ignore(send(TocWindow, expand_node, Id))
414 )
415 ; TocWindow = @nil
416 ),
417 ( object(Node)
418 -> send_super(Node, collapsed, Val),
419 send(Node, update_image),
420 ( Val == @off
421 -> send(TocWindow, normalise_tree, Node)
422 ; true
423 )
424 ; true
425 )
426 ).
427
428hide_sons(Node) :->
429 ::
430 send(Node?sons, for_all, message(@arg1, delete_tree)).
431
432can_expand(TF, Val:bool) :->
433 ::
434 ( Val == @off
435 -> send_super(TF, collapsed, @nil)
436 ; send_super(TF, collapsed, @on)
437 ).
438
439:- pce_group(appearance).
440
441image(TF, Img:image) :->
442 ::
443 get(TF, member, bitmap, BM),
444 send(BM, image, Img).
445
446font(TF, Font:font) :->
447 ::
448 send(TF?image?graphicals, for_all,
449 if(message(@arg1, has_send_method, font),
450 message(@arg1, font, Font))).
451
452update_image(_) :->
453 true.
454
455:- pce_group(action).
456
457select(Node, Modified:[bool]) :->
458 ( Modified == @on
459 -> send(Node, toggle_selected)
460 ; get(Node, tree, Tree),
461 send(Tree, selection, Node?image),
462 send(Node, flush),
463 send(Tree?window, select_node, Node?identifier)
464 ).
465
466
467open(Node) :->
468 send(Node?window, open_node, Node?identifier).
469
470:- pce_end_class(toc_node).
471
472
473 476
477:- pce_global(@toc_node_format, make_toc_node_format). 478:- pce_global(@toc_node, new(@receiver?node)).
479:- pce_global(@toc_node_recogniser,
480 new(handler_group(click_gesture(left, '', single,
481 message(@toc_node, select)),
482 click_gesture(left, c, single,
483 message(@toc_node, select, @on)),
484 click_gesture(left, '', double,
485 message(@toc_node, open)),
486 handler(ms_right_down,
487 and(message(@toc_node, select),
488 new(or))),
489 popup_gesture(?(@receiver?window, popup,
490 @toc_node?identifier)),
491 handler(area_enter,
492 message(@receiver, entered, @on)),
493 handler(area_exit,
494 message(@receiver, entered, @off))))).
495
496
497:- pce_global(@toc_drag_and_drop_recogniser,
498 make_toc_drag_and_drop_recogniser). 499
500make_toc_drag_and_drop_recogniser(G) :-
501 new(G, drag_and_drop_gesture(left, '', @default,
502 @arg1?drop_target)),
503 send(G, condition, @event?window?drag_and_drop == @on).
504
505make_toc_node_format(F) :-
506 new(F, format(vertical, 1, @on)),
507 send(F, row_sep, 5).
508
509 512
513:- pce_begin_class(toc_image, device, ).
514
515initialise(TF, Label:'char_array|graphical', Img:image) :->
516 send_super(TF, initialise),
517 send(TF, format, @toc_node_format),
518 send(TF, display, bitmap(Img)),
519 ( send(Label, instance_of, char_array)
520 -> new(Gr, text(Label, left, normal))
521 ; Gr = Label
522 ),
523 send(Gr, name, label),
524 send(TF, display, Gr).
525
526selected(TF, Sel:bool) :->
527 get(TF, member, label, Text),
528 send(Text, selected, Sel).
529selected(TF, Sel:bool) :<-
530 get(TF, member, label, Text),
531 get(Text, selected, Sel).
532
533label_text(TF, Text:graphical) :<-
534 ::
535 get(TF, member, label, Text).
536
537label(TF, Label:'char_array|graphical') :->
538 ::
539 get(TF, label_text, Text),
540 ( send(Label, instance_of, char_array)
541 -> send(Text, string, Label)
542 ; free(Text),
543 send(TF, display, Label),
544 send(Label, name, label)
545 ).
546label(TF, Label:'char_array|graphical') :<-
547 ::
548 get(TF, label_text, Text),
549 ( send(Text, has_get_method, string)
550 -> get(Text, string, Label)
551 ; Label = Text
552 ).
553
554image(TF, Image:image) :->
555 ::
556 get(TF, member, bitmap, BM),
557 send(BM, image, Image).
558image(TF, Image:image) :<-
559 ::
560 get(TF, member, bitmap, BM),
561 get(BM, image, Image).
562
563:- pce_group(event).
564
565event(TF, Ev:event) :->
566 ( send_super(TF, event, Ev)
567 ; send(@toc_node_recogniser, event, Ev)
568 ).
569
570:- pce_group(window).
571
572entered(TF, Val:bool) :->
573 ( Val == @on,
574 ( send(TF, clipped_by_window)
575 -> send(@unclip_window, attach, TF)
576 ; true
577 )
578 ; true
579 ).
580
581:- pce_group(drop).
582
583drop_target(TF, DTG:'chain|any') :<-
584 ( get(TF, selected, @on)
585 -> get(TF?device, selection, Nodes),
586 get(Nodes, map, @arg1?identifier, DTG)
587 ; get(TF?node, identifier, DTG)
588 ).
589
590:- pce_end_class(toc_image).
591
592image(folder, @off, resource(opendir)) :- !.
593image(folder, _, resource(closedir)).
594
595
596 599
600:- pce_begin_class(toc_folder, toc_node, ).
601
602variable(collapsed_image, [image], get, ).
603variable(expanded_image, [image], get, ).
604
605initialise(TF,
606 Label:label='char_array|graphical',
607 Id:identifier=[any],
608 CollapsedImg:collapsed_image=[image],
609 ExpandedImg:expanded_image=[image],
610 CanExpand:can_expand=[bool]) :->
611 send(TF, slot, collapsed_image, CollapsedImg),
612 default(ExpandedImg, CollapsedImg, TheExpandedImg),
613 send(TF, slot, expanded_image, TheExpandedImg),
614 ( CollapsedImg == @default
615 -> image(folder, closed, I)
616 ; I = CollapsedImg
617 ),
618 send_super(TF, initialise, Id, toc_image(Label, I)),
619 ( CanExpand == @off
620 -> send_class(TF, node, collapsed(@nil))
621 ; send_class(TF, node, collapsed(@on))
622 ).
623
624:- pce_group(appearance).
625
626collapsed_image(TF, Img:[image]) :->
627 ::
628 send(TF, slot, collapsed_image, Img),
629 send(TF, update_image).
630
631expanded_image(TF, Img:[image]) :->
632 ::
633 send(TF, slot, expanded_image, Img),
634 send(TF, update_image).
635
636
637:- pce_group(open).
638
639update_image(TF) :->
640 ::
641 get(TF, collapsed, Val),
642 ( Val == @off
643 -> get(TF, expanded_image, Img0)
644 ; get(TF, collapsed_image, Img0)
645 ),
646 ( Img0 == @default
647 -> image(folder, Val, Img)
648 ; Img = Img0
649 ),
650 send(TF, image, Img).
651
652:- pce_group(action).
653
654open(TF) :->
655 get(TF, node, Node),
656 get(Node, collapsed, Collapsed),
657 ( Collapsed == @on
658 -> send(Node, collapsed, @off)
659 ; Collapsed == @off
660 -> send(Node, collapsed, @on)
661 ; send_super(Node, open)
662 ).
663
664:- pce_end_class.
665
666 669
670:- pce_begin_class(toc_file, toc_node, ).
671
672initialise(TF, Label:'char_array|graphical', Id:[any], Img:[image]) :->
673 default(Img, resource(file), I),
674 send_super(TF, initialise, Id, toc_image(Label, I)),
675 send(TF, collapsed, @nil).
676
677:- pce_group(build).
678
679son(TF, _Son:toc_node) :->
680 send(TF, report, error, 'Cannot add sons to a file'),
681 fail.
682
683expand_all(_TF) :->
684 true.
685
686:- pce_end_class