File Coverage

blib/lib/App/Asciio.pm
Criterion Covered Total %
statement 65 161 40.3
branch 1 26 3.8
condition 0 23 0.0
subroutine 22 47 46.8
pod 0 27 0.0
total 88 284 30.9


line stmt bran cond sub pod time code
1              
2             package App::Asciio ;
3              
4 4     4   911858 use strict; use warnings;
  4     4   8  
  4         193  
  4         26  
  4         17  
  4         333  
5              
6 4     4   2725 use utf8;
  4         1337  
  4         28  
7 4     4   2148 use Encode;
  4         70325  
  4         472  
8              
9 4     4   2287 use Clone;
  4         2292  
  4         257  
10 4     4   2422 use Data::TreeDumper ;
  4         147448  
  4         501  
11 4     4   62 use List::Util qw(min max first) ;
  4         14  
  4         371  
12 4     4   3205 use List::MoreUtils qw(any minmax first_value) ;
  4         82951  
  4         45  
13              
14 4     4   10396 use App::Asciio::Actions ;
  4         35  
  4         168  
15 4     4   2618 use App::Asciio::Ascii ;
  4         18  
  4         190  
16 4     4   2682 use App::Asciio::Dialogs ;
  4         14  
  4         154  
17 4     4   2702 use App::Asciio::Elements ;
  4         15  
  4         163  
18 4     4   2471 use App::Asciio::Io ;
  4         18  
  4         277  
19 4     4   2515 use App::Asciio::Menues ;
  4         43  
  4         153  
20 4     4   2288 use App::Asciio::Options ;
  4         17  
  4         186  
21 4     4   2930 use App::Asciio::Setup ;
  4         20  
  4         181  
22 4     4   32 use App::Asciio::String ;
  4         8  
  4         336  
23 4     4   31 use App::Asciio::Markup ;
  4         10  
  4         544  
24 4     4   2680 use App::Asciio::Undo ;
  4         15  
  4         11516  
25              
26             #-----------------------------------------------------------------------------
27              
28             our $VERSION = '1.9.02' ;
29              
30             #-----------------------------------------------------------------------------
31              
32             =encoding utf8
33              
34             =head1 NAME
35              
36             ___ _ _ ____
37             / | __________(_|_) __ \
38             / /| | / ___/ ___/ / / / / /
39             / ___ |(__ ) /__/ / / /_/ /
40             /_/ |_/____/\___/_/_/\____/
41              
42              
43             =head1 SYNOPSIS
44              
45             $> asciio [file.asciio] # GUI application using Gtk3
46              
47             $> tasciio [file.asciio] # TUI application
48              
49             $> asciio_to_text file.asciio # converts asciio files to ASCII
50              
51             =head1 DESCRIPTION
52              
53             Asciio allows you to draw ASCII diagrams in a GUI or TUI. The diagrams can be
54             saved as ASCII text or in a format that allows you to modify them later.
55              
56             Diagrams consist of boxes and text elements connected by arrows. Boxes stay
57             connected when you move them around.
58              
59             Both GUI and TUI have vim-like bindings, the GUI has a few extra bindings that
60             are usually found in GUI applications.
61              
62             Keyboard bindings are the best way to use Asciio, they are listed at the end of
63             this documentation. Bindings can also be modified.
64              
65             =head1 DOCUMENTATION
66              
67             =head2 GUI
68              
69             .-------------------------------------------------------------.
70             | ........................................................... |
71             | ..........-------------..------------..--------------...... |
72             | .........| stencils > || asciio > || box |..... |
73             | .........| Rulers > || computer > || text |..... |
74             | .........| File > || people > || wirl_arrow |..... |
75             grid----->......'-------------'| divers > || axis |..... |
76             | ..................^.....'------------'| ... |..... |
77             | ..................|...................'--------------'..... |
78             | ..................|........................................ |
79             '-------------------|-----------------------------------------'
80             |
81             context menu access some commands
82             most are accessed through the keyboard
83              
84             =head2 Exporting to ASCII
85              
86             You can export to a file in ASCII by using a '.txt' file extension.
87              
88             You can also export the selection, in ASCII, to the Primary clipboard.
89              
90             =head2 Elements
91              
92             =head3 boxes and text
93              
94             .----------.
95             | title |
96             .----------. |----------| ************
97             | | | body 1 | * *
98             '----------' | body 2 | ************
99             '----------'
100             any text
101             (\_/) |
102             text (O.o) <------'
103             (> <)
104              
105             =head3 if-box and process-box
106              
107             .--------------.
108             / a == b \ __________
109             ( && ) \ \
110             \ 'string' ne '' / ) process )
111             '--------------' /_________/
112            
113              
114             =head3 user boxes and exec-boxes
115              
116             For simple elements, put your design in a box, with or without a frame.
117              
118             The an "exec-box" object that lets you put the output of an external
119             application in a box, in the example below the table is generated, if you
120             already have text in a file you can use 'cat your_file' as the command.
121              
122             +------------+------------+------------+------------+
123             | input_size ‖ algorithmA | algorithmB | algorithmC |
124             +============+============+============+============+
125             | 1 ‖ 206.4 sec. | 206.4 sec. | 0.02 sec. |
126             +------------+------------+------------+------------+
127             | 250 ‖ - | 80 min. | 2.27 sec. |
128             +------------+------------+------------+------------+
129              
130             =head3 wirl-arrow
131              
132             Rotating the end clockwise or counter-clockwise changes its direction.
133              
134             ^ ^
135             | -----. \
136             | | \
137             '---- | '-------
138             ------> |
139             v
140            
141             =head3 multi section wirl-arrow
142              
143             A set of whirl arrows connected to each other.
144              
145             .----------. .
146             | | \ / \
147             .-------' ^ \ / \
148             | .-----------> \ ' .
149             | '----. \ /
150             | | \ /
151             '--------' '------'
152            
153              
154             =head3 angled-arrow and axis
155              
156             -------. .-------
157             \ /
158             \ / ^
159             | ^
160             / \ | /
161             / \ | /
162             ------' '------- -------->
163            
164             =head2 Examples
165              
166             .----Base::Class::Derived_B
167             /
168             Something::Else /
169             \ .-------Base::Class::Derived_C
170             \ /
171             '-------Base::Class
172             ' \
173             / '----Latest::Greatest
174             Some::Thing--'
175              
176             _____
177             | ___ |
178             ||___|| load
179             | ooo |--.------------------.------------------------.
180             '_____' | | |
181             v v v
182             .----------. .--------------------------. .----------------.
183             | module C | | module A | | module B |
184             '----------' |--------------------------| | (instrumented) |
185             | | .-----. | '----------------'
186             '---------------->| A.o | | |
187             | '-----' | |
188             | .------------------. | |
189             | | A.instrumented.o |<-------------'
190             | '------------------' |
191             '--------------------------'
192              
193             =head3 Unicode example
194              
195             ╭───────────────────────────────────────────────────────╮
196             │ 中文韩文和unicode符号支持以及全新的菱形元素 │
197             │ Chinese Korean and unicode symbols and rhombus object │
198             ╰───────────────────────────────────────────────────────╯
199             ,',
200             ,' ',
201             ,' ',
202             ╭────────: :───────────╮
203             │ ', ,' │
204             │ ', ,' │
205             │ ',' │
206             │ │ v
207             v v ⎛ ⎞
208             ┌───┐ ╭───╮ ⎜ ⎟
209             │ │ │ │ ⎜ ⎟
210             └───┘ ╰───╯ ⎝ ⎠
211              
212             ┌──────────────┐ ┌──────────────┐
213             │ 主机1(host1) │ │ 主机2(host2) │
214             └──────────────┘ └──────────────┘
215             ^ ^ ^ ^
216             │ │ │ │
217             │ ╰───────────────────────╮ │ │
218             │ │ │ │
219             │ ╭───────────────────│───╯ │
220             │ │ │ │
221             PCIEx4│ PCIEx4│ PCIEx4 │ PCIEx4│
222             ┌─────────────┐ ┌─────────────┐
223             │ HBA card1 │ │ HBA card2 │
224             └─────────────┘ └─────────────┘
225              
226             ## Exporting to SVG
227              
228             The "goat" project (https://github.com/blampe/goat) must be installed.
229              
230             =head2 Bindings
231              
232             Edit selected element
233              
234             Delete selected element(s)
235              
236             Undo
237              
238             -r Redo
239              
240             <.> Quick link
241              
242             <,> Quick copy
243              
244             Add vertical ruler
245              
246             Add horizontal ruler
247              
248             Remove rulers
249              
250             Moving elements:
251              
252             =over 4
253              
254             Move selected elements left
255              
256             Move selected elements down
257              
258             Move selected elements up
259              
260             Move selected elements right
261              
262              
263             Move selected elements left
264              
265             Move selected elements down
266              
267             Move selected elements up
268              
269             Move selected elements right
270              
271             =back
272              
273             Selecting elements:
274              
275             =over 4
276              
277             Select next element
278              
279             Select previous element
280              
281             Select next element move mouse
282              
283             Select all elements
284              
285             Select connected elements
286              
287             Deselect all elements
288              
289             =back
290              
291             Resizing elements:
292              
293             =over 4
294              
295             <1> Make element narrower
296              
297             <2> Make element taller
298              
299             <3> Make element shorter
300              
301             <4> Make element wider
302              
303             Shrink box
304              
305             =back
306              
307             Clipboard:
308              
309             =over 4
310              
311             Copy to clipboard
312              
313            

Insert from clipboard

314              
315             Export to clipboard & primary as ascii
316              
317            

Import from primary to box

318              
319             Import from primary to text
320              
321             =back
322              
323             <:> command group:
324              
325             =over 4
326              
327             Quit
328              
329             Quit no save
330              
331             Save
332              
333             SaveAs
334              
335             Open
336              
337             Insert
338              
339             Display manpage
340              
341             Help
342              
343             Display commands
344              
345             Display action files
346              
347             Display keyboard mapping
348              
349             =back
350              
351             Insert group:
352              
353             =over 4
354              
355             Add angled arrow
356              
357             Add arrow
358              
359             Add unicode arrow
360              
361             Add shrink box
362              
363             Add box
364              
365             Add unicode box
366              
367             Add multiple boxes
368              
369             Add connector
370              
371             Add exec-box no border
372              
373             Add exec-box
374              
375             Insert from file
376              
377             Add group object type 1
378              
379             Add help box
380              
381             Add if-box
382              
383             Add horizontal ruler
384              
385             External command output in a box
386              
387             External command output in a box no frame
388              
389            

Add process

390              
391             Add vertical ruler
392              
393             Add text
394              
395             Add multiple text
396              
397             =back
398              
399             arrow group:
400              
401             =over 4
402              
403             Insert multi-wirl section
404              
405             Flip arrow start and end
406              
407             Change arrow direction
408              
409             Append multi-wirl sectioni
410              
411             Remove last section from multi-wirl
412              
413             =back
414              
415              
416             align group:
417              
418             =over 4
419              
420             Align top
421              
422             Align left
423              
424             Align bottom
425              
426             Align right
427              
428             Align vertically
429              
430             Align horizontally
431              
432             =back
433              
434             grouping group:
435              
436             =over 4
437              
438             Group selected elements
439              
440             Ungroup selected elements
441              
442             Temporary move selected element to the front
443              
444             Move selected elements to the front
445              
446             Move selected elements to the back
447              
448             =back
449              
450             stripes-group group:
451              
452             =over 4
453              
454             <1> Create one stripe group
455              
456             Create stripes group
457              
458             Ungroup stripes group
459              
460             =back
461              
462             display group:
463              
464             =over 4
465              
466             Change grid color
467              
468             Change Asciio background color
469              
470             Flip grid display
471              
472             Flip color scheme
473              
474             Flip transparent element background
475              
476             =back
477              
478             debug group:
479              
480             =over 4
481              
482             Dump selected elements
483              
484             Dump all elements
485              
486             Display undo stack statistics
487              
488             Test
489              
490             Dump self
491              
492             Display numbered objects
493              
494             =back
495              
496             slides group:
497              
498             =over 4
499              
500             Previous slide
501              
502             First slide
503              
504             Load slides
505              
506             Next slide
507              
508             =back
509              
510             Mouse emulation:
511              
512             =over 4
513              
514             <'> Toggle> mouse
515              
516             <Ö> Mouse shift-left-click
517              
518             <ö> Mouse left-click
519              
520             <ä> Mouse right-click
521              
522             Mouse drag left 3
523              
524             Mouse drag down 3
525              
526             Mouse drag up 3
527              
528             Mouse drag right 3
529              
530             Mouse drag down
531              
532             Mouse drag left
533              
534             Mouse drag right
535              
536             Mouse drag up
537              
538              
539             Mouse drag down
540              
541             Mouse drag left
542              
543             Mouse drag right
544              
545             Mouse drag up
546              
547              
548             <ö> Mouse alt-left-click
549              
550             <ö> Mouse ctl-left-click
551              
552             =back
553              
554             =head2 GUI extra bindings
555              
556             Select all elements
557              
558             Copy to clipboard
559              
560             Insert from clipboard
561              
562             Export to clipboard & primary as ascii
563              
564             Import from primary to box
565              
566             Undo
567              
568             Redo
569              
570             <+> Zoom in
571              
572             <-> Zoom out
573              
574             Edit selected element
575              
576             Add to delection
577              
578             <0A0-button-1> Quick link
579              
580             <0AS-button-1> Duplicate elements
581              
582             Insert flex point
583              
584             =head1 Asciio and Vim
585              
586             You can call Asciio from vim and insert your diagram.
587              
588             map a :call TAsciio()
589              
590             function! TAsciio()
591             let line = getline('.')
592              
593             let tempn = tempname()
594             let tempnt = tempn . '.txt'
595             let temp = shellescape(tempn)
596             let tempt = shellescape(tempnt)
597              
598             exec "normal i Asciio_file:" . tempn . "\"
599              
600             if ! has("gui_running")
601             exec "silent !mkdir -p $(dirname " . temp . ")"
602             exec "silent !cp ~/.config/Asciio/templates/empty.asciio ". temp . "; tasciio " . temp . "; asciio_to_text " . temp . " >" . tempt
603             exec "read " . tempnt
604             endif
605              
606             redraw!
607             endfunction
608              
609             =cut
610              
611             sub new
612             {
613 169     169 0 1248352 my ($class) = @_ ;
614              
615 169         3552 my $self =
616             bless
617             {
618             ELEMENT_TYPES => [],
619             ELEMENTS => [],
620             CONNECTIONS => [],
621             CLIPBOARD => {},
622             FONT_FAMILY => 'Monospace',
623             FONT_SIZE => '10',
624             TAB_AS_SPACES => ' ',
625             OPAQUE_ELEMENTS => 1,
626             DISPLAY_GRID => 1,
627             DISPLAY_GRID2 => 1,
628            
629            
630             PREVIOUS_X => 0, PREVIOUS_Y => 0,
631             MOUSE_X => 0, MOUSE_Y => 0,
632             DRAGGING => undef,
633             SELECTION_RECTANGLE =>{START_X => 0, START_Y => 0},
634            
635             ACTIONS => {},
636            
637             COPY_OFFSET_X => 3,
638             COPY_OFFSET_Y => 3,
639             COLORS => {},
640            
641             NEXT_GROUP_COLOR => 0,
642            
643             WORK_DIRECTORY => '.asciio_work_dir',
644             CREATE_BACKUP => 1,
645             MODIFIED => 0,
646            
647             DO_STACK_POINTER => 0,
648             DO_STACK => [] ,
649             }, $class ;
650              
651              
652 169         784 return($self) ;
653             }
654              
655             #-----------------------------------------------------------------------------
656              
657             sub event_options_changed
658             {
659 0     0 0 0 my ($self) = @_;
660              
661 0         0 $self->{CURRENT_ACTIONS} = $self->{ACTIONS} ;
662              
663 0         0 $self->set_font($self->{FONT_FAMILY}, $self->{FONT_SIZE}) ;
664              
665 0 0       0 $self->{TAB_AS_SPACES} = ' ' unless defined $self->{TAB_AS_SPACES} ;
666              
667 0         0 App::Asciio::Markup::use_markup($self->{USE_MARKUP_MODE}) ;
668             }
669              
670             #-----------------------------------------------------------------------------
671              
672             sub exit
673             {
674 0     0 0 0 my ($self, $code) = @_ ;
675              
676 0   0     0 exit ($code // 0) ;
677             }
678              
679             #-----------------------------------------------------------------------------
680              
681             sub set_title
682             {
683 0     0 0 0 my ($self, $title) = @_;
684              
685 0 0       0 defined $title and $self->{TITLE} = $title ;
686             }
687              
688             sub get_title
689             {
690 0     0 0 0 my ($self) = @_;
691 0         0 Encode::_utf8_on($self->{TITLE});
692 0         0 $self->{TITLE} ;
693             }
694              
695             #-----------------------------------------------------------------------------
696              
697             sub set_font
698             {
699 0     0 0 0 my ($self, $font_family, $font_size) = @_;
700              
701 0   0     0 $self->{FONT_FAMILY} = $font_family || 'Monospace';
702 0   0     0 $self->{FONT_SIZE} = $font_size || 10 ;
703             }
704              
705             sub get_font
706             {
707 0     0 0 0 my ($self) = @_;
708              
709 0         0 return($self->{FONT_FAMILY}, $self->{FONT_SIZE}) ;
710             }
711              
712             sub get_font_as_string
713             {
714 0     0 0 0 my ($self) = @_;
715              
716 0         0 return("$self->{FONT_FAMILY} $self->{FONT_SIZE}") ;
717             }
718              
719             #-----------------------------------------------------------------------------
720              
721             sub update_display
722             {
723 0     0 0 0 my ($self) = @_;
724              
725 0         0 $self->call_hook('CANONIZE_CONNECTIONS', $self->{CONNECTIONS}, $self->get_character_size()) ;
726             }
727              
728             #-----------------------------------------------------------------------------
729              
730             sub call_hook
731             {
732 0     0 0 0 my ($self, $hook_name, @arguments) = @_;
733              
734 0 0       0 $self->{HOOKS}{$hook_name}->(@arguments) if (exists $self->{HOOKS}{$hook_name}) ;
735             }
736              
737             #-----------------------------------------------------------------------------
738              
739             sub button_release_event
740             {
741 0     0 0 0 my ($self, $event) = @_ ;
742              
743 0 0 0     0 if((defined $self->{EDIT_SEMAPHORE}) && ($self->{EDIT_SEMAPHORE} > 0))
744             {
745 0         0 $self->{EDIT_SEMAPHORE}--;
746 0         0 return ;
747             }
748              
749 0         0 my $button = $event->{BUTTON} ;
750 0         0 my $modifiers = $event->{MODIFIERS} ;
751              
752 0 0       0 if($self->exists_action("${modifiers}$event->{TYPE}-$button"))
753             {
754 0         0 $self->run_actions(["${modifiers}$event->{TYPE}-$button", $event]) ;
755             }
756              
757 0         0 undef $self->{DRAGGING} ;
758              
759 0 0 0     0 if(defined $self->{MODIFIED_INDEX} && defined $self->{MODIFIED} && $self->{MODIFIED_INDEX} == $self->{MODIFIED})
      0        
760             {
761 0         0 $self->pop_undo_buffer(1) ; # no changes
762             }
763              
764 0         0 $self->update_display();
765             }
766              
767             #-----------------------------------------------------------------------------
768              
769             sub button_press_event
770             {
771 0     0 0 0 my ($self, $event) = @_ ;
772              
773 0         0 undef $self->{DRAGGING} ;
774 0         0 delete $self->{RESIZE_CONNECTOR_NAME} ;
775              
776 0         0 $self->create_undo_snapshot() ;
777 0         0 $self->{MODIFIED_INDEX} = $self->{MODIFIED} ;
778              
779 0         0 my $button = $event->{BUTTON} ;
780 0         0 my $modifiers = $event->{MODIFIERS} ;
781              
782 0         0 $self->run_actions(["${modifiers}$event->{TYPE}-$button", $event]) ;
783             }
784              
785             #-----------------------------------------------------------------------------
786              
787             sub motion_notify_event
788             {
789 0     0 0 0 my ($self, $event) = @_ ;
790              
791 0 0 0     0 if((defined $self->{EDIT_SEMAPHORE}) && ($self->{EDIT_SEMAPHORE} > 0))
792             {
793 0         0 $self->{EDIT_SEMAPHORE}--;
794 0         0 return ;
795             }
796              
797             # my $button = $event->{BUTTON} ;
798 0         0 my($x, $y) = @{$event->{COORDINATES}} ;
  0         0  
799 0         0 my $modifiers = $event->{MODIFIERS} ;
800              
801 0 0 0     0 if($self->{PREVIOUS_X} != $x || $self->{PREVIOUS_Y} != $y)
802             {
803 0 0       0 if($self->exists_action("${modifiers}motion_notify"))
804             {
805 0         0 $self->run_actions(["${modifiers}motion_notify", $event]) ;
806             }
807             else
808             {
809 0         0 ($self->{PREVIOUS_X}, $self->{PREVIOUS_Y}) = ($x, $y) ;
810 0         0 ($self->{MOUSE_X}, $self->{MOUSE_Y}) = ($x, $y) ;
811             }
812             }
813             }
814              
815             #-----------------------------------------------------------------------------
816              
817             sub select_element_event
818             {
819 0     0 0 0 my ($self, $x, $y, $filter) = @_ ;
820              
821 0         0 my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X}, $y - $self->{PREVIOUS_Y}) ;
822              
823 0         0 $self->{SELECTION_RECTANGLE}{END_X} = $x ;
824 0         0 $self->{SELECTION_RECTANGLE}{END_Y} = $y ;
825              
826 0 0   0   0 $filter = sub {1} unless defined $filter ;
  0         0  
827              
828             $self->select_elements
829             (
830             1,
831             grep
832 0         0 { $filter->($_) }
833             grep # elements within selection rectangle
834             {
835             $self->element_completely_within_rectangle
836             (
837             $_,
838             $self->{SELECTION_RECTANGLE},
839             )
840 0         0 } @{$self->{ELEMENTS}}
  0         0  
  0         0  
841             ) ;
842              
843 0         0 $self->update_display();
844             }
845              
846             #-----------------------------------------------------------------------------
847              
848             sub move_elements_event
849             {
850 0     0 0 0 my ($self, $x, $y) = @_;
851              
852 0         0 my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X}, $y - $self->{PREVIOUS_Y}) ;
853              
854 0         0 my @selected_elements = $self->get_selected_elements(1) ;
855              
856 0         0 $self->move_elements($x_offset, $y_offset, @selected_elements) ;
857 0         0 $self->update_display();
858             }
859              
860             #-----------------------------------------------------------------------------
861              
862             sub resize_element_event
863             {
864 0     0 0 0 my ($self, $x, $y) = @_ ;
865              
866 0         0 my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X}, $y - $self->{PREVIOUS_Y}) ;
867              
868 0         0 my ($selected_element) = $self->get_selected_elements(1) ;
869              
870             $self->{RESIZE_CONNECTOR_NAME} =
871             $self->resize_element
872             (
873             $self->{PREVIOUS_X} - $selected_element->{X}, $self->{PREVIOUS_Y} - $selected_element->{Y} ,
874             $x - $selected_element->{X}, $y - $selected_element->{Y} ,
875             $selected_element,
876             $self->{RESIZE_CONNECTOR_NAME},
877 0         0 ) ;
878            
879 0         0 $self->update_display();
880             }
881              
882             #-----------------------------------------------------------------------------
883              
884             my %ignored_keys = map { $_ => 1 } qw(000-Control_L 000-Control_R 000-Shift_L 000-Shift_R 000-Alt_L 000-ISO_Level3_Shift) ;
885              
886             sub key_press_event
887             {
888 0     0 0 0 my ($self, $event)= @_;
889              
890 0         0 my $modifiers = $event->{MODIFIERS} ;
891 0         0 my $key = $event->{KEY_NAME} ;
892              
893 0         0 $self->{CACHE}{ORIGINAL_EVENT} = $event ;
894              
895 0 0       0 $self->run_actions("${modifiers}$key") unless exists $ignored_keys{"${modifiers}$key"} ;
896             }
897              
898             #-----------------------------------------------------------------------------
899              
900             sub mouse_scroll_event
901             {
902 0     0 0 0 my ($self, $event)= @_;
903              
904 0         0 my ($modifiers, $direction) = ($event->{MODIFIERS}, $event->{DIRECTION}) ;
905              
906 0         0 $self->run_actions("${modifiers}$direction") ;
907             }
908              
909             #-----------------------------------------------------------------------------
910              
911             sub update_quadrants
912             {
913 0     0 0 0 my ($self, $element) = @_ ;
914              
915 0         0 my ($x1, $x2, $y1, $y2) = $element->get_extents() ;
916             }
917              
918             #-----------------------------------------------------------------------------
919              
920             {
921              
922             my $overlays_sub ;
923              
924 0     0 0 0 sub set_overlays_sub { $overlays_sub = $_[1] ; }
925 0 0   0 0 0 sub get_overlays { defined $overlays_sub ? $overlays_sub->(@_) : () ; }
926              
927             }
928              
929             #-----------------------------------------------------------------------------
930              
931       0 0   sub show_pointer { ; }
932       0 0   sub hide_pointer { ; }
933            
934             #-----------------------------------------------------------------------------
935              
936             sub get_character_size
937             {
938 96     96 0 681 my ($self) = @_ ;
939            
940 96 50       208 if(exists $self->{USER_CHARACTER_WIDTH})
941             {
942 96         286 return ($self->{USER_CHARACTER_WIDTH}, $self->{USER_CHARACTER_HEIGHT}) ;
943             }
944             else
945             {
946 0         0 return (8, 16) ;
947             }
948             }
949              
950             #-----------------------------------------------------------------------------
951              
952             sub set_character_size
953             {
954 169     169 0 934 my ($self, $width, $height) = @_ ;
955              
956 169         609 ($self->{USER_CHARACTER_WIDTH}, $self->{USER_CHARACTER_HEIGHT}) = ($width, $height) ;
957             }
958              
959             #-----------------------------------------------------------------------------
960              
961             sub get_color
962             {
963 0     0 0   my ($self, $name) = @_;
964              
965 0   0       return($self->{COLORS}{$name} // [1, 0, 0]) ;
966             }
967              
968             #-----------------------------------------------------------------------------
969              
970             sub invalidate_rendering_cache
971             {
972 0     0 0   my ($self) = @_ ;
973              
974 0           for my $element (@{$self->{ELEMENTS}})
  0            
975             {
976 0           delete $element->{CACHE} ;
977             }
978              
979 0           delete $self->{CACHE} ;
980             }
981              
982             #-----------------------------------------------------------------------------
983              
984             =head1 DEPENDENCIES
985              
986             gnome libraries, gtk, gtk-perl for the gtk version
987              
988             =head1 BUGS AND LIMITATIONS
989              
990             Please report errors at https://github.com/nkh/P5-App-Asciio/issues.
991              
992             =head1 AUTHORS
993              
994             Khemir Nadim ibn Hamouda
995             https://github.com/nkh
996             CPAN ID: NKH
997              
998             Qin Qing
999             northisland2017@gmail.com
1000             unicode support, scroll bar, and rhombus object
1001            
1002             =head1 LICENSE AND COPYRIGHT
1003              
1004             This program is free software; you can redistribute it and/or modify it under
1005             the same terms as Perl itself or GPL3.
1006              
1007             =head2 Docker Image
1008              
1009             There are docker images made by third parties, use a search engine for the latest.
1010              
1011             example image: https://gist.github.com/BruceWind/32920cf74ba5b7172b31b06fec38aabb
1012              
1013             =head1 SEE ALSO
1014              
1015             http://www.jave.de
1016             http://search.cpan.org/~osfameron/Text-JavE-0.0.2/JavE.pm
1017             http://ditaa.sourceforge.net/
1018             http://www.codeproject.com/KB/macros/codeplotter.aspx
1019             http://search.cpan.org/~jpierce/Text-FIGlet-1.06/FIGlet.pm
1020             http://www.ascii-art.de (used some entries as base for the network stencil)
1021             http://www.textfiles.com/art/
1022             http://www2.b3ta.com/_bunny/texbunny.gif
1023              
1024              
1025             *\o_ _o/*
1026             / * * \
1027             <\ *\o/* />
1028             )
1029             o/* / > *\o
1030             <\ />
1031             __o */\ /\* o__
1032             * /> <\ *
1033             /\* __o_ _o__ */\
1034             * / * * \ *
1035             <\ />
1036             *\o/*
1037             ejm97 __)__
1038              
1039             =cut
1040              
1041             #------------------------------------------------------------------------------------------------------
1042              
1043             "
1044             (\_/)
1045             (O.o)
1046             /> ASCII world domination!
1047             "
1048              
1049