34
35:- module(pce_toc, []). 36:- use_module(library(pce)). 37:- use_module(library(pce_unclip)). 38:- require([ send_list/2,
39 default/3
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 new(FImg, image(resource(file))),
317 get(FImg, size, size(W,_)),
318 LevelGap is W+1,
319 send(TC, level_gap, LevelGap).
320
321root(TC, Root:toc_node, Relink:[bool]) :->
322 ::
323 send_super(TC, root, Root, Relink),
324 send(TC?nodes, append, Root?identifier, Root).
325
326selection(TC, SelectedNodes:chain) :<-
327 ::
328 get(TC?contains, find_all, @arg1?selected == @on, SelectedNodes).
329
330selection(TC, Selection:'any|graphical|chain*') :->
331 ::
332 send(TC, compute),
333 ( send(Selection, instance_of, chain)
334 -> get(Selection, map, ?(TC, node_image, @arg1), Graphicals),
335 send_super(TC, selection, Graphicals)
336 ; Selection == @nil
337 -> send_super(TC, selection, Selection)
338 ; get(TC, node_image, Selection, Gr)
339 -> send_super(TC, selection, Gr)
340 ).
341
342node(TC, From:any, Node:toc_node) :<-
343 ::
344 ( send(From, instance_of, toc_node)
345 -> Node = From
346 ; get(TC?nodes, member, From, Node)
347 ).
348
349node_image(TC, From:any, Gr:graphical) :<-
350 ::
351 ( send(From, instance_of, graphical)
352 -> Gr = From
353 ; send(From, instance_of, toc_node)
354 -> get(From, image, Gr)
355 ; get(TC?nodes, member, From, Node),
356 get(Node, image, Gr)
357 ).
358
359:- pce_end_class(toc_tree).
360
361
362:- pce_begin_class(toc_node, node,
363 ).
364
365variable(identifier, [any], none, ).
366
367initialise(TN, Id:any, Image:toc_image) :->
368 send(TN, slot, identifier, Id),
369 send_super(TN, initialise, Image).
370
371
372identifier(TN, Id:any) :<-
373 ::
374 get(TN, slot, identifier, Id0),
375 ( Id0 == @default
376 -> Id = TN
377 ; Id = Id0
378 ).
379
380
381son(TN, Son:toc_node) :->
382 ::
383 send_super(TN, son, Son),
384 get(Son, identifier, Id),
385 get(TN?tree, nodes, Nodes),
386 send(Nodes, append, Id, Son).
387
388
389unlink(TN) :->
390 ( get(TN, tree, Tree),
391 Tree \== @nil,
392 get(Tree, nodes, Table),
393 get(TN, identifier, Id),
394 send(Table, delete, Id)
395 -> true
396 ; true
397 ),
398 send_super(TN, unlink).
399
400
401collapsed(Node, Val:bool*) :->
402 ::
403 ( get(Node, collapsed, Val)
404 -> true
405 ; ( Val == @on
406 -> get(Node?tree, window, TocWindow),
407 get(Node, identifier, Id),
408 send(TocWindow, collapse_node, Id)
409 ; Val == @off
410 -> get(Node?tree, window, TocWindow),
411 get(Node, identifier, Id),
412 ( get(TocWindow, display, Display)
413 -> send(Display, busy_cursor),
414 ignore(send(TocWindow, expand_node, Id)),
415 send(Display, busy_cursor, @nil)
416 ; ignore(send(TocWindow, expand_node, Id))
417 )
418 ; TocWindow = @nil
419 ),
420 ( object(Node)
421 -> send_super(Node, collapsed, Val),
422 send(Node, update_image),
423 ( Val == @off
424 -> send(TocWindow, normalise_tree, Node)
425 ; true
426 )
427 ; true
428 )
429 ).
430
431hide_sons(Node) :->
432 ::
433 send(Node?sons, for_all, message(@arg1, delete_tree)).
434
435can_expand(TF, Val:bool) :->
436 ::
437 ( Val == @off
438 -> send_super(TF, collapsed, @nil)
439 ; send_super(TF, collapsed, @on)
440 ).
441
442:- pce_group(appearance).
443
444image(TF, Img:image) :->
445 ::
446 get(TF, member, bitmap, BM),
447 send(BM, image, Img).
448
449font(TF, Font:font) :->
450 ::
451 send(TF?image?graphicals, for_all,
452 if(message(@arg1, has_send_method, font),
453 message(@arg1, font, Font))).
454
455update_image(_) :->
456 true.
457
458:- pce_group(action).
459
460select(Node, Modified:[bool]) :->
461 ( Modified == @on
462 -> send(Node, toggle_selected)
463 ; get(Node, tree, Tree),
464 send(Tree, selection, Node?image),
465 send(Node, flush),
466 send(Tree?window, select_node, Node?identifier)
467 ).
468
469
470open(Node) :->
471 send(Node?window, open_node, Node?identifier).
472
473:- pce_end_class(toc_node).
474
475
476 479
480:- pce_global(@toc_node_format, make_toc_node_format). 481:- pce_global(@toc_node, new(@receiver?node)).
482:- pce_global(@toc_node_recogniser,
483 new(handler_group(click_gesture(left, '', single,
484 message(@toc_node, select)),
485 click_gesture(left, c, single,
486 message(@toc_node, select, @on)),
487 click_gesture(left, '', double,
488 message(@toc_node, open)),
489 handler(ms_right_down,
490 and(message(@toc_node, select),
491 new(or))),
492 popup_gesture(?(@receiver?window, popup,
493 @toc_node?identifier)),
494 handler(area_enter,
495 message(@receiver, entered, @on)),
496 handler(area_exit,
497 message(@receiver, entered, @off))))).
498
499
500:- pce_global(@toc_drag_and_drop_recogniser,
501 make_toc_drag_and_drop_recogniser). 502
503make_toc_drag_and_drop_recogniser(G) :-
504 new(G, drag_and_drop_gesture(left, '', @default,
505 @arg1?drop_target)),
506 send(G, condition, @event?window?drag_and_drop == @on).
507
508make_toc_node_format(F) :-
509 new(F, format(vertical, 1, @on)),
510 send(F, row_sep, 5).
511
512 515
516:- pce_begin_class(toc_image, device, ).
517
518initialise(TF, Label:'char_array|graphical', Img:image) :->
519 send_super(TF, initialise),
520 send(TF, format, @toc_node_format),
521 send(TF, display, bitmap(Img)),
522 ( send(Label, instance_of, char_array)
523 -> new(Gr, text(Label, left, normal))
524 ; Gr = Label
525 ),
526 send(Gr, name, label),
527 send(TF, display, Gr).
528
529selected(TF, Sel:bool) :->
530 get(TF, member, label, Text),
531 send(Text, selected, Sel).
532selected(TF, Sel:bool) :<-
533 get(TF, member, label, Text),
534 get(Text, selected, Sel).
535
536label_text(TF, Text:graphical) :<-
537 ::
538 get(TF, member, label, Text).
539
540label(TF, Label:'char_array|graphical') :->
541 ::
542 get(TF, label_text, Text),
543 ( send(Label, instance_of, char_array)
544 -> send(Text, string, Label)
545 ; free(Text),
546 send(TF, display, Label),
547 send(Label, name, label)
548 ).
549label(TF, Label:'char_array|graphical') :<-
550 ::
551 get(TF, label_text, Text),
552 ( send(Text, has_get_method, string)
553 -> get(Text, string, Label)
554 ; Label = Text
555 ).
556
557image(TF, Image:image) :->
558 ::
559 get(TF, member, bitmap, BM),
560 send(BM, image, Image).
561image(TF, Image:image) :<-
562 ::
563 get(TF, member, bitmap, BM),
564 get(BM, image, Image).
565
566:- pce_group(event).
567
568event(TF, Ev:event) :->
569 ( send_super(TF, event, Ev)
570 ; send(@toc_node_recogniser, event, Ev)
571 ).
572
573:- pce_group(window).
574
575entered(TF, Val:bool) :->
576 ( Val == @on,
577 ( send(TF, clipped_by_window)
578 -> send(@unclip_window, attach, TF)
579 ; true
580 )
581 ; true
582 ).
583
584:- pce_group(drop).
585
586drop_target(TF, DTG:'chain|any') :<-
587 ( get(TF, selected, @on)
588 -> get(TF?device, selection, Nodes),
589 get(Nodes, map, @arg1?identifier, DTG)
590 ; get(TF?node, identifier, DTG)
591 ).
592
593:- pce_end_class(toc_image).
594
595image(folder, @off, resource(opendir)) :- !.
596image(folder, _, resource(closedir)).
597
598
599 602
603:- pce_begin_class(toc_folder, toc_node, ).
604
605variable(collapsed_image, [image], get, ).
606variable(expanded_image, [image], get, ).
607
608initialise(TF,
609 Label:label='char_array|graphical',
610 Id:identifier=[any],
611 CollapsedImg:collapsed_image=[image],
612 ExpandedImg:expanded_image=[image],
613 CanExpand:can_expand=[bool]) :->
614 send(TF, slot, collapsed_image, CollapsedImg),
615 default(ExpandedImg, CollapsedImg, TheExpandedImg),
616 send(TF, slot, expanded_image, TheExpandedImg),
617 ( CollapsedImg == @default
618 -> image(folder, closed, I)
619 ; I = CollapsedImg
620 ),
621 send_super(TF, initialise, Id, toc_image(Label, I)),
622 ( CanExpand == @off
623 -> send_class(TF, node, collapsed(@nil))
624 ; send_class(TF, node, collapsed(@on))
625 ).
626
627:- pce_group(appearance).
628
629collapsed_image(TF, Img:[image]) :->
630 ::
631 send(TF, slot, collapsed_image, Img),
632 send(TF, update_image).
633
634expanded_image(TF, Img:[image]) :->
635 ::
636 send(TF, slot, expanded_image, Img),
637 send(TF, update_image).
638
639
640:- pce_group(open).
641
642update_image(TF) :->
643 ::
644 get(TF, collapsed, Val),
645 ( Val == @off
646 -> get(TF, expanded_image, Img0)
647 ; get(TF, collapsed_image, Img0)
648 ),
649 ( Img0 == @default
650 -> image(folder, Val, Img)
651 ; Img = Img0
652 ),
653 send(TF, image, Img).
654
655:- pce_group(action).
656
657open(TF) :->
658 get(TF, node, Node),
659 get(Node, collapsed, Collapsed),
660 ( Collapsed == @on
661 -> send(Node, collapsed, @off)
662 ; Collapsed == @off
663 -> send(Node, collapsed, @on)
664 ; send_super(Node, open)
665 ).
666
667:- pce_end_class.
668
669 672
673:- pce_begin_class(toc_file, toc_node, ).
674
675initialise(TF, Label:'char_array|graphical', Id:[any], Img:[image]) :->
676 default(Img, resource(file), I),
677 send_super(TF, initialise, Id, toc_image(Label, I)),
678 send(TF, collapsed, @nil).
679
680:- pce_group(build).
681
682son(TF, _Son:toc_node) :->
683 send(TF, report, error, 'Cannot add sons to a file'),
684 fail.
685
686expand_all(_TF) :->
687 true.
688
689:- pce_end_class