| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | package App::Asciio ; | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | $|++ ; | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 1 |  |  | 1 |  | 851 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 38 |  | 
| 7 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 33 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 1 |  |  | 1 |  | 830 | use Data::TreeDumper ; | 
|  | 1 |  |  |  |  | 67953 |  | 
|  | 1 |  |  |  |  | 69 |  | 
| 10 | 1 |  |  | 1 |  | 628 | use Clone; | 
|  | 1 |  |  |  |  | 590 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 11 | 1 |  |  | 1 |  | 6 | use List::Util qw(min max first) ; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 88 |  | 
| 12 | 1 |  |  | 1 |  | 492 | use List::MoreUtils qw(any minmax first_value) ; | 
|  | 1 |  |  |  |  | 11293 |  | 
|  | 1 |  |  |  |  | 8 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 1 |  |  | 1 |  | 1254 | use App::Asciio::Setup ; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | use App::Asciio::Dialogs ; | 
| 16 |  |  |  |  |  |  | use App::Asciio::Elements ; | 
| 17 |  |  |  |  |  |  | use App::Asciio::Menues ; | 
| 18 |  |  |  |  |  |  | use App::Asciio::Actions ; | 
| 19 |  |  |  |  |  |  | use App::Asciio::Undo ; | 
| 20 |  |  |  |  |  |  | use App::Asciio::Io ; | 
| 21 |  |  |  |  |  |  | use App::Asciio::Ascii ; | 
| 22 |  |  |  |  |  |  | use App::Asciio::Options ; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | our $VERSION = '1.51' ; | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | =head1 NAME | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | App::Asciio - Plain ASCII diagram | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | |     |             |       | | 
| 35 |  |  |  |  |  |  | |       |     |      |      |       | | 
| 36 |  |  |  |  |  |  | |       |     |      |      |       | | 
| 37 |  |  |  |  |  |  | v       |     v      |      v       | | 
| 38 |  |  |  |  |  |  | v            v              v | 
| 39 |  |  |  |  |  |  | _____                           _____ | 
| 40 |  |  |  |  |  |  | /\  _  \                        /\  __ \ | 
| 41 |  |  |  |  |  |  | \ \ \_\ \    ___     ___   _   _\ \ \ \ \ | 
| 42 |  |  |  |  |  |  | ----->	 \ \  __ \  /  __\  / ___\/\ \/\ \ \ \ \ \  -----> | 
| 43 |  |  |  |  |  |  | \ \ \ \ \/\__,  \/\ \___' \ \ \ \ \ \_\ \ | 
| 44 |  |  |  |  |  |  | \ \_\ \_\/\____/\ \____/\ \_\ \_\ \_____\ | 
| 45 |  |  |  |  |  |  | \/_/\/_/\/___/  \/___/  \/_/\/_/\/_____/ | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | |             |             |     | | 
| 48 |  |  |  |  |  |  | |     |       |     |       |     |      | | 
| 49 |  |  |  |  |  |  | v     |       |     |       v     |      | | 
| 50 |  |  |  |  |  |  | |       v     |             |      | | 
| 51 |  |  |  |  |  |  | v             |             |      v | 
| 52 |  |  |  |  |  |  | v             v | 
| 53 |  |  |  |  |  |  | (\_/) | 
| 54 |  |  |  |  |  |  | (O.o) ASCII world domination is near! | 
| 55 |  |  |  |  |  |  | (> <) | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | $> perl asciio.pl | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | It has always been painful to do ASCII diagrams by hand. This perl application allows | 
| 64 |  |  |  |  |  |  | you to draw ASCII diagrams in a modern (but simple) graphical interface. | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | The ASCII graphs can be saved as ASCII or in a format that allows you to modify them later. | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | Special thanks go to the Muppet and the gtk-perl group, Gábor Szabó for his help and advices. | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | Adam Kennedy coined the cool name. | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | =head1 DOCUMENTATION | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =head2 Asciio user interface | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | .-----------------------------------------------------------------. | 
| 78 |  |  |  |  |  |  | |                             Asciio                              | | 
| 79 |  |  |  |  |  |  | |-----------------------------------------------------------------| | 
| 80 |  |  |  |  |  |  | | ............................................................... | | 
| 81 |  |  |  |  |  |  | | ..............-------------..------------..--------------...... | | 
| 82 |  |  |  |  |  |  | | .............| stencils  > || asciio   > || box          |..... | | 
| 83 |  |  |  |  |  |  | | .............| Rulers    > || computer > || text         |..... | | 
| 84 |  |  |  |  |  |  | | .............| File      > || people   > || wirl_arrow   |..... | | 
| 85 |  |  |  |  |  |  | grid---------->.......'-------------'| divers   > || axis         |..... | | 
| 86 |  |  |  |  |  |  | | ......................^.....'------------'| boxes      > |..... | | 
| 87 |  |  |  |  |  |  | | ......................|...................| rulers     > |..... | | 
| 88 |  |  |  |  |  |  | | ......................|...................'--------------'..... | | 
| 89 |  |  |  |  |  |  | | ......................|........................................ | | 
| 90 |  |  |  |  |  |  | | ......................|........................................ | | 
| 91 |  |  |  |  |  |  | | ......................|........................................ | | 
| 92 |  |  |  |  |  |  | | ......................|........................................ | | 
| 93 |  |  |  |  |  |  | '-----------------------|-----------------------------------------' | 
| 94 |  |  |  |  |  |  | | | 
| 95 |  |  |  |  |  |  | | | 
| 96 |  |  |  |  |  |  | context menu | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | Press 'F1' for help. | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | =head2 context menu | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | The context menu allows to access to B<Asciio> commands. | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | =head2 keyboard shortcuts | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | All the keyboad commands definitions can be found under I<asciio/setup/actions/>. Among the commands | 
| 108 |  |  |  |  |  |  | implemented are: | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | =over 2 | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | =item * select all | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | =item * delete | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | =item * undo | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =item * group/ungroup | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | =item * open / save | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =item * local clipboard operations | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | =item * send to front/back | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | =item * insert arrow, boxes, text | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | =item * ... | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | =back | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | The available commands are displayed if you press B<K>. | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =head2 elements | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | There are a few elements implemented at the moment. | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | =head3 wirl arrow | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | An arrow that tries to do what you want. Try rotating the end clockwise then counter clockwise to see how it acts | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | ^ | 
| 143 |  |  |  |  |  |  | | | 
| 144 |  |  |  |  |  |  | |    --------. | 
| 145 |  |  |  |  |  |  | |            | | 
| 146 |  |  |  |  |  |  | '-------     | | 
| 147 |  |  |  |  |  |  | | | 
| 148 |  |  |  |  |  |  | O-------------X     /      | | 
| 149 |  |  |  |  |  |  | /       | | 
| 150 |  |  |  |  |  |  | /        | | 
| 151 |  |  |  |  |  |  | /         v | 
| 152 |  |  |  |  |  |  | / | 
| 153 |  |  |  |  |  |  | / | 
| 154 |  |  |  |  |  |  | v | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | =head3 multi section wirl arrow | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | A set of whirl arrows connected to each other | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | .----------.                       . | 
| 162 |  |  |  |  |  |  | |          |                \     / \ | 
| 163 |  |  |  |  |  |  | .-------'           ^     \   /   \ | 
| 164 |  |  |  |  |  |  | |                    \     \ /     \ | 
| 165 |  |  |  |  |  |  | |   .----------->     \     '       . | 
| 166 |  |  |  |  |  |  | |   '----.             \           / | 
| 167 |  |  |  |  |  |  | |        |              \         / | 
| 168 |  |  |  |  |  |  | '--------'               '-------' | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | =head3 angled arrow and axis | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | -------.         .------- | 
| 175 |  |  |  |  |  |  | \       / | 
| 176 |  |  |  |  |  |  | \     / | 
| 177 |  |  |  |  |  |  | \   / | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | /   \ | 
| 180 |  |  |  |  |  |  | /     \ | 
| 181 |  |  |  |  |  |  | /       \ | 
| 182 |  |  |  |  |  |  | ------'         '------- | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | ^ | 
| 185 |  |  |  |  |  |  | ^    |    ^ | 
| 186 |  |  |  |  |  |  | \   |   / | 
| 187 |  |  |  |  |  |  | \  |  / | 
| 188 |  |  |  |  |  |  | \ | / | 
| 189 |  |  |  |  |  |  | <-------- --------> | 
| 190 |  |  |  |  |  |  | / |\ | 
| 191 |  |  |  |  |  |  | /  | \ | 
| 192 |  |  |  |  |  |  | /   |  \ | 
| 193 |  |  |  |  |  |  | v    |   v | 
| 194 |  |  |  |  |  |  | v | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | =head3 box and text | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | .----------. | 
| 200 |  |  |  |  |  |  | |  title   | | 
| 201 |  |  |  |  |  |  | .----------.   |----------|   ************ | 
| 202 |  |  |  |  |  |  | |          |   | body 1   |   *          * | 
| 203 |  |  |  |  |  |  | '----------'   | body 2   |   ************ | 
| 204 |  |  |  |  |  |  | '----------' | 
| 205 |  |  |  |  |  |  | anything in a box | 
| 206 |  |  |  |  |  |  | (\_/)               | | 
| 207 |  |  |  |  |  |  | edit_me                 (O.o)  <------------' | 
| 208 |  |  |  |  |  |  | (> <) | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | You can also use the 'External commands in box' to direct an external command output to a box. Default shortcuts are 'x' and CTL + 'x'. | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | =head3 "if" box and "process" box | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | ____________ | 
| 216 |  |  |  |  |  |  | .--------------.     \           \ | 
| 217 |  |  |  |  |  |  | / a == b         \     \           \   __________ | 
| 218 |  |  |  |  |  |  | (    &&            )     ) process   )  \         \ | 
| 219 |  |  |  |  |  |  | \ 'string' ne '' /     /           /    ) process ) | 
| 220 |  |  |  |  |  |  | '--------------'     /___________/    /_________/ | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | =head3 your own stencils | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | Take a look at I<setup/stencils/computer> for a stencil example. Stencils listed in I<setup/setup.ini> will | 
| 226 |  |  |  |  |  |  | be loaded when B<Asciio> starts. | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | =head3 your own element type | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | For simple elements, put your design in a box. That should cover 90% of anyone's needs. You can look in | 
| 231 |  |  |  |  |  |  | I<lib/stripes> for element implementation examples. | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | =head2 exporting to ASCII | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | You can export to a file in ASCII format but using the B<.txt> extension. | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | Exporting to the clipboard is done with B<ctl + e>. | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | =head1 EXAMPLES | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | User code ^            ^ OS code | 
| 243 |  |  |  |  |  |  | \          / | 
| 244 |  |  |  |  |  |  | \        / | 
| 245 |  |  |  |  |  |  | \      / | 
| 246 |  |  |  |  |  |  | User code <----Mode----->OS code | 
| 247 |  |  |  |  |  |  | /      \ | 
| 248 |  |  |  |  |  |  | /        \ | 
| 249 |  |  |  |  |  |  | /          \ | 
| 250 |  |  |  |  |  |  | User code  v            v OS code | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | .---.  .---. .---.  .---.    .---.  .---. | 
| 254 |  |  |  |  |  |  | OS API   '---'  '---' '---'  '---'    '---'  '---' | 
| 255 |  |  |  |  |  |  | |      |     |      |        |      | | 
| 256 |  |  |  |  |  |  | v      v     |      v        |      v | 
| 257 |  |  |  |  |  |  | .------------. | .-----------. |  .-----. | 
| 258 |  |  |  |  |  |  | | Filesystem | | | Scheduler | |  | MMU | | 
| 259 |  |  |  |  |  |  | '------------' | '-----------' |  '-----' | 
| 260 |  |  |  |  |  |  | |       |      |        | | 
| 261 |  |  |  |  |  |  | v       |      |        v | 
| 262 |  |  |  |  |  |  | .----.     |      |    .---------. | 
| 263 |  |  |  |  |  |  | | IO |<----'      |    | Network | | 
| 264 |  |  |  |  |  |  | '----'            |    '---------' | 
| 265 |  |  |  |  |  |  | |              |         | | 
| 266 |  |  |  |  |  |  | v              v         v | 
| 267 |  |  |  |  |  |  | .---------------------------------------. | 
| 268 |  |  |  |  |  |  | |                  HAL                  | | 
| 269 |  |  |  |  |  |  | '---------------------------------------' | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | .---------.  .---------. | 
| 275 |  |  |  |  |  |  | | State 1 |  | State 2 | | 
| 276 |  |  |  |  |  |  | '---------'  '---------' | 
| 277 |  |  |  |  |  |  | ^   \         ^  \ | 
| 278 |  |  |  |  |  |  | /     \       /    \ | 
| 279 |  |  |  |  |  |  | /       \     /      \ | 
| 280 |  |  |  |  |  |  | /         \   /        \ | 
| 281 |  |  |  |  |  |  | /           \ /          \ | 
| 282 |  |  |  |  |  |  | /             v            v | 
| 283 |  |  |  |  |  |  | ******        ******        ****** | 
| 284 |  |  |  |  |  |  | * T1 *        * T2 *        * T3 * | 
| 285 |  |  |  |  |  |  | ******        ******        ****** | 
| 286 |  |  |  |  |  |  | ^             ^             / | 
| 287 |  |  |  |  |  |  | \             \           / | 
| 288 |  |  |  |  |  |  | \             \         / | 
| 289 |  |  |  |  |  |  | \             \       / stimuli | 
| 290 |  |  |  |  |  |  | \             \     / | 
| 291 |  |  |  |  |  |  | \             \   v | 
| 292 |  |  |  |  |  |  | \         .---------. | 
| 293 |  |  |  |  |  |  | '--------| State 3 | | 
| 294 |  |  |  |  |  |  | '---------' | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | .--Base::Class::Derived_A | 
| 298 |  |  |  |  |  |  | / | 
| 299 |  |  |  |  |  |  | .----Base::Class::Derived_B | 
| 300 |  |  |  |  |  |  | Something--------.             /         \ | 
| 301 |  |  |  |  |  |  | \           /           '---Base::Class::Derived::More | 
| 302 |  |  |  |  |  |  | Something::else    \         /             \ | 
| 303 |  |  |  |  |  |  | \             \       /               '-Base::Class::Derived::Deeper | 
| 304 |  |  |  |  |  |  | \             \     / | 
| 305 |  |  |  |  |  |  | \             \   .-----------Base::Class::Derived_C | 
| 306 |  |  |  |  |  |  | \             \ / | 
| 307 |  |  |  |  |  |  | '-------Base::Class | 
| 308 |  |  |  |  |  |  | /   \ \ \ | 
| 309 |  |  |  |  |  |  | '     \ \ \ | 
| 310 |  |  |  |  |  |  | |      \ \ '---The::Latest | 
| 311 |  |  |  |  |  |  | /|       \ \      \ | 
| 312 |  |  |  |  |  |  | With::Some::fantasy' '        \ \      '----The::Latest::Greatest | 
| 313 |  |  |  |  |  |  | /|         \ \ | 
| 314 |  |  |  |  |  |  | More::Stuff' '          \ '-I::Am::Running::Out::Of::Ideas | 
| 315 |  |  |  |  |  |  | /|           \ | 
| 316 |  |  |  |  |  |  | More::Stuff' '            \ | 
| 317 |  |  |  |  |  |  | /              '---Last::One | 
| 318 |  |  |  |  |  |  | More::Stuff' | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | ____[] | 
| 322 |  |  |  |  |  |  | | ___ | | 
| 323 |  |  |  |  |  |  | ||   ||  device | 
| 324 |  |  |  |  |  |  | ||___||  loads | 
| 325 |  |  |  |  |  |  | | ooo |------------------------------------------------------------. | 
| 326 |  |  |  |  |  |  | | ooo |    |                          |                            | | 
| 327 |  |  |  |  |  |  | | ooo |    |                          |                            | | 
| 328 |  |  |  |  |  |  | '_____'    |                          |                            | | 
| 329 |  |  |  |  |  |  | |                          |                            | | 
| 330 |  |  |  |  |  |  | v                          v                            v | 
| 331 |  |  |  |  |  |  | .-------------------.  .---------------------------.    .-------------------. | 
| 332 |  |  |  |  |  |  | | Loadable module C |  |     Loadable module A     |    | Loadable module B | | 
| 333 |  |  |  |  |  |  | '-------------------'  |---------------------------|    |   (instrumented)  | | 
| 334 |  |  |  |  |  |  | |            |         .-----.           |    '-------------------' | 
| 335 |  |  |  |  |  |  | '--------------------->| A.o |           |              | | 
| 336 |  |  |  |  |  |  | calls    |         '-----'           |              | | 
| 337 |  |  |  |  |  |  | |    .------------------.   |              | | 
| 338 |  |  |  |  |  |  | |    | A.instrumented.o |<-----------------' | 
| 339 |  |  |  |  |  |  | |    '------------------'   |    calls | 
| 340 |  |  |  |  |  |  | '---------------------------' | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | =cut | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | sub new | 
| 346 |  |  |  |  |  |  | { | 
| 347 |  |  |  |  |  |  | my ($class) = @_ ; | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | my $self = | 
| 350 |  |  |  |  |  |  | bless | 
| 351 |  |  |  |  |  |  | { | 
| 352 |  |  |  |  |  |  | ELEMENT_TYPES => [], | 
| 353 |  |  |  |  |  |  | ELEMENTS => [], | 
| 354 |  |  |  |  |  |  | CONNECTIONS => [], | 
| 355 |  |  |  |  |  |  | CLIPBOARD => {}, | 
| 356 |  |  |  |  |  |  | FONT_FAMILY => 'Monospace', | 
| 357 |  |  |  |  |  |  | FONT_SIZE => '10', | 
| 358 |  |  |  |  |  |  | TAB_AS_SPACES => '   ', | 
| 359 |  |  |  |  |  |  | OPAQUE_ELEMENTS => 1, | 
| 360 |  |  |  |  |  |  | DISPLAY_GRID => 1, | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | PREVIOUS_X => -1, PREVIOUS_Y => -1, | 
| 363 |  |  |  |  |  |  | MOUSE_X => 0, MOUSE_Y => 0, | 
| 364 |  |  |  |  |  |  | DRAGGING => '', | 
| 365 |  |  |  |  |  |  | SELECTION_RECTANGLE =>{START_X => 0, START_Y => 0}, | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | KEYS => {K =>{}, C =>{},}, | 
| 368 |  |  |  |  |  |  | ACTIONS => {}, | 
| 369 |  |  |  |  |  |  | VALID_SELECT_ACTION => { map {$_, 1} qw(resize move)}, | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | COPY_OFFSET_X => 3, | 
| 372 |  |  |  |  |  |  | COPY_OFFSET_Y => 3, | 
| 373 |  |  |  |  |  |  | COLORS => | 
| 374 |  |  |  |  |  |  | { | 
| 375 |  |  |  |  |  |  | background => [255, 255, 255], | 
| 376 |  |  |  |  |  |  | grid => [229, 235, 255], | 
| 377 |  |  |  |  |  |  | ruler_line => [85, 155, 225], | 
| 378 |  |  |  |  |  |  | selected_element_background => [180, 244, 255], | 
| 379 |  |  |  |  |  |  | element_background => [251, 251, 254], | 
| 380 |  |  |  |  |  |  | element_foreground => [0, 0, 0] , | 
| 381 |  |  |  |  |  |  | selection_rectangle => [255, 0, 255], | 
| 382 |  |  |  |  |  |  | test => [0, 255, 255], | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | group_colors => | 
| 385 |  |  |  |  |  |  | [ | 
| 386 |  |  |  |  |  |  | [[250, 221, 190], [250, 245, 239]], | 
| 387 |  |  |  |  |  |  | [[182, 250, 182], [241, 250, 241]], | 
| 388 |  |  |  |  |  |  | [[185, 219, 250], [244, 247, 250]], | 
| 389 |  |  |  |  |  |  | [[137, 250, 250], [235, 250, 250]], | 
| 390 |  |  |  |  |  |  | [[198, 229, 198], [239, 243, 239]], | 
| 391 |  |  |  |  |  |  | ], | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | connection => 'Chocolate', | 
| 394 |  |  |  |  |  |  | connection_point => [230, 198, 133], | 
| 395 |  |  |  |  |  |  | connector_point => 'DodgerBlue', | 
| 396 |  |  |  |  |  |  | new_connection => 'red' , | 
| 397 |  |  |  |  |  |  | extra_point => [230, 198, 133], | 
| 398 |  |  |  |  |  |  | }, | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | NEXT_GROUP_COLOR => 0, | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  | WORK_DIRECTORY => '.asciio_work_dir', | 
| 403 |  |  |  |  |  |  | CREATE_BACKUP => 1, | 
| 404 |  |  |  |  |  |  | MODIFIED => 0, | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | DO_STACK_POINTER => 0, | 
| 407 |  |  |  |  |  |  | DO_STACK => [] , | 
| 408 |  |  |  |  |  |  | }, $class ; | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | return($self) ; | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | sub event_options_changed | 
| 416 |  |  |  |  |  |  | { | 
| 417 |  |  |  |  |  |  | my ($self) = @_; | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | my $number_of_group_colors = scalar(@{$self->{COLORS}{group_colors}}) ; | 
| 420 |  |  |  |  |  |  | $self->{GROUP_COLORS} = [0 .. $number_of_group_colors - 1] , | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | $self->{CURRENT_ACTIONS} = $self->{ACTIONS}  ; | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | $self->set_font($self->{FONT_FAMILY}, $self->{FONT_SIZE}); | 
| 425 |  |  |  |  |  |  | } | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  |  | 
| 429 |  |  |  |  |  |  | sub set_title | 
| 430 |  |  |  |  |  |  | { | 
| 431 |  |  |  |  |  |  | my ($self, $title) = @_; | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | if(defined $title) | 
| 434 |  |  |  |  |  |  | { | 
| 435 |  |  |  |  |  |  | $self->{TITLE} = $title ; | 
| 436 |  |  |  |  |  |  | } | 
| 437 |  |  |  |  |  |  | } | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | sub get_title | 
| 440 |  |  |  |  |  |  | { | 
| 441 |  |  |  |  |  |  | my ($self) = @_; | 
| 442 |  |  |  |  |  |  | $self->{TITLE} ; | 
| 443 |  |  |  |  |  |  | } | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | sub set_font | 
| 448 |  |  |  |  |  |  | { | 
| 449 |  |  |  |  |  |  | my ($self, $font_family, $font_size) = @_; | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | $self->{FONT_FAMILY} = $font_family || 'Monospace'; | 
| 452 |  |  |  |  |  |  | $self->{FONT_SIZE} = $font_size || 10 ; | 
| 453 |  |  |  |  |  |  | } | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | sub get_font | 
| 456 |  |  |  |  |  |  | { | 
| 457 |  |  |  |  |  |  | my ($self) = @_; | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | return($self->{FONT_FAMILY},  $self->{FONT_SIZE}) ; | 
| 460 |  |  |  |  |  |  | } | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | sub update_display | 
| 465 |  |  |  |  |  |  | { | 
| 466 |  |  |  |  |  |  | my ($self) = @_; | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | $self->call_hook('CANONIZE_CONNECTIONS', $self->{CONNECTIONS}, $self->get_character_size()) ; | 
| 469 |  |  |  |  |  |  | } | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | sub get_grid_usage | 
| 472 |  |  |  |  |  |  | { | 
| 473 |  |  |  |  |  |  | my ($self) = @_; | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | my %cost_map ; | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | for my $element (@{$self->{ELEMENTS}}) | 
| 480 |  |  |  |  |  |  | { | 
| 481 |  |  |  |  |  |  | for my $mask_and_element_strip ($element->get_mask_and_element_stripes()) | 
| 482 |  |  |  |  |  |  | { | 
| 483 |  |  |  |  |  |  | my $x_offset = $element->{X} + $mask_and_element_strip->{X_OFFSET} ; | 
| 484 |  |  |  |  |  |  | my $y_offset = $element->{Y} + $mask_and_element_strip->{Y_OFFSET} ; | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | my $string_offset = 0 ; | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | for my $string ( split /\n/, $mask_and_element_strip->{TEXT}) | 
| 489 |  |  |  |  |  |  | { | 
| 490 |  |  |  |  |  |  | for (0 .. length($string) - 1 ) | 
| 491 |  |  |  |  |  |  | { | 
| 492 |  |  |  |  |  |  | my $x_offset_line = $x_offset + $_ ; | 
| 493 |  |  |  |  |  |  | my $y_offset_line = ($y_offset + $string_offset)  ; | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | $cost_map{"$x_offset_line.$y_offset_line"} = 0 ; | 
| 496 |  |  |  |  |  |  | } | 
| 497 |  |  |  |  |  |  |  | 
| 498 |  |  |  |  |  |  | $string_offset++ ; | 
| 499 |  |  |  |  |  |  | } | 
| 500 |  |  |  |  |  |  | } | 
| 501 |  |  |  |  |  |  | } | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  | return \%cost_map ; | 
| 504 |  |  |  |  |  |  | } | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | sub call_hook | 
| 509 |  |  |  |  |  |  | { | 
| 510 |  |  |  |  |  |  | my ($self, $hook_name,  @arguments) = @_; | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | $self->{HOOKS}{$hook_name}->(@arguments)  if (exists $self->{HOOKS}{$hook_name}) ; | 
| 513 |  |  |  |  |  |  | } | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | sub button_release_event | 
| 519 |  |  |  |  |  |  | { | 
| 520 |  |  |  |  |  |  | my ($self, $event) = @_ ; | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | my $modifiers = $event->{MODIFIERS} ; | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | if($self->exists_action("${modifiers}-button_release")) | 
| 525 |  |  |  |  |  |  | { | 
| 526 |  |  |  |  |  |  | $self->run_actions(["${modifiers}-button_release", $event]) ; | 
| 527 |  |  |  |  |  |  | return 1 ; | 
| 528 |  |  |  |  |  |  | } | 
| 529 |  |  |  |  |  |  |  | 
| 530 |  |  |  |  |  |  | if(defined $self->{MODIFIED_INDEX} && defined $self->{MODIFIED} && $self->{MODIFIED_INDEX} == $self->{MODIFIED}) | 
| 531 |  |  |  |  |  |  | { | 
| 532 |  |  |  |  |  |  | $self->pop_undo_buffer(1) ; | 
| 533 |  |  |  |  |  |  | } | 
| 534 |  |  |  |  |  |  |  | 
| 535 |  |  |  |  |  |  | $self->update_display(); | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  |  | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | sub button_press_event | 
| 541 |  |  |  |  |  |  | { | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | my ($self, $event, $wrapper_event) = @_ ; | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | $self->{DRAGGING} = '' ; | 
| 546 |  |  |  |  |  |  | delete $self->{RESIZE_CONNECTOR_NAME} ; | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | $self->create_undo_snapshot() ; | 
| 549 |  |  |  |  |  |  | $self->{MODIFIED_INDEX} = $self->{MODIFIED} ; | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | my $modifiers = $event->{MODIFIERS} ; | 
| 552 |  |  |  |  |  |  | my $button = $event->{BUTTON} ; | 
| 553 |  |  |  |  |  |  |  | 
| 554 |  |  |  |  |  |  | if($self->exists_action("${modifiers}-button_press-$button")) | 
| 555 |  |  |  |  |  |  | { | 
| 556 |  |  |  |  |  |  | $self->run_actions(["${modifiers}-button_press-$button", $event]) ; | 
| 557 |  |  |  |  |  |  | return 1 ; | 
| 558 |  |  |  |  |  |  | } | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | my($x, $y) = @{$event->{COORDINATES}} ; | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | if($event->{TYPE} eq '2button-press') | 
| 563 |  |  |  |  |  |  | { | 
| 564 |  |  |  |  |  |  | my @element_over = grep { $self->is_over_element($_, $x, $y) } reverse @{$self->{ELEMENTS}} ; | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | if(@element_over) | 
| 567 |  |  |  |  |  |  | { | 
| 568 |  |  |  |  |  |  | my $selected_element = $element_over[0] ; | 
| 569 |  |  |  |  |  |  | $self->edit_element($selected_element) ; | 
| 570 |  |  |  |  |  |  | $self->update_display(); | 
| 571 |  |  |  |  |  |  | } | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | return 1 ; | 
| 574 |  |  |  |  |  |  | } | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | if($event->{BUTTON} == 1) | 
| 577 |  |  |  |  |  |  | { | 
| 578 |  |  |  |  |  |  | my $modifiers = $event->{MODIFIERS} ; | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | my ($first_element) = first_value {$self->is_over_element($_, $x, $y)} reverse @{$self->{ELEMENTS}} ; | 
| 581 |  |  |  |  |  |  |  | 
| 582 |  |  |  |  |  |  | if ($modifiers eq 'C00') | 
| 583 |  |  |  |  |  |  | { | 
| 584 |  |  |  |  |  |  | if(defined $first_element) | 
| 585 |  |  |  |  |  |  | { | 
| 586 |  |  |  |  |  |  | $self->run_actions_by_name('Copy to clipboard', ['Insert from clipboard', 0, 0])  ; | 
| 587 |  |  |  |  |  |  | } | 
| 588 |  |  |  |  |  |  | } | 
| 589 |  |  |  |  |  |  | else | 
| 590 |  |  |  |  |  |  | { | 
| 591 |  |  |  |  |  |  | if(defined $first_element) | 
| 592 |  |  |  |  |  |  | { | 
| 593 |  |  |  |  |  |  | if ($modifiers eq '00S') | 
| 594 |  |  |  |  |  |  | { | 
| 595 |  |  |  |  |  |  | $self->select_elements_flip($first_element) ; | 
| 596 |  |  |  |  |  |  | } | 
| 597 |  |  |  |  |  |  | else | 
| 598 |  |  |  |  |  |  | { | 
| 599 |  |  |  |  |  |  | unless($self->is_element_selected($first_element)) | 
| 600 |  |  |  |  |  |  | { | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | $self->select_elements(0, @{$self->{ELEMENTS}}) ; | 
| 603 |  |  |  |  |  |  | $self->select_elements(1, $first_element) ; | 
| 604 |  |  |  |  |  |  | } | 
| 605 |  |  |  |  |  |  | } | 
| 606 |  |  |  |  |  |  | } | 
| 607 |  |  |  |  |  |  | else | 
| 608 |  |  |  |  |  |  | { | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | $self->deselect_all_elements()  if ($modifiers eq '000')  ; | 
| 611 |  |  |  |  |  |  | } | 
| 612 |  |  |  |  |  |  | } | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | $self->{SELECTION_RECTANGLE} = {START_X => $x , START_Y => $y} ; | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | $self->update_display(); | 
| 617 |  |  |  |  |  |  | } | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | if($event->{BUTTON} == 2) | 
| 620 |  |  |  |  |  |  | { | 
| 621 |  |  |  |  |  |  | $self->{SELECTION_RECTANGLE} = {START_X => $x , START_Y => $y} ; | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | $self->update_display(); | 
| 624 |  |  |  |  |  |  | } | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | if($event->{BUTTON} == 3) | 
| 627 |  |  |  |  |  |  | { | 
| 628 |  |  |  |  |  |  | $self->display_popup_menu($wrapper_event) ; | 
| 629 |  |  |  |  |  |  | } | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | return 1; | 
| 632 |  |  |  |  |  |  | } | 
| 633 |  |  |  |  |  |  |  | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | sub motion_notify_event | 
| 637 |  |  |  |  |  |  | { | 
| 638 |  |  |  |  |  |  | my ($self, $event) = @_ ; | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | my($x, $y) = @{$event->{COORDINATES}} ; | 
| 641 |  |  |  |  |  |  | my $modifiers = $event->{MODIFIERS} ; | 
| 642 |  |  |  |  |  |  | my $button = $event->{BUTTON} ; | 
| 643 |  |  |  |  |  |  |  | 
| 644 |  |  |  |  |  |  | if($self->exists_action("${modifiers}motion_notify")) | 
| 645 |  |  |  |  |  |  | { | 
| 646 |  |  |  |  |  |  | $self->run_actions(["${modifiers}-motion_notify", $event]) ; | 
| 647 |  |  |  |  |  |  | return 1 ; | 
| 648 |  |  |  |  |  |  | } | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | if($self->{PREVIOUS_X} != $x || $self->{PREVIOUS_Y} != $y) | 
| 651 |  |  |  |  |  |  | { | 
| 652 |  |  |  |  |  |  | ($self->{MOUSE_X}, $self->{MOUSE_Y}) = ($x, $y) ; | 
| 653 |  |  |  |  |  |  | $self->update_display() ; | 
| 654 |  |  |  |  |  |  | } | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | if ($event->{STATE} >= "button1-mask") | 
| 657 |  |  |  |  |  |  | { | 
| 658 |  |  |  |  |  |  | if($self->{DRAGGING} ne '') | 
| 659 |  |  |  |  |  |  | { | 
| 660 |  |  |  |  |  |  | if      ($self->{DRAGGING} eq 'move') { $self->move_elements_event($x, $y) ; } | 
| 661 |  |  |  |  |  |  | elsif ($self->{DRAGGING}eq 'resize') { $self->resize_element_event($x, $y) ; } | 
| 662 |  |  |  |  |  |  | elsif ($self->{DRAGGING}eq 'select') { $self->select_element_event($x, $y) ; } | 
| 663 |  |  |  |  |  |  | } | 
| 664 |  |  |  |  |  |  | else | 
| 665 |  |  |  |  |  |  | { | 
| 666 |  |  |  |  |  |  | my @selected_elements = $self->get_selected_elements(1) ; | 
| 667 |  |  |  |  |  |  | my ($first_element) = first_value {$self->is_over_element($_, $x, $y)} reverse @selected_elements ; | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | if(@selected_elements > 1) | 
| 670 |  |  |  |  |  |  | { | 
| 671 |  |  |  |  |  |  | if(defined $first_element) | 
| 672 |  |  |  |  |  |  | { | 
| 673 |  |  |  |  |  |  | $self->{DRAGGING} = 'move' ; | 
| 674 |  |  |  |  |  |  | } | 
| 675 |  |  |  |  |  |  | else | 
| 676 |  |  |  |  |  |  | { | 
| 677 |  |  |  |  |  |  | $self->{DRAGGING} = 'select' ; | 
| 678 |  |  |  |  |  |  | } | 
| 679 |  |  |  |  |  |  | } | 
| 680 |  |  |  |  |  |  | else | 
| 681 |  |  |  |  |  |  | { | 
| 682 |  |  |  |  |  |  | if(defined $first_element) | 
| 683 |  |  |  |  |  |  | { | 
| 684 |  |  |  |  |  |  | $self->{DRAGGING} = $first_element->get_selection_action | 
| 685 |  |  |  |  |  |  | ( | 
| 686 |  |  |  |  |  |  | $x - $first_element->{X}, | 
| 687 |  |  |  |  |  |  | $y - $first_element->{Y}, | 
| 688 |  |  |  |  |  |  | ); | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | $self->{DRAGGING} ='' unless exists $self->{VALID_SELECT_ACTION}{$self->{DRAGGING}} ; | 
| 691 |  |  |  |  |  |  | } | 
| 692 |  |  |  |  |  |  | else | 
| 693 |  |  |  |  |  |  | { | 
| 694 |  |  |  |  |  |  | $self->{DRAGGING} = 'select' ; | 
| 695 |  |  |  |  |  |  | } | 
| 696 |  |  |  |  |  |  | } | 
| 697 |  |  |  |  |  |  |  | 
| 698 |  |  |  |  |  |  | ($self->{PREVIOUS_X}, $self->{PREVIOUS_Y}) = ($x, $y) ; | 
| 699 |  |  |  |  |  |  | } | 
| 700 |  |  |  |  |  |  | } | 
| 701 |  |  |  |  |  |  |  | 
| 702 |  |  |  |  |  |  | if ($event->{STATE} >= "button2-mask") | 
| 703 |  |  |  |  |  |  | { | 
| 704 |  |  |  |  |  |  | $self->select_element_event($x, $y, $self->{MIDDLE_BUTTON_SELECTION_FILTER} || sub{1}) ; | 
| 705 |  |  |  |  |  |  | } | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | return 1; | 
| 708 |  |  |  |  |  |  | } | 
| 709 |  |  |  |  |  |  |  | 
| 710 |  |  |  |  |  |  |  | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | sub select_element_event | 
| 713 |  |  |  |  |  |  | { | 
| 714 |  |  |  |  |  |  | my ($self, $x, $y, $filter) = @_ ; | 
| 715 |  |  |  |  |  |  |  | 
| 716 |  |  |  |  |  |  | my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X},  $y - $self->{PREVIOUS_Y}) ; | 
| 717 |  |  |  |  |  |  |  | 
| 718 |  |  |  |  |  |  | if($x_offset != 0 || $y_offset != 0) | 
| 719 |  |  |  |  |  |  | { | 
| 720 |  |  |  |  |  |  | $self->{SELECTION_RECTANGLE}{END_X} = $x ; | 
| 721 |  |  |  |  |  |  | $self->{SELECTION_RECTANGLE}{END_Y} = $y ; | 
| 722 |  |  |  |  |  |  |  | 
| 723 |  |  |  |  |  |  | $filter = sub {1} unless defined $filter ; | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | $self->select_elements | 
| 726 |  |  |  |  |  |  | ( | 
| 727 |  |  |  |  |  |  | 1, | 
| 728 |  |  |  |  |  |  | grep | 
| 729 |  |  |  |  |  |  | { $filter->($_) } | 
| 730 |  |  |  |  |  |  | grep | 
| 731 |  |  |  |  |  |  | { | 
| 732 |  |  |  |  |  |  | $self->element_completely_within_rectangle | 
| 733 |  |  |  |  |  |  | ( | 
| 734 |  |  |  |  |  |  | $_, | 
| 735 |  |  |  |  |  |  | $self->{SELECTION_RECTANGLE}, | 
| 736 |  |  |  |  |  |  | ) | 
| 737 |  |  |  |  |  |  | } @{$self->{ELEMENTS}} | 
| 738 |  |  |  |  |  |  | )  ; | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | $self->update_display(); | 
| 741 |  |  |  |  |  |  |  | 
| 742 |  |  |  |  |  |  | ($self->{PREVIOUS_X}, $self->{PREVIOUS_Y}) = ($x, $y) ; | 
| 743 |  |  |  |  |  |  | } | 
| 744 |  |  |  |  |  |  | } | 
| 745 |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  |  | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  | sub move_elements_event | 
| 749 |  |  |  |  |  |  | { | 
| 750 |  |  |  |  |  |  | my ($self, $x, $y) = @_; | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X},  $y - $self->{PREVIOUS_Y}) ; | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | if($x_offset != 0 || $y_offset != 0) | 
| 755 |  |  |  |  |  |  | { | 
| 756 |  |  |  |  |  |  | my @selected_elements = $self->get_selected_elements(1) ; | 
| 757 |  |  |  |  |  |  |  | 
| 758 |  |  |  |  |  |  | $self->move_elements($x_offset, $y_offset, @selected_elements) ; | 
| 759 |  |  |  |  |  |  | $self->update_display(); | 
| 760 |  |  |  |  |  |  |  | 
| 761 |  |  |  |  |  |  | ($self->{PREVIOUS_X}, $self->{PREVIOUS_Y}) = ($x, $y) ; | 
| 762 |  |  |  |  |  |  | } | 
| 763 |  |  |  |  |  |  | } | 
| 764 |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  |  | 
| 767 |  |  |  |  |  |  | sub resize_element_event | 
| 768 |  |  |  |  |  |  | { | 
| 769 |  |  |  |  |  |  | my ($self, $x, $y) = @_ ; | 
| 770 |  |  |  |  |  |  |  | 
| 771 |  |  |  |  |  |  | my ($x_offset, $y_offset) = ($x - $self->{PREVIOUS_X},  $y - $self->{PREVIOUS_Y}) ; | 
| 772 |  |  |  |  |  |  |  | 
| 773 |  |  |  |  |  |  | if($x_offset != 0 || $y_offset != 0) | 
| 774 |  |  |  |  |  |  | { | 
| 775 |  |  |  |  |  |  | my ($selected_element) = $self->get_selected_elements(1) ; | 
| 776 |  |  |  |  |  |  |  | 
| 777 |  |  |  |  |  |  | $self->{RESIZE_CONNECTOR_NAME} = | 
| 778 |  |  |  |  |  |  | $self->resize_element | 
| 779 |  |  |  |  |  |  | ( | 
| 780 |  |  |  |  |  |  | $self->{PREVIOUS_X} - $selected_element->{X}, $self->{PREVIOUS_Y} - $selected_element->{Y} , | 
| 781 |  |  |  |  |  |  | $x - $selected_element->{X}, $y - $selected_element->{Y} , | 
| 782 |  |  |  |  |  |  | $selected_element, | 
| 783 |  |  |  |  |  |  | $self->{RESIZE_CONNECTOR_NAME}, | 
| 784 |  |  |  |  |  |  | ) ; | 
| 785 |  |  |  |  |  |  |  | 
| 786 |  |  |  |  |  |  | $self->update_display(); | 
| 787 |  |  |  |  |  |  |  | 
| 788 |  |  |  |  |  |  | ($self->{PREVIOUS_X}, $self->{PREVIOUS_Y}) = ($x, $y) ; | 
| 789 |  |  |  |  |  |  | } | 
| 790 |  |  |  |  |  |  | } | 
| 791 |  |  |  |  |  |  |  | 
| 792 |  |  |  |  |  |  |  | 
| 793 |  |  |  |  |  |  |  | 
| 794 |  |  |  |  |  |  | sub key_press_event | 
| 795 |  |  |  |  |  |  | { | 
| 796 |  |  |  |  |  |  | my ($self, $event)= @_; | 
| 797 |  |  |  |  |  |  |  | 
| 798 |  |  |  |  |  |  | my $modifiers = $event->{MODIFIERS} ; | 
| 799 |  |  |  |  |  |  | my $key = $self->{KEYS}{C}{$event->{KEY_VALUE}} ; | 
| 800 |  |  |  |  |  |  |  | 
| 801 |  |  |  |  |  |  | $self->run_actions("$modifiers-$key") ; | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  | return 0 ; | 
| 804 |  |  |  |  |  |  | } | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  |  | 
| 807 |  |  |  |  |  |  |  | 
| 808 |  |  |  |  |  |  | sub get_character_size | 
| 809 |  |  |  |  |  |  | { | 
| 810 |  |  |  |  |  |  | my ($self) = @_ ; | 
| 811 |  |  |  |  |  |  |  | 
| 812 |  |  |  |  |  |  | if(exists $self->{USER_CHARACTER_WIDTH}) | 
| 813 |  |  |  |  |  |  | { | 
| 814 |  |  |  |  |  |  | return ($self->{USER_CHARACTER_WIDTH}, $self->{USER_CHARACTER_HEIGHT}) ; | 
| 815 |  |  |  |  |  |  | } | 
| 816 |  |  |  |  |  |  | else | 
| 817 |  |  |  |  |  |  | { | 
| 818 |  |  |  |  |  |  | return (8, 16) ; | 
| 819 |  |  |  |  |  |  | } | 
| 820 |  |  |  |  |  |  | } | 
| 821 |  |  |  |  |  |  |  | 
| 822 |  |  |  |  |  |  |  | 
| 823 |  |  |  |  |  |  |  | 
| 824 |  |  |  |  |  |  | sub set_character_size | 
| 825 |  |  |  |  |  |  | { | 
| 826 |  |  |  |  |  |  | my ($self, $width, $height) = @_ ; | 
| 827 |  |  |  |  |  |  |  | 
| 828 |  |  |  |  |  |  | ($self->{USER_CHARACTER_WIDTH}, $self->{USER_CHARACTER_HEIGHT}) = ($width, $height) ; | 
| 829 |  |  |  |  |  |  | } | 
| 830 |  |  |  |  |  |  |  | 
| 831 |  |  |  |  |  |  |  | 
| 832 |  |  |  |  |  |  |  | 
| 833 |  |  |  |  |  |  | sub get_color | 
| 834 |  |  |  |  |  |  | { | 
| 835 |  |  |  |  |  |  | my ($self, $name) = @_; | 
| 836 |  |  |  |  |  |  |  | 
| 837 |  |  |  |  |  |  | unless (exists $self->{ALLOCATED_COLORS}{$name}) | 
| 838 |  |  |  |  |  |  | { | 
| 839 |  |  |  |  |  |  | my $color  = [255, 0, 0]; | 
| 840 |  |  |  |  |  |  |  | 
| 841 |  |  |  |  |  |  | $self->{ALLOCATED_COLORS}{$name} = $color ; | 
| 842 |  |  |  |  |  |  | } | 
| 843 |  |  |  |  |  |  |  | 
| 844 |  |  |  |  |  |  | return($self->{ALLOCATED_COLORS}{$name}) ; | 
| 845 |  |  |  |  |  |  | } | 
| 846 |  |  |  |  |  |  |  | 
| 847 |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  |  | 
| 849 |  |  |  |  |  |  | sub flush_color_cache | 
| 850 |  |  |  |  |  |  | { | 
| 851 |  |  |  |  |  |  | my ($self) = @_ ; | 
| 852 |  |  |  |  |  |  | delete $self->{ALLOCATED_COLORS} ; | 
| 853 |  |  |  |  |  |  | } | 
| 854 |  |  |  |  |  |  |  | 
| 855 |  |  |  |  |  |  |  | 
| 856 |  |  |  |  |  |  |  | 
| 857 |  |  |  |  |  |  |  | 
| 858 |  |  |  |  |  |  | =head1 DEPENDENCIES | 
| 859 |  |  |  |  |  |  |  | 
| 860 |  |  |  |  |  |  | gnome libraries, gtk, gtk-perl for the gtk version | 
| 861 |  |  |  |  |  |  |  | 
| 862 |  |  |  |  |  |  | =head1 BUGS AND LIMITATIONS | 
| 863 |  |  |  |  |  |  |  | 
| 864 |  |  |  |  |  |  | Undoubtedly many as I wrote this as a fun little project where I used no design nor 'methodic' whatsoever. | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | =head1 AUTHOR | 
| 867 |  |  |  |  |  |  |  | 
| 868 |  |  |  |  |  |  | Khemir Nadim ibn Hamouda | 
| 869 |  |  |  |  |  |  | CPAN ID: NKH | 
| 870 |  |  |  |  |  |  | mailto:nadim@khemir.net | 
| 871 |  |  |  |  |  |  |  | 
| 872 |  |  |  |  |  |  | =head1 LICENSE AND COPYRIGHT | 
| 873 |  |  |  |  |  |  |  | 
| 874 |  |  |  |  |  |  | This program is free software; you can redistribute | 
| 875 |  |  |  |  |  |  | it and/or modify it under the same terms as Perl itself. | 
| 876 |  |  |  |  |  |  |  | 
| 877 |  |  |  |  |  |  | =head1 SUPPORTED OSes | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | =head2 Gentoo | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | I run gentoo, packages to install gtk-perl exist. Install Asciio with cpan. | 
| 882 |  |  |  |  |  |  |  | 
| 883 |  |  |  |  |  |  | =head2 FreeBSD | 
| 884 |  |  |  |  |  |  |  | 
| 885 |  |  |  |  |  |  | FreeBSD users can now install asciio either by package: | 
| 886 |  |  |  |  |  |  |  | 
| 887 |  |  |  |  |  |  | $ pkg_add -r asciio | 
| 888 |  |  |  |  |  |  |  | 
| 889 |  |  |  |  |  |  | or from source (out of the ports system) by: | 
| 890 |  |  |  |  |  |  |  | 
| 891 |  |  |  |  |  |  | $ cd /usr/ports/graphics/asciio | 
| 892 |  |  |  |  |  |  | $ make install clean | 
| 893 |  |  |  |  |  |  |  | 
| 894 |  |  |  |  |  |  | Thanks to Emanuel Haupt. | 
| 895 |  |  |  |  |  |  |  | 
| 896 |  |  |  |  |  |  | =head2 Ubuntu and Debian | 
| 897 |  |  |  |  |  |  |  | 
| 898 |  |  |  |  |  |  | Ports are on the way. | 
| 899 |  |  |  |  |  |  |  | 
| 900 |  |  |  |  |  |  | =head2 Windows | 
| 901 |  |  |  |  |  |  |  | 
| 902 |  |  |  |  |  |  | B<Asciio> is part of the B<camelbox> distribution and can be found here: L<http://code.google.com/p/camelbox/>. Install, run AsciiO from the 'bin' directory. | 
| 903 |  |  |  |  |  |  |  | 
| 904 |  |  |  |  |  |  | .-------------------------------. | 
| 905 |  |  |  |  |  |  | /                               /| | 
| 906 |  |  |  |  |  |  | /     camelbox for win32        / | | 
| 907 |  |  |  |  |  |  | /                               /  | | 
| 908 |  |  |  |  |  |  | /                               /   | | 
| 909 |  |  |  |  |  |  | .-------------------------------.    | | 
| 910 |  |  |  |  |  |  | |  ______\\_,                   |    | | 
| 911 |  |  |  |  |  |  | | (_. _ o_ _/                   |    | | 
| 912 |  |  |  |  |  |  | |  '-' \_. /                    |    | | 
| 913 |  |  |  |  |  |  | |      /  /                     |    | | 
| 914 |  |  |  |  |  |  | |     /  /    .--.  .--.        |    | | 
| 915 |  |  |  |  |  |  | |    (  (    / '' \/ '' \   "   |    | | 
| 916 |  |  |  |  |  |  | |     \  \_.'            \   )  |    | | 
| 917 |  |  |  |  |  |  | |     ||               _  './   |    | | 
| 918 |  |  |  |  |  |  | |      |\   \     ___.'\  /     |    | | 
| 919 |  |  |  |  |  |  | |        '-./   .'    \ |/      |    | | 
| 920 |  |  |  |  |  |  | |           \| /       )|\      |    | | 
| 921 |  |  |  |  |  |  | |            |/       // \\     |    . | 
| 922 |  |  |  |  |  |  | |            |\    __//   \\__  |   / | 
| 923 |  |  |  |  |  |  | |           //\\  /__/  mrf\__| |  / | 
| 924 |  |  |  |  |  |  | |       .--_/  \_--.            | / | 
| 925 |  |  |  |  |  |  | |      /__/      \__\           |/ | 
| 926 |  |  |  |  |  |  | '-------------------------------' | 
| 927 |  |  |  |  |  |  |  | 
| 928 |  |  |  |  |  |  | B<camelbox> is a great distribution for windows. I hope it will merge with X-berry series of Perl distributions. | 
| 929 |  |  |  |  |  |  |  | 
| 930 |  |  |  |  |  |  | =head1 Mac OsX | 
| 931 |  |  |  |  |  |  |  | 
| 932 |  |  |  |  |  |  | This works too (and I have screenshots to prove it :). I don't own a mac and the mac user hasn't send me how to do it yet. | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | =head1 other unices | 
| 935 |  |  |  |  |  |  |  | 
| 936 |  |  |  |  |  |  | YMMV, install gtk-perl and AsciiO from cpan. | 
| 937 |  |  |  |  |  |  |  | 
| 938 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 939 |  |  |  |  |  |  |  | 
| 940 |  |  |  |  |  |  | http://www.jave.de | 
| 941 |  |  |  |  |  |  | http://search.cpan.org/~osfameron/Text-JavE-0.0.2/JavE.pm | 
| 942 |  |  |  |  |  |  | http://ditaa.sourceforge.net/ | 
| 943 |  |  |  |  |  |  | http://www.codeproject.com/KB/macros/codeplotter.aspx | 
| 944 |  |  |  |  |  |  | http://search.cpan.org/~jpierce/Text-FIGlet-1.06/FIGlet.pm | 
| 945 |  |  |  |  |  |  | http://www.fossildraw.com/?gclid=CLanxZXxoJECFRYYEAodnBS8Dg (doesn't always respond) | 
| 946 |  |  |  |  |  |  |  | 
| 947 |  |  |  |  |  |  | http://www.ascii-art.de (used some entries as base for the network stencil) | 
| 948 |  |  |  |  |  |  | http://c2.com/cgi/wiki?UmlAsciiArt | 
| 949 |  |  |  |  |  |  | http://www.textfiles.com/art/ | 
| 950 |  |  |  |  |  |  | http://www2.b3ta.com/_bunny/texbunny.gif | 
| 951 |  |  |  |  |  |  |  | 
| 952 |  |  |  |  |  |  |  | 
| 953 |  |  |  |  |  |  | *\o_               _o/* | 
| 954 |  |  |  |  |  |  | /  *             *  \ | 
| 955 |  |  |  |  |  |  | <\       *\o/*       /> | 
| 956 |  |  |  |  |  |  | ) | 
| 957 |  |  |  |  |  |  | o/*   / >    *\o | 
| 958 |  |  |  |  |  |  | <\            /> | 
| 959 |  |  |  |  |  |  | __o     */\          /\*     o__ | 
| 960 |  |  |  |  |  |  | * />                        <\ * | 
| 961 |  |  |  |  |  |  | /\*    __o_       _o__     */\ | 
| 962 |  |  |  |  |  |  | * /  *     *  \ * | 
| 963 |  |  |  |  |  |  | <\           /> | 
| 964 |  |  |  |  |  |  | *\o/* | 
| 965 |  |  |  |  |  |  | ejm97        __)__ | 
| 966 |  |  |  |  |  |  |  | 
| 967 |  |  |  |  |  |  | =cut | 
| 968 |  |  |  |  |  |  |  | 
| 969 |  |  |  |  |  |  |  | 
| 970 |  |  |  |  |  |  |  | 
| 971 |  |  |  |  |  |  | "ASCII world domination!"  ; | 
| 972 |  |  |  |  |  |  |  | 
| 973 |  |  |  |  |  |  |  |