1#lang racket/base 2 3(require racket/contract 4 racket/unit 5 racket/class 6 racket/path 7 racket/port 8 racket/list 9 racket/match 10 racket/format 11 string-constants 12 framework 13 framework/private/srcloc-panel 14 mrlib/name-message 15 mrlib/switchable-button 16 mrlib/cache-image-snip 17 (prefix-in image-core: mrlib/image-core) 18 mrlib/close-icon 19 mrlib/panel-wob 20 net/sendurl 21 net/url 22 23 drracket/private/drsig 24 "insulated-read-language.rkt" 25 "insert-large-letters.rkt" 26 "get-defs.rkt" 27 "local-member-names.rkt" 28 "eval-helpers-and-pref-init.rkt" 29 "parse-logger-args.rkt" 30 drracket/get-module-path 31 "named-undefined.rkt" 32 (prefix-in drracket:arrow: "../arrow.rkt") 33 (prefix-in icons: images/compile-time) 34 mred 35 (prefix-in mred: mred) 36 37 mzlib/date 38 39 framework/private/aspell 40 framework/private/logging-timer 41 42 setup/collects 43 scribble/xref 44 setup/xref 45 scribble/tag 46 (only-in scribble/base doc-prefix)) 47 48(provide unit@) 49 50(define define-menu-configure (string-constant define-menu-configure)) 51 52(define module-browser-progress-constant (string-constant module-browser-progress)) 53(define status-compiling-definitions (string-constant module-browser-compiling-defns)) 54(define show-lib-paths (string-constant module-browser-show-lib-paths/short)) 55(define show-planet-paths (string-constant module-browser-show-planet-paths/short)) 56(define refresh (string-constant module-browser-refresh)) 57 58(define oprintf 59 (let ([op (current-output-port)]) 60 (λ args 61 (apply fprintf op args)))) 62 63;; =================================================================================================== 64;; Compiled bitmaps 65 66(require (for-syntax 67 racket/base 68 (prefix-in icons: (combine-in images/icons/file images/icons/control images/icons/style 69 images/icons/stickman images/logos)))) 70 71(define execute-bitmap 72 (icons:compiled-bitmap (icons:play-icon #:color icons:run-icon-color 73 #:height (icons:toolbar-icon-height)))) 74(define break-bitmap 75 (icons:compiled-bitmap (icons:stop-icon #:color icons:halt-icon-color 76 #:height (icons:toolbar-icon-height)))) 77(define small-save-bitmap 78 (icons:compiled-bitmap (icons:small-save-icon #:height (icons:toolbar-icon-height)))) 79(define save-bitmap 80 (icons:compiled-bitmap (icons:save-icon #:height (icons:toolbar-icon-height)))) 81 82(begin-for-syntax 83 (define stickman-height 18) 84 (define num-running-frames 12)) 85 86(define running-frame-list 87 (icons:compiled-bitmap-list 88 (for/list ([t (in-range 0 1 (/ 1 num-running-frames))]) 89 (icons:running-stickman-icon t #:height stickman-height)))) 90(define running-frames (list->vector running-frame-list)) 91 92(define standing-frame 93 (icons:compiled-bitmap 94 (icons:standing-stickman-icon #:height stickman-height))) 95 96(define very-small-planet-bitmap 97 (icons:compiled-bitmap (icons:planet-logo #:height (icons:toolbar-icon-height)))) 98 99;; =================================================================================================== 100 101(define-local-member-name 102 update-kill-button-label 103 does-break-kill? 104 get-panel-percentages-and-orientation 105 set-panel-percentages-and-orientation) 106 107(define-unit unit@ 108 (import [prefix help-desk: drracket:help-desk^] 109 [prefix drracket:app: drracket:app^] 110 [prefix drracket:frame: drracket:frame^] 111 [prefix drracket:text: drracket:text^] 112 [prefix drracket:rep: drracket:rep/int^] 113 [prefix drracket:language-configuration: drracket:language-configuration/internal^] 114 [prefix drracket:language: drracket:language^] 115 [prefix drracket:get/extend: drracket:get/extend^] 116 [prefix drracket:module-overview: drracket:module-overview^] 117 [prefix drracket:tools: drracket:tools^] 118 [prefix drracket:init: drracket:init/int^] 119 [prefix drracket:module-language: drracket:module-language/int^] 120 [prefix drracket:module-language-tools: drracket:module-language-tools^] 121 [prefix drracket:modes: drracket:modes^] 122 [prefix drracket:debug: drracket:debug^] 123 [prefix drracket: drracket:interface^]) 124 (export (rename drracket:unit/int^ [-frame% frame%])) 125 (init-depend drracket:module-language/int^) 126 127 (define struct:teachpack-callbacks struct:drracket:unit:teachpack-callbacks) 128 (define teachpack-callbacks? drracket:unit:teachpack-callbacks?) 129 (define teachpack-callbacks-get-names drracket:unit:teachpack-callbacks-get-names) 130 (define teachpack-callbacks-add drracket:unit:teachpack-callbacks-add) 131 (define teachpack-callbacks-remove drracket:unit:teachpack-callbacks-remove) 132 (define teachpack-callbacks-remove-all drracket:unit:teachpack-callbacks-remove-all) 133 (define make-teachpack-callbacks drracket:unit:teachpack-callbacks) 134 (define teachpack-callbacks drracket:unit:teachpack-callbacks) 135 136 (keymap:add-to-right-button-menu 137 (let ([old (keymap:add-to-right-button-menu)]) 138 (λ (menu text event) 139 (old menu text event) 140 (when (and (is-a? text text%) 141 (or (is-a? text (get-definitions-text%)) 142 (is-a? text drracket:rep:text%)) 143 (is-a? event mouse-event%)) 144 145 (let ([add-sep 146 (let ([added? #f]) 147 (λ () 148 (unless added? 149 (set! added? #t) 150 (new separator-menu-item% [parent menu]))))]) 151 152 (add-search-help-desk-menu-item text menu 153 (let-values ([(x y) 154 (send text dc-location-to-editor-location 155 (send event get-x) 156 (send event get-y))]) 157 (send text find-position x y)) 158 add-sep) 159 160 (when (is-a? text editor:basic<%>) 161 (let-values ([(pos text) (send text get-pos/text event)]) 162 (when (and pos (is-a? text text%)) 163 (send text split-snip pos) 164 (send text split-snip (+ pos 1)) 165 (let ([snip (send text find-snip pos 'after-or-none)]) 166 (when (or (is-a? snip image-snip%) 167 (is-a? snip image-core:image%) 168 (is-a? snip cache-image-snip%)) 169 (add-sep) 170 (define (save-image-callback _1 _2) 171 (define fn 172 (put-file #f 173 (send text get-top-level-window) 174 #f "untitled.png" "png")) 175 (when fn 176 (define kind (filename->kind fn)) 177 (cond 178 [kind 179 (cond 180 [(or (is-a? snip image-snip%) 181 (is-a? snip cache-image-snip%)) 182 (send (send snip get-bitmap) save-file fn kind)] 183 [else 184 (image-core:save-image-as-bitmap snip fn kind)])] 185 [else 186 (message-box 187 (string-constant drscheme) 188 "Must choose a filename that ends with either .png, .jpg, .xbm, or .xpm" 189 #:dialog-mixin frame:focus-table-mixin)]))) 190 (new menu-item% 191 [parent menu] 192 [label (string-constant save-image)] 193 [callback save-image-callback])))))) 194 195 (void)))))) 196 197 (define (add-search-help-desk-menu-item text menu position [add-sep void]) 198 (let* ([end (send text get-end-position)] 199 [start (send text get-start-position)]) 200 (unless (= 0 (send text last-position)) 201 (let* ([str (if (= end start) 202 (find-symbol text position) 203 (send text get-text start end))] 204 ;; almost the same code as "search-help-desk" in "rep.rkt" 205 [l (send text get-canvas)] 206 [l (and l (send l get-top-level-window))] 207 [l (and l (is-a? l drracket:unit:frame<%>) (send l get-definitions-text))] 208 [l (and l (send l get-next-settings))] 209 [l (and l (drracket:language-configuration:language-settings-language l))] 210 [ctxt (and l (send l capability-value 'drscheme:help-context-term))] 211 [name (and l (send l get-language-name))]) 212 (unless (string=? str "") 213 (add-sep) 214 (let ([short-str (shorten-str str 50)]) 215 (make-object menu-item% 216 (gui-utils:format-literal-label 217 (string-constant search-help-desk-for) 218 (if (equal? short-str str) 219 str 220 (string-append short-str "..."))) 221 menu 222 (λ x (help-desk:help-desk str (list ctxt name)))) 223 (void))))))) 224 225 (define (filename->kind fn) 226 (let ([ext (filename-extension fn)]) 227 (and ext 228 (let ([sym (string->symbol (bytes->string/utf-8 ext))]) 229 (ormap (λ (pr) (and (equal? sym (car pr)) (cadr pr))) 230 allowed-extensions))))) 231 232 (define allowed-extensions '((png png) 233 (jpg jpeg) 234 (xbm xbm) 235 (xpm xpm))) 236 237 238 239 ;; find-symbol : number -> string 240 ;; finds the symbol around the position `pos' (approx) 241 (define (find-symbol text pos) 242 (cond 243 [(and (is-a? text racket:text<%>) 244 (not (send text is-stopped?))) 245 (let* ([before (send text get-backward-sexp pos)] 246 [before+ (and before (send text get-forward-sexp before))] 247 [after (send text get-forward-sexp pos)] 248 [after- (and after (send text get-backward-sexp after))]) 249 250 (define (get-tokens start end) 251 (let loop ([i start]) 252 (cond 253 [(and (< i end) 254 (< i (send text last-position))) 255 (define-values (tstart tend) (send text get-token-range i)) 256 (cons (list (send text classify-position i) tstart tend) 257 (loop tend))] 258 [else '()]))) 259 260 ;; find-searchable-tokens : number number -> (or/c #f (list symbol number number)) 261 (define (find-searchable-tokens start end) 262 (define tokens (get-tokens start end)) 263 (for/or ([tok tokens]) 264 (define type (list-ref tok 0)) 265 (cond [(or (equal? type 'symbol) 266 (equal? type 'hash-colon-keyword) 267 ;; The token may have been categorized as a keyword due to 268 ;; its presence in the tabification preferences: 269 (equal? type 'keyword)) 270 tok] 271 [else 272 #f]))) 273 274 (define searchable-token 275 (or (and before before+ 276 (<= before pos before+) 277 (find-searchable-tokens before before+)) 278 (and after after- 279 (<= after- pos after) 280 (find-searchable-tokens after- after)))) 281 (if searchable-token 282 (send text get-text (list-ref searchable-token 1) (list-ref searchable-token 2)) 283 ""))] 284 [else 285 (send text split-snip pos) 286 (send text split-snip (+ pos 1)) 287 (let ([snip (send text find-snip pos 'after)]) 288 (if (is-a? snip string-snip%) 289 (let* ([before 290 (let loop ([i (- pos 1)] 291 [chars null]) 292 (if (< i 0) 293 chars 294 (let ([char (send text get-character i)]) 295 (if (non-letter? char) 296 chars 297 (loop (- i 1) 298 (cons char chars))))))] 299 [after 300 (let loop ([i pos]) 301 (if (< i (send text last-position)) 302 (let ([char (send text get-character i)]) 303 (if (non-letter? char) 304 null 305 (cons char (loop (+ i 1))))) 306 null))]) 307 (apply string (append before after))) 308 ""))])) 309 310 ;; non-letter? : char -> boolean 311 ;; returns #t if the character belongs in a symbol (approx) and #f it is 312 ;; a divider between symbols (approx) 313 (define (non-letter? x) 314 (or (char-whitespace? x) 315 (memq x '(#\` #\' #\, #\; #\" 316 #\{ #\( #\[ #\] #\) #\})))) 317 (define (shorten-str str len) 318 (if ((string-length str) . <= . len) 319 str 320 (substring str 0 len))) 321 322 323 ; 324 ; 325 ; 326 ; ;;; ; ; ; ; 327 ; ; ; ; 328 ; ; ; ; ; 329 ; ;;;; ; ; ;;; ;;; ;;;; ; ;;; ; ;; ;; ; ; ;;; ; ;;; ;; ; 330 ; ; ;; ; ; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ; ; ; ;; 331 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 332 ; ; ; ;;;; ; ; ; ; ; ; ; ; ; ; ;;;; ; ; ; ; ; 333 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 334 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; 335 ; ; ; ;;;;; ;;; ;; ; ;;; ; ; ;; ; ; ;;;;; ; ;;; ;; ; 336 ; ; 337 ; ; ; 338 ; ;;;; 339 340 (define (get-fraction-from-user parent) 341 (define dlg (make-object dialog% (string-constant enter-fraction))) 342 (define hp (make-object horizontal-panel% dlg)) 343 (make-object message% (string-constant whole-part) hp) 344 (define whole 345 (keymap:call/text-keymap-initializer 346 (λ () 347 (make-object text-field% #f hp void)))) 348 (define vp (new-vertical-panel% [parent hp])) 349 (define hp2 (new-horizontal-panel% [parent vp])) 350 (define num 351 (keymap:call/text-keymap-initializer 352 (λ () 353 (make-object text-field% #f hp2 void)))) 354 (define num-m (make-object message% (string-constant numerator) hp2)) 355 (define hp3 (make-object horizontal-panel% vp)) 356 (define den 357 (keymap:call/text-keymap-initializer 358 (λ () 359 (make-object text-field% #f hp3 void)))) 360 (define den-m (make-object message% (string-constant denominator) hp3)) 361 (define bp (make-object horizontal-panel% dlg)) 362 (define ok? #f) 363 (define (validate-number) 364 (define num-s (string->number (send num get-value))) 365 (define den-s (string->number (send den get-value))) 366 (define whole-s (if (string=? (send whole get-value) "") 367 0 368 (string->number (send whole get-value)))) 369 (cond 370 [(or (not whole-s) (not (integer? whole-s))) 371 (string-constant insert-number/bad-whole-part)] 372 [(or (not num-s) (not (integer? num-s)) (< num-s 0)) 373 (string-constant insert-number/bad-numerator)] 374 [(or (not den-s) (not (integer? den-s)) (<= den-s 0)) 375 (string-constant insert-number/bad-denominator)] 376 [else 377 (if (< whole-s 0) 378 (- whole-s (/ num-s den-s)) 379 (+ whole-s (/ num-s den-s)))])) 380 (define (ok-callback) 381 (define v (validate-number)) 382 (cond 383 [(number? v) 384 (set! ok? #t) 385 (send dlg show #f)] 386 [else 387 (message-box 388 (string-constant drscheme) 389 v 390 dlg 391 #:dialog-mixin frame:focus-table-mixin)])) 392 (define (cancel-callback) (send dlg show #f)) 393 (define-values (ok cancel) 394 (gui-utils:ok/cancel-buttons 395 bp 396 (λ (x y) (ok-callback)) 397 (λ (x y) (cancel-callback)))) 398 (let ([mw (max (send den-m get-width) (send num-m get-width))]) 399 (send den-m min-width mw) 400 (send num-m min-width mw)) 401 (send bp set-alignment 'right 'center) 402 (send dlg show #t) 403 (and ok? 404 (let ([v (validate-number)]) 405 (and (number? v) 406 v)))) 407 408 ;; create-executable : (instanceof drracket:unit:frame<%>) -> void 409 (define (create-executable frame) 410 (define definitions-text (send frame get-definitions-text)) 411 (define program-filename (send definitions-text get-filename)) 412 (define settings (send definitions-text get-next-settings)) 413 (cond 414 [(not (drracket:language-configuration:language-allows-executable-creation? 415 (drracket:language-configuration:language-settings-language settings))) 416 (message-box (string-constant drscheme) 417 (string-constant drracket-creates-executables-only-in-some-languages) 418 frame 419 #:dialog-mixin frame:focus-table-mixin)] 420 [(not program-filename) 421 (message-box (string-constant create-executable-title) 422 (string-constant must-save-before-executable) 423 frame 424 #:dialog-mixin frame:focus-table-mixin)] 425 [else 426 (when (or (not (send definitions-text is-modified?)) 427 (gui-utils:get-choice 428 (string-constant definitions-not-saved) 429 (string-constant yes) 430 (string-constant no) 431 (string-constant drscheme) 432 #f 433 frame)) 434 (send (drracket:language-configuration:language-settings-language settings) 435 create-executable 436 (drracket:language-configuration:language-settings-settings settings) 437 frame 438 program-filename))])) 439 440 (define-values (get-program-editor-mixin add-to-program-editor-mixin) 441 (let* ([program-editor-mixin 442 (mixin (editor:basic<%> (class->interface text%)) () 443 (init-rest args) 444 (inherit get-top-level-window) 445 446 (define/private (reset-highlighting) 447 (let ([f (get-top-level-window)]) 448 (when (and f 449 (is-a? f drracket:unit:frame<%>)) 450 (let ([interactions-text (send f get-interactions-text)]) 451 (when (object? interactions-text) 452 (send interactions-text reset-highlighting)))))) 453 454 (define/augment (after-insert x y) 455 (reset-highlighting) 456 (inner (void) after-insert x y)) 457 458 (define/augment (after-delete x y) 459 (reset-highlighting) 460 (inner (void) after-delete x y)) 461 462 (apply super-make-object args))] 463 [get-program-editor-mixin 464 (λ () 465 (drracket:tools:only-in-phase 'drracket:unit:get-program-editor-mixin 466 'phase2 467 'init-complete) 468 program-editor-mixin)] 469 [add-to-program-editor-mixin 470 (λ (mixin) 471 (drracket:tools:only-in-phase 'drracket:unit:add-to-program-editor-mixin 'phase1) 472 (let ([old program-editor-mixin]) 473 (set! program-editor-mixin (λ (x) (mixin (old x))))))]) 474 (values get-program-editor-mixin 475 add-to-program-editor-mixin))) 476 477 ;; this sends a message to its frame when it gets the focus 478 (define make-searchable-canvas% 479 (λ (%) 480 (class % 481 (inherit get-top-level-window) 482 (define/override (on-focus on?) 483 (when on? 484 (send (get-top-level-window) make-searchable this)) 485 (super on-focus on?)) 486 (super-new)))) 487 488 (define interactions-canvas% 489 (class (make-searchable-canvas% 490 (canvas:info-mixin 491 (canvas:wide-snip-mixin 492 (canvas:info-mixin 493 canvas:color%)))) 494 (init [style '()]) 495 (super-new (style (cons 'auto-hscroll style))) 496 (inherit set-scroll-via-copy) 497 (set-scroll-via-copy #t))) 498 499 500 (define definitions-canvas% 501 (class (make-searchable-canvas% (canvas:info-mixin canvas:color%)) 502 (init [style '()]) 503 (super-new (style (cons 'auto-hscroll style))) 504 (inherit set-scroll-via-copy) 505 (set-scroll-via-copy #t))) 506 507 ; 508 ; 509 ; 510 ; ; ;;; ; ; 511 ; ; ; ; 512 ; ; ; ; ; ; 513 ; ;; ; ;;; ;;;;;;; ; ;; ; ;;;; ; ;;; ; ;; ;;; ;;;; ;;; ; ; ;;;; 514 ; ; ;; ; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; 515 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; 516 ; ; ; ;;;;;; ; ; ; ; ; ; ; ; ; ; ; ;; ; ;;;;;; ; ; 517 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 518 ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 519 ; ;; ; ;;;; ; ; ; ; ; ;; ; ;;; ; ; ;;; ;; ;;;; ; ; ;; 520 ; 521 ; 522 ; 523 524 525 (define get-definitions-text% 526 (let ([definitions-text% #f]) 527 (λ () 528 (drracket:tools:only-in-phase 'phase2 'init-complete) 529 (unless definitions-text% 530 (set! definitions-text% (make-definitions-text%))) 531 definitions-text%))) 532 533 (define (show-line-numbers?) 534 (preferences:get 'drracket:show-line-numbers?)) 535 536 (define (make-definitions-text%) 537 (let ([definitions-super% 538 (text:line-numbers-mixin 539 (text:first-line-mixin 540 (drracket:module-language:module-language-put-file-mixin 541 (racket:text-mixin 542 (color:text-mixin 543 (drracket:rep:drs-bindings-keymap-mixin 544 (mode:host-text-mixin 545 (text:foreground-color-mixin 546 (drracket:rep:drs-autocomplete-mixin 547 (λ (x) x) 548 (text:normalize-paste-mixin 549 (text:column-guide-mixin 550 (text:inline-overview-mixin 551 (text:all-string-snips-mixin 552 (text:ascii-art-enlarge-boxes-mixin 553 (number-snip:remove-decimal-looking-number-snips-on-insertion-mixin 554 text:info%)))))))))))))))]) 555 ((get-program-editor-mixin) 556 (class* definitions-super% (drracket:unit:definitions-text<%>) 557 (inherit is-locked? lock while-unlocked 558 highlight-first-line is-printing?) 559 560 (define interactions-text #f) 561 (define/public (set-interactions-text it) 562 (set! interactions-text it)) 563 564 (define tab #f) 565 (define/public (get-tab) tab) 566 (define/public (set-tab t) (set! tab t)) 567 568 (inherit begin-edit-sequence end-edit-sequence 569 delete insert last-position paragraph-start-position 570 get-character) 571 572 (define save-file-metadata #f) 573 574 (define/pubment (begin-metadata-changes) 575 (set! ignore-edits? #t) 576 (inner (void) begin-metadata-changes)) 577 (define/pubment (end-metadata-changes) 578 (set! ignore-edits? #f) 579 (inner (void) end-metadata-changes)) 580 581 (define/augment (on-save-file filename fmt) 582 (inner (void) on-save-file filename fmt) 583 (define lang (drracket:language-configuration:language-settings-language next-settings)) 584 (define settings (drracket:language-configuration:language-settings-settings 585 next-settings)) 586 (define name-mod (send lang get-reader-module)) 587 (when name-mod 588 ;; the reader-module method's result is used a test of whether or 589 ;; not the get-metadata method is used for this language 590 (let ([metadata (send lang get-metadata (filename->modname filename) settings)]) 591 (begin-edit-sequence #f #f) 592 (begin-metadata-changes) 593 (let ([locked? (is-locked?)]) 594 (when locked? (lock #f)) 595 (set! save-file-metadata metadata) 596 (while-unlocked 597 (λ () 598 (insert metadata 0 0))) 599 (when locked? (lock #t)))))) 600 (define/private (filename->modname filename) 601 (let-values ([(base name dir) (split-path filename)]) 602 (string->symbol (regexp-replace #rx"\\.[^.]*$" 603 (path->string name) 604 "")))) 605 606 (define/augment (after-save-file success?) 607 (when save-file-metadata 608 (let ([modified? (is-modified?)] 609 [locked? (is-locked?)]) 610 (when locked? (lock #f)) 611 (while-unlocked 612 (λ () 613 (delete 0 (string-length save-file-metadata)))) 614 (when locked? (lock #t)) 615 (set! save-file-metadata #f) 616 ;; restore modification status to where it was before the metadata is removed 617 (set-modified modified?) 618 (end-metadata-changes) 619 (end-edit-sequence))) 620 (inner (void) after-save-file success?)) 621 622 (define/augment (on-load-file filename format) 623 (inner (void) on-load-file filename format) 624 (begin-edit-sequence #f #f)) 625 (define/augment (after-load-file success?) 626 (when success? 627 (let-values ([(module-language module-language-settings) 628 (get-module-language/settings)]) 629 (let-values ([(matching-language settings) 630 (pick-new-language 631 this 632 (drracket:language-configuration:get-languages) 633 module-language 634 module-language-settings)]) 635 (cond 636 [matching-language 637 (set-next-settings 638 (drracket:language-configuration:language-settings 639 matching-language 640 settings) 641 #f)] 642 [else 643 (define lang (drracket:language-configuration:language-settings-language 644 (get-next-settings))) 645 (when (send lang get-reader-module) 646 (set-next-settings 647 (drracket:language-configuration:get-default-language-settings) 648 #f))]))) 649 (set-modified #f)) 650 651 (end-edit-sequence) 652 (inner (void) after-load-file success?)) 653 654 (define/augment (on-lexer-valid valid?) 655 (inner (void) on-lexer-valid valid?) 656 (let ([f (get-top-level-window)]) 657 (when (and f 658 (is-a? f drracket:unit:frame<%>)) 659 (send f set-color-status! valid?)))) 660 661 (define/override (get-can-close-parent) 662 (and tab (send tab get-frame))) 663 664 ;; if we use the tab to get to the top-level frame too 665 ;; soon then we use some GUI controls before they are 666 ;; initialized, so delay this until the file is 667 ;; opened in the definitions window 668 (define allow-top-level-connection #f) 669 (define/public (enable-top-level-window-connection) 670 (set! allow-top-level-connection #t)) 671 (define/override (get-top-level-window) 672 (or (super get-top-level-window) 673 (and allow-top-level-connection 674 tab 675 (send tab get-frame)))) 676 677 (inherit is-modified? run-after-edit-sequence) 678 (define/override (set-modified mod?) 679 (super set-modified mod?) 680 (run-after-edit-sequence 681 (λ () 682 (let ([f (get-top-level-window)]) 683 (when (and f 684 (is-a? f drracket:unit:frame<%>)) 685 (send f update-save-button)))))) 686 (define/override set-filename 687 (case-lambda 688 [(fn) (set-filename fn #f)] 689 [(fn tmp?) 690 (super set-filename fn tmp?) 691 (let ([f (get-top-level-window)]) 692 (when (and f 693 (is-a? f drracket:unit:frame<%>)) 694 (send (send f get-interactions-text) set-port-unsaved-name 695 (if fn 696 "interactions from an unsaved editor" 697 (format "interactions from ~a" fn))) 698 (send f update-save-message)))])) 699 700 (field 701 [needs-execution-state #f] 702 [already-warned-state #f] 703 [execute-settings (preferences:get 704 drracket:language-configuration:settings-preferences-symbol)] 705 [next-settings execute-settings]) 706 707 (define/private (set-needs-execution-state! s) (set! needs-execution-state s)) 708 709 ;; get-needs-execution-message : -> (or/c string #f) 710 ;; returns the current warning message if "Run" should be clicked (ie, if the 711 ;; state of the REPL is out of sync with drscheme). 712 (define/public (get-needs-execution-message) 713 (and (not already-warned-state) 714 (or (and (not (this-and-next-language-the-same?)) 715 (string-constant needs-execute-language-changed)) 716 needs-execution-state))) 717 718 (define/pubment (get-next-settings) next-settings) 719 (define/pubment (set-next-settings _next-settings [update-prefs? #t]) 720 (when (or 721 (send (drracket:language-configuration:language-settings-language _next-settings) 722 get-reader-module) 723 (send (drracket:language-configuration:language-settings-language next-settings) 724 get-reader-module)) 725 (set-modified #t)) 726 (set! next-settings _next-settings) 727 (let ([f (get-top-level-window)]) 728 (when (and f 729 (is-a? f drracket:unit:frame<%>)) 730 (send f language-changed))) 731 732 (highlight-first-line 733 (is-a? (drracket:language-configuration:language-settings-language _next-settings) 734 drracket:module-language:module-language<%>)) 735 736 (let ([lang (drracket:language-configuration:language-settings-language next-settings)] 737 [sets (drracket:language-configuration:language-settings-settings next-settings)]) 738 (preferences:set 739 'drracket:recent-language-names 740 (limit-length 741 (remove-duplicate-languages 742 (cons (cons (send lang get-language-name) 743 (send lang marshall-settings sets)) 744 (preferences:get 'drracket:recent-language-names))) 745 10))) 746 747 (when update-prefs? 748 (preferences:set 749 drracket:language-configuration:settings-preferences-symbol 750 next-settings)) 751 752 (remove-auto-text) 753 (insert-auto-text) 754 (after-set-next-settings _next-settings)) 755 756 (define/pubment (after-set-next-settings s) 757 (inner (void) after-set-next-settings s)) 758 759 (define/public (this-and-next-language-the-same?) 760 (define execute-lang 761 (drracket:language-configuration:language-settings-language execute-settings)) 762 (define next-lang 763 (drracket:language-configuration:language-settings-language next-settings)) 764 (and (equal? (send execute-lang get-language-position) 765 (send next-lang get-language-position)) 766 (equal? (send execute-lang marshall-settings 767 (drracket:language-configuration:language-settings-settings 768 execute-settings)) 769 (send execute-lang marshall-settings 770 (drracket:language-configuration:language-settings-settings 771 next-settings))))) 772 773 (define/pubment (set-needs-execution-message msg) 774 (set-needs-execution-state! msg)) 775 (define/pubment (teachpack-changed) 776 (set-needs-execution-state! (string-constant needs-execute-teachpack-changed))) 777 (define/pubment (just-executed) 778 (set! execute-settings next-settings) 779 (set-needs-execution-state! #f) 780 (send tab clear-execution-state) 781 (set! already-warned-state #f)) 782 (define/pubment (already-warned?) 783 already-warned-state) 784 (define/pubment (already-warned) 785 (set! already-warned-state #t)) 786 787 ;; the really-modified? flag determines if there 788 ;; is a modification that is not the insertion of the auto-text 789 (define really-modified? #f) 790 791 ;; when this flag is #t, edits to the buffer do not count as 792 ;; user's edits and so the yellow warning does not appear 793 (define ignore-edits? #f) 794 795 (define/augment (after-insert x y) 796 (unless ignore-edits? 797 (set! really-modified? #t) 798 (set-needs-execution-state! (string-constant needs-execute-defns-edited))) 799 (inner (void) after-insert x y)) 800 (define/augment (after-delete x y) 801 (unless ignore-edits? 802 (set! really-modified? #t) 803 (set-needs-execution-state! (string-constant needs-execute-defns-edited))) 804 (inner (void) after-delete x y)) 805 806 (define/override (is-special-first-line? l) 807 (and (preferences:get 'drracket:module-language-first-line-special?) 808 (is-lang-line? l))) 809 810 (inherit get-filename) 811 812 (inherit get-filename/untitled-name) 813 (define/private (get-date-string) 814 (string-append 815 (date->string (seconds->date (current-seconds))) 816 " " 817 (get-filename/untitled-name))) 818 819 (define/override (on-paint before dc left top right bottom dx dy draw-caret) 820 (super on-paint before dc left top right bottom dx dy draw-caret) 821 822 ;; [Disabled] For printing, put date and filename in the top margin: 823 (when (and #f before (is-printing?)) 824 (let ([h (box 0)] 825 [w (box 0)]) 826 (send (current-ps-setup) get-editor-margin w h) 827 (unless ((unbox h) . < . 2) 828 (let ([font (make-font #:size (inexact->exact (ceiling (* 1/2 (unbox h)))) 829 #:family 'modern)] 830 [old-font (send dc get-font)]) 831 (send dc set-font font) 832 (send dc draw-text (get-date-string) 0 0) 833 (send dc set-font old-font))))) 834 835 ;; draw the arrows 836 (when before 837 (when error-arrows 838 (define old-pen (send dc get-pen)) 839 (define old-brush (send dc get-brush)) 840 (send dc set-brush "red" 'solid) 841 (define font-size-factor 842 (cond 843 [(<= (editor:get-current-preferred-font-size) 12) 1] 844 [else (* (editor:get-current-preferred-font-size) 1/8)])) 845 (define pen-width font-size-factor) 846 (define arrow-head-size (* 8 font-size-factor)) 847 (define arrow-root-radius (* 1 font-size-factor)) 848 (send dc set-pen (send the-pen-list find-or-create-pen "red" 1 'solid)) 849 (let loop ([pts error-arrows]) 850 (cond 851 [(null? pts) (void)] 852 [(null? (cdr pts)) (void)] 853 [else (define pt1 (car pts)) 854 (define pt2 (cadr pts)) 855 (draw-arrow dc dx dy pt1 pt2 856 pen-width arrow-head-size arrow-root-radius) 857 (loop (cdr pts))])) 858 (send dc set-pen old-pen) 859 (send dc set-brush old-brush)))) 860 861 (define/private (draw-arrow dc dx dy pt1 pt2 pen-width arrow-head-size arrow-root-radius) 862 (define-values (x1 y1) 863 (find-poss (srcloc-source pt1) (- (srcloc-position pt1) 1) (srcloc-position pt1))) 864 (define-values (x2 y2) 865 (find-poss (srcloc-source pt2) (- (srcloc-position pt2) 1) (srcloc-position pt2))) 866 (drracket:arrow:draw-arrow dc x1 y1 x2 y2 dx dy 867 #:pen-width pen-width 868 #:arrow-head-size arrow-head-size 869 #:arrow-root-radius arrow-root-radius)) 870 871 (inherit dc-location-to-editor-location) 872 (define/private (find-poss text left-pos right-pos) 873 (let ([xlb (box 0)] 874 [ylb (box 0)] 875 [xrb (box 0)] 876 [yrb (box 0)]) 877 (send text position-location left-pos xlb ylb #t) 878 (send text position-location right-pos xrb yrb #f) 879 (let*-values ([(xl-off yl-off) (send text editor-location-to-dc-location 880 (unbox xlb) 881 (unbox ylb))] 882 [(xl yl) (dc-location-to-editor-location xl-off yl-off)] 883 [(xr-off yr-off) (send text editor-location-to-dc-location 884 (unbox xrb) 885 (unbox yrb))] 886 [(xr yr) (dc-location-to-editor-location xr-off yr-off)]) 887 (values (/ (+ xl xr) 2) 888 (/ (+ yl yr) 2))))) 889 890 (define/public (still-untouched?) 891 (and (or (= (last-position) 0) (not really-modified?)) 892 (not (is-modified?)) 893 (not (get-filename)))) 894 ;; inserts the auto-text if any 895 (define/public (insert-auto-text) 896 (define lang 897 (drracket:language-configuration:language-settings-language 898 next-settings)) 899 (define auto-text 900 (and (not really-modified?) 901 (not (get-filename)) 902 (is-a? lang drracket:module-language:module-language<%>) 903 (send lang get-auto-text 904 (drracket:language-configuration:language-settings-settings 905 next-settings)))) 906 (when auto-text 907 (set! ignore-edits? #t) 908 (begin-edit-sequence #f #f) 909 (insert auto-text) 910 (set-modified #f) 911 (set! ignore-edits? #f) 912 (end-edit-sequence) 913 (set! really-modified? #f))) 914 (define/private (remove-auto-text) 915 (when (and (not really-modified?) 916 (not (get-filename)) 917 (> (last-position) 0)) 918 (begin-edit-sequence #f #f) 919 (send this erase) 920 (set-modified #f) 921 (end-edit-sequence) 922 (set! really-modified? #f))) 923 924 (inherit invalidate-bitmap-cache) 925 (define/public (set-error-arrows arrows) 926 (unless (eq? arrows error-arrows) 927 (set! error-arrows arrows) 928 (invalidate-bitmap-cache))) 929 930 (define error-arrows #f) 931 932 (super-new [show-line-numbers? (show-line-numbers?)]) 933 934 (highlight-first-line 935 (is-a? (drracket:language-configuration:language-settings-language next-settings) 936 drracket:module-language:module-language<%>)) 937 (inherit set-max-undo-history) 938 (set-max-undo-history 'forever) 939 940 (inherit set-inline-overview-enabled?) 941 (set-inline-overview-enabled? (preferences:get 'drracket:inline-overview-shown?)) 942 943 (inherit set-file-creator-and-type) 944 (set-file-creator-and-type #"DrSc" #f))))) 945 946 (define (get-module-language/settings) 947 (let* ([module-language 948 (and (preferences:get 'drracket:switch-to-module-language-automatically?) 949 (ormap 950 (λ (lang) 951 (and (is-a? lang drracket:module-language:module-language<%>) 952 lang)) 953 (drracket:language-configuration:get-languages)))] 954 [module-language-settings 955 (let ([prefs-setting (preferences:get 956 drracket:language-configuration:settings-preferences-symbol)]) 957 (cond 958 [(eq? (drracket:language-configuration:language-settings-language prefs-setting) 959 module-language) 960 (drracket:language-configuration:language-settings-settings prefs-setting)] 961 [else 962 (and module-language 963 (send module-language default-settings))]))]) 964 (values module-language module-language-settings))) 965 966 967 968 969 ; 970 ; 971 ; 972 ; 973 ; ;;; ;;;;;;; 974 ; ;;; ;;; 975 ; ;; ;;; ;;;; ;;;;; ;;; ;;; ;; ;;;; 976 ; ;;;;;;; ;; ;;;;;;;; ;;; ;;;;;;; ;; ;;; 977 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 978 ; ;;; ;;; ;;;;;;; ;;; ;;; ;;; ;;; ;;;;;;; 979 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 980 ; ;;;;;;; ;;;;;; ;;; ;;; ;;; ;;; ;;;;;; ;;; ;;; ;;; 981 ; ;; ;;; ;;;; ;;; ;;; ;;; ;;; ;;;; ;;; ;;; ;;; 982 ; 983 ; 984 ; 985 ; 986 987 ;; get-pos : text mouse-event% -> (union #f number) 988 (define (get-pos text event) 989 (let*-values ([(event-x event-y) 990 (values (send event get-x) 991 (send event get-y))] 992 [(x y) (send text dc-location-to-editor-location 993 event-x 994 event-y)]) 995 (let* ([on-it? (box #f)] 996 [pos (send text find-position x y #f on-it?)]) 997 (and (unbox on-it?) 998 pos)))) 999 1000 (let ([old (keymap:add-to-right-button-menu)]) 1001 (keymap:add-to-right-button-menu 1002 (λ (menu editor event) 1003 (when (is-a? editor text%) 1004 (let* ([canvas (send editor get-canvas)] 1005 [frame (and canvas (send canvas get-top-level-window))]) 1006 (when (is-a? frame drracket:unit:frame<%>) 1007 (let* ([language-settings (send (send frame get-definitions-text) get-next-settings)] 1008 [new-language (drracket:language-configuration:language-settings-language 1009 language-settings)] 1010 [capability-info 1011 (get-define-popup-info 1012 (send new-language capability-value 'drscheme:define-popup))]) 1013 (when capability-info 1014 (let* ([current-pos (get-pos editor event)] 1015 [current-word (and current-pos (get-current-word editor current-pos))] 1016 [defn (and current-word 1017 (ormap (λ (defn) (and (string=? current-word (defn-name defn)) 1018 defn)) 1019 (get-definitions capability-info 1020 #f 1021 editor)))]) 1022 (when defn 1023 (new separator-menu-item% (parent menu)) 1024 (new menu-item% 1025 (parent menu) 1026 (label (gui-utils:format-literal-label (string-constant jump-to-defn) 1027 (defn-name defn))) 1028 (callback (λ (x y) 1029 (send editor set-position (defn-start-pos defn)))))))))))) 1030 (old menu editor event)))) 1031 1032 ;; get-current-word : editor number -> string 1033 ;; returns the string that is being clicked on 1034 (define (get-current-word editor pos) 1035 (let* ([search 1036 (λ (dir offset) 1037 (let loop ([pos pos]) 1038 (cond 1039 [(or (= pos 0) 1040 (= pos (send editor last-position))) 1041 pos] 1042 [(memq (send editor get-character pos) 1043 '(#\space #\return #\newline #\( #\) #\[ #\] #\tab)) 1044 (offset pos)] 1045 [else (loop (dir pos))])))] 1046 [before (search sub1 add1)] 1047 [after (search add1 (λ (x) x))]) 1048 (send editor get-text before after))) 1049 1050 (define func-defs-canvas% 1051 (class name-message% 1052 (init-field frame) 1053 1054 (unless (is-a? frame drracket:unit:frame<%>) 1055 (error 'func-defs-canvas "frame is not a drracket:unit:frame<%>")) 1056 1057 (define sort-by-name? (preferences:get 'drracket:defns-popup-sort-by-name?)) 1058 (define sorting-name (if sort-by-name? 1059 (string-constant sort-by-position) 1060 (string-constant sort-by-name))) 1061 (define/private (change-sorting-order) 1062 (set! sort-by-name? (not sort-by-name?)) 1063 (preferences:set 'drracket:defns-popup-sort-by-name? sort-by-name?) 1064 (set! sorting-name (if sort-by-name? 1065 (string-constant sort-by-position) 1066 (string-constant sort-by-name)))) 1067 1068 (define define-popup-capability-info 1069 (get-define-popup-info 1070 (drracket:language:get-capability-default 'drscheme:define-popup))) 1071 1072 (inherit set-message set-hidden?) 1073 (define/public (language-changed new-language vertical?) 1074 (set! define-popup-capability-info 1075 (get-define-popup-info 1076 (send new-language capability-value 'drscheme:define-popup))) 1077 (define define-name 1078 (get-define-popup-name define-popup-capability-info 1079 vertical?)) 1080 (cond 1081 [define-name 1082 (set-message #f define-name) 1083 (set-hidden? #f)] 1084 [else 1085 (set-hidden? #t)])) 1086 (define/override (fill-popup menu reset) 1087 (when define-popup-capability-info 1088 (define text (send frame get-definitions-text)) 1089 (define hidden-prefixes (preferences:get 'drracket:define-popup-hidden-prefixes)) 1090 (define popup-infos-to-use 1091 (for/list ([a-define-popup-capability-info (in-list define-popup-capability-info)] 1092 #:unless (member (define-popup-info-long-name a-define-popup-capability-info) 1093 hidden-prefixes)) 1094 a-define-popup-capability-info)) 1095 (define unsorted-defns (get-definitions popup-infos-to-use (not sort-by-name?) text)) 1096 (define defns (if sort-by-name? 1097 (sort 1098 unsorted-defns 1099 (λ (x y) (string-ci<=? (defn-name x) (defn-name y)))) 1100 unsorted-defns)) 1101 (cond 1102 [(= 1 (length define-popup-capability-info)) 1103 (new menu:can-restore-menu-item% 1104 [label sorting-name] 1105 [parent menu] 1106 [callback (λ (x y) (change-sorting-order))])] 1107 [else 1108 (define config-menu (new menu% [parent menu] [label define-menu-configure])) 1109 (new menu:can-restore-menu-item% 1110 [label sorting-name] 1111 [parent config-menu] 1112 [callback (λ (x y) (change-sorting-order))]) 1113 (for ([a-define-popup-capability-info (in-list define-popup-capability-info)]) 1114 (define lab (define-popup-info-long-name a-define-popup-capability-info)) 1115 (define item 1116 (new menu:can-restore-checkable-menu-item% 1117 [label lab] 1118 [parent config-menu] 1119 [callback 1120 (λ (_1 _2) 1121 (define curr (preferences:get 'drracket:define-popup-hidden-prefixes)) 1122 (define new 1123 (if (send item is-checked?) 1124 (remove lab curr) 1125 (remove-duplicates (cons lab curr)))) 1126 (preferences:set 'drracket:define-popup-hidden-prefixes new))])) 1127 (send item check (not (member lab hidden-prefixes))))]) 1128 1129 (make-object separator-menu-item% menu) 1130 (if (null? defns) 1131 (send (make-object menu:can-restore-menu-item% 1132 (string-constant no-definitions-found) 1133 menu 1134 void) 1135 enable #f) 1136 (let loop ([defns defns]) 1137 (unless (null? defns) 1138 (let* ([defn (car defns)] 1139 [checked? 1140 (let ([t-start (send text get-start-position)] 1141 [t-end (send text get-end-position)] 1142 [d-start (defn-start-pos defn)] 1143 [d-end (defn-end-pos defn)]) 1144 (or (<= t-start d-start t-end) 1145 (<= t-start d-end t-end) 1146 (<= d-start t-start t-end d-end)))] 1147 [item 1148 (make-object (if checked? 1149 menu:can-restore-checkable-menu-item% 1150 menu:can-restore-menu-item%) 1151 (gui-utils:quote-literal-label (defn-name defn)) 1152 1153 menu 1154 (λ (x y) 1155 (reset) 1156 (send text set-position (defn-start-pos defn) (defn-start-pos defn)) 1157 (let ([canvas (send text get-canvas)]) 1158 (when canvas 1159 (send canvas focus)))))]) 1160 (when checked? 1161 (send item check #t)) 1162 (loop (cdr defns)))))))) 1163 1164 (super-new (label "(define ...)") ;; this default is quickly changed 1165 [string-constant-untitled (string-constant untitled)] 1166 [string-constant-no-full-name-since-not-saved 1167 (string-constant no-full-name-since-not-saved)]))) 1168 1169 (define (set-box/f! b v) (when (box? b) (set-box! b v))) 1170 1171 ; 1172 ; 1173 ; 1174 ; 1175 ; ;;;; 1176 ; ;;; 1177 ; ;;;; ;;; ;;;;;;; ;;; ;; ;;; ;;;; 1178 ; ;;;; ;;;;;;;;;;;; ;;;;;;;;;;; ;; ;;; 1179 ; ;;; ;;; ;; ;;; ;;; ;;; ;;; ;;; ;;; 1180 ; ;;; ;;; ;;;;; ;;; ;;; ;;; ;;;;;;; 1181 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 1182 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;;;; 1183 ; ;;; ;;; ;;;;;; ;;; ;;; ;;; ;;;; 1184 ; 1185 ; 1186 ; 1187 ; 1188 1189 (define dragable/def-int-mixin 1190 (mixin (panel:dragable<%>) () 1191 (init-field unit-frame) 1192 (inherit get-percentages popup-menu 1193 set-orientation get-vertical?) 1194 (define/augment (after-percentage-change) 1195 (define percentages (get-percentages)) 1196 (when (and (= 1 1197 (length (send unit-frame get-definitions-canvases)) 1198 (length (send unit-frame get-interactions-canvases))) 1199 (= 2 (length percentages))) 1200 (preferences:set 'drracket:unit-window-size-percentage (car percentages))) 1201 (inner (void) after-percentage-change)) 1202 (define/override (right-click-in-gap evt before after) 1203 (define menu (new popup-menu%)) 1204 (define vertical? (get-vertical?)) 1205 (new menu-item% 1206 [parent menu] 1207 [label 1208 ;; something seems to be wrong with the get-vertical? method... 1209 (if vertical? 1210 (string-constant change-to-vertical-alignment) 1211 (string-constant change-to-horizontal-alignment))] 1212 [callback 1213 (λ (a b) 1214 (preferences:set 'drracket:defs/ints-horizontal vertical?) 1215 (set-orientation vertical?))]) 1216 (popup-menu menu (send evt get-x) (send evt get-y))) 1217 (super-new))) 1218 1219 (define vertical-dragable/def-int% (dragable/def-int-mixin panel:vertical-dragable%)) 1220 (define horizontal-dragable/def-int% (dragable/def-int-mixin panel:horizontal-dragable%)) 1221 1222 (define tab% 1223 (class* object% (drracket:rep:context<%> drracket:unit:tab<%>) 1224 (init-field frame 1225 defs 1226 i 1227 defs-shown? 1228 ints-shown?) 1229 (define enabled? #t) 1230 (field [ints #f] 1231 [visible-defs #f] 1232 [visible-ints #f] 1233 [focus-d/i 'defs]) 1234 1235 ;; only called to initialize this tab. 1236 ;; the interactions editor should be invariant. 1237 (define/public (set-ints i) (set! ints i)) 1238 1239 (define/public-final (get-frame) frame) 1240 (define/public-final (get-defs) defs) 1241 (define/public-final (get-ints) ints) 1242 (define/public-final (get-visible-defs) (values visible-defs defs-shown?)) 1243 (define/public-final (set-visible-defs vd ds?) 1244 (set! visible-defs vd) 1245 (set! defs-shown? ds?)) 1246 (define/public-final (get-visible-ints) (values visible-ints ints-shown?)) 1247 (define/public-final (set-visible-ints vi is?) 1248 (set! visible-ints vi) 1249 (set! ints-shown? is?)) 1250 (define/public-final (set-focus-d/i di) 1251 (set! focus-d/i di)) 1252 (define/public-final (get-focus-d/i) focus-d/i) 1253 (define/public-final (get-i) i) 1254 (define/public-final (set-i _i) (set! i _i)) 1255 (define/public (disable-evaluation) 1256 (set! enabled? #f) 1257 (send ints lock #t) 1258 (send frame disable-evaluation-in-tab this)) 1259 (define/public (enable-evaluation) 1260 (set! enabled? #t) 1261 (send ints lock #f) 1262 (send frame enable-evaluation-in-tab this)) 1263 (define/public (get-enabled) enabled?) 1264 1265 (define last-touched (current-inexact-milliseconds)) 1266 (define/public-final (touched) (set! last-touched (current-inexact-milliseconds))) 1267 (define/public-final (get-last-touched) last-touched) 1268 1269 (define panel-percentages #f) 1270 (define panel-orientation #f) 1271 (define/public (set-panel-percentages-and-orientation p o) 1272 (set! panel-percentages p) 1273 (set! panel-orientation o)) 1274 (define/public (get-panel-percentages-and-orientation) 1275 (values panel-percentages panel-orientation)) 1276 1277 1278 ;; current-execute-warning is a snapshot of the needs-execution-message 1279 ;; that is taken each time repl submission happens, and it gets reset 1280 ;; when "Run" is clicked. 1281 (define current-execute-warning #f) 1282 (define/pubment (repl-submit-happened) 1283 (set! current-execute-warning (send defs get-needs-execution-message)) 1284 (update-execute-warning-gui)) 1285 (define/public (get-current-execute-warning) current-execute-warning) 1286 (define/public (clear-execution-state) 1287 (set! current-execute-warning #f) 1288 (update-execute-warning-gui) 1289 (send defs already-warned)) 1290 (define/public (update-execute-warning-gui) 1291 (when (is-current-tab?) 1292 (send frame show/hide-warning-message 1293 (get-current-execute-warning) 1294 (λ () 1295 ;; this callback might be run with a different tab ... 1296 (send (send frame get-current-tab) clear-execution-state))))) 1297 1298 (define/public (get-directory) 1299 (define bx (box #f)) 1300 (define filename (send defs get-filename bx)) 1301 (get-init-dir 1302 (and (not (unbox bx)) filename))) 1303 1304 (define/pubment (can-close?) 1305 (and (send defs can-close?) 1306 (send ints can-close?) 1307 (inner #t can-close?))) 1308 (define/pubment (on-close) 1309 (send defs on-close) 1310 (send ints on-close) 1311 (inner (void) on-close)) 1312 1313 ;; this should really do something local to the tab, but 1314 ;; for now it doesn't. 1315 (define/public (ensure-rep-shown rep) 1316 (send frame ensure-rep-shown rep)) 1317 1318 (field [thread-to-break-box (make-weak-box #f)] 1319 [custodian-to-kill-box (make-weak-box #f)] 1320 [do-kill? #f]) 1321 1322 (define/public (does-break-kill?) do-kill?) 1323 ;; break-callback : -> void 1324 (define/public (break-callback) 1325 (let ([thread-to-break (weak-box-value thread-to-break-box)] 1326 [custodian-to-kill (weak-box-value custodian-to-kill-box)]) 1327 (cond 1328 [(or (not thread-to-break) 1329 (not custodian-to-kill)) 1330 (bell)] 1331 [do-kill? 1332 (when custodian-to-kill 1333 (custodian-shutdown-all custodian-to-kill)) 1334 (set! do-kill? #f) 1335 (send (get-frame) update-kill-button-label)] 1336 [else 1337 (when thread-to-break 1338 (break-thread thread-to-break)) 1339 ;; only offer a kill the next time if 1340 ;; something got broken. 1341 (set! do-kill? #t) 1342 (send (get-frame) update-kill-button-label)]))) 1343 1344 ;; reset-offer-kill 1345 (define/public (reset-offer-kill) 1346 (set! do-kill? #f) 1347 (send (get-frame) update-kill-button-label)) 1348 1349 ;; get-breakables : -> (union #f thread) (union #f cust) -> void 1350 (define/public (get-breakables) 1351 (values (weak-box-value thread-to-break-box) (weak-box-value custodian-to-kill-box))) 1352 1353 ;; set-breakables : (union #f thread) (union #f cust) -> void 1354 (define/public (set-breakables thd cust) 1355 (set! thread-to-break-box (make-weak-box thd)) 1356 (set! custodian-to-kill-box (make-weak-box cust))) 1357 1358 (define/pubment (clear-annotations) 1359 (inner (void) clear-annotations) 1360 (send ints reset-highlighting)) 1361 1362 (define running? #f) 1363 (define/public-final (is-running?) running?) 1364 (define/public (update-running b?) 1365 (set! running? b?) 1366 (send frame update-running b?)) 1367 1368 (define/public-final (is-current-tab?) (eq? this (send frame get-current-tab))) 1369 1370 (define log-visible? #f) 1371 (define/public-final (toggle-log) 1372 (set! log-visible? (not log-visible?)) 1373 (send frame show/hide-log log-visible?) 1374 (send (get-ints) enable/disable-capture-log log-visible?)) 1375 (define/public-final (hide-log) 1376 (when log-visible? (toggle-log))) 1377 (define/public-final (update-log) 1378 (send frame show/hide-log log-visible?) 1379 (send frame set-logger-text-field-value (send (get-ints) get-user-log-receiver-args-str))) 1380 (define/public-final (update-logger-window command) 1381 (when (is-current-tab?) 1382 (send frame update-logger-window command))) 1383 1384 (define current-planet-status #f) 1385 (define/public-final (new-planet-status a b) 1386 (set! current-planet-status (cons a b)) 1387 (update-planet-status)) 1388 (define/public-final (clear-planet-status) 1389 (set! current-planet-status #f) 1390 (update-planet-status)) 1391 (define/public-final (update-planet-status) 1392 (send frame show-planet-status 1393 (and current-planet-status 1394 (car current-planet-status)) 1395 (and current-planet-status 1396 (cdr current-planet-status)))) 1397 1398 (super-new))) 1399 1400 ;; should only be called by the tab% object (and the class itself) 1401 (define-local-member-name 1402 disable-evaluation-in-tab 1403 enable-evaluation-in-tab 1404 update-toolbar-visibility 1405 show/hide-log 1406 set-logger-text-field-value 1407 show-planet-status 1408 enable-top-level-window-connection) 1409 1410 (define frame-mixin 1411 (mixin (drracket:frame:<%> frame:status-line<%> frame:searchable-text<%> frame:size-pref<%>) 1412 (drracket:unit:frame<%>) 1413 (init filename) 1414 (inherit set-label-prefix get-show-menu 1415 get-menu% 1416 get-area-container 1417 update-info 1418 get-file-menu 1419 search-hidden? 1420 unhide-search 1421 hide-search 1422 file-menu:get-close-item 1423 file-menu:get-save-item 1424 file-menu:get-save-as-item 1425 file-menu:get-revert-item 1426 file-menu:get-print-item 1427 get-eventspace) 1428 1429 (define resizable-panel (drr-named-undefined 'resizable-panel)) 1430 (define definitions-canvas (drr-named-undefined 'definitions-canvas)) 1431 (define definitions-canvases (drr-named-undefined 'definitions-canvases)) 1432 (define interactions-canvas (drr-named-undefined 'interactions-canvas)) 1433 (define interactions-canvases (drr-named-undefined 'interactions-canvases)) 1434 (define button-panel (drr-named-undefined 'button-panel)) 1435 1436 1437 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1438 ;; 1439 ;; execute warning 1440 ;; 1441 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1442 1443 (define execute-warning-panel #f) 1444 (define execute-warning-parent-panel #f) 1445 (define execute-warning-canvas #f) 1446 (define/public-final (show/hide-warning-message msg hide-canvas) 1447 (when (and execute-warning-parent-panel 1448 execute-warning-panel) 1449 (cond 1450 [msg 1451 (cond 1452 [execute-warning-canvas 1453 (send execute-warning-canvas set-message msg)] 1454 [else 1455 (set! execute-warning-canvas 1456 (new execute-warning-canvas% 1457 [stretchable-height #t] 1458 [parent execute-warning-panel] 1459 [message msg])) 1460 (new close-icon% 1461 [parent execute-warning-panel] 1462 [bg-color "yellow"] 1463 [callback (λ () (hide-canvas))])]) 1464 (send execute-warning-parent-panel 1465 change-children 1466 (λ (l) (append (remq execute-warning-panel l) 1467 (list execute-warning-panel))))] 1468 [else 1469 (when execute-warning-canvas 1470 (send execute-warning-parent-panel 1471 change-children 1472 (λ (l) (remq execute-warning-panel l))) 1473 (send execute-warning-canvas set-message #f))]))) 1474 1475 1476 ;; bind the proc to a field 1477 ;; so it stays alive as long 1478 ;; as the frame stays alive 1479 (define show-line-numbers-pref-fn 1480 (let ([fn (lambda (pref value) 1481 (when show-line-numbers-menu-item 1482 (send show-line-numbers-menu-item set-label 1483 (if value 1484 (string-constant hide-line-numbers/menu) 1485 (string-constant show-line-numbers/menu)))) 1486 (show-line-numbers! value))]) 1487 (preferences:add-callback 1488 'drracket:show-line-numbers? 1489 fn 1490 #t) 1491 fn)) 1492 (define show-line-numbers-menu-item #f) 1493 1494 (define/override (add-line-number-menu-items menu) 1495 (define on? (preferences:get 'drracket:show-line-numbers?)) 1496 (new separator-menu-item% [parent menu]) 1497 (new checkable-menu-item% 1498 [label (string-constant show-line-numbers-in-definitions)] 1499 [parent menu] 1500 [checked on?] 1501 [callback 1502 (λ (c dc) 1503 (preferences:set 'drracket:show-line-numbers? (not on?)))]) 1504 (super add-line-number-menu-items menu)) 1505 1506 (define/private (show-line-numbers! show) 1507 (for ([tab tabs]) 1508 (define text (send tab get-defs)) 1509 (send text show-line-numbers! show)) 1510 (send definitions-canvas refresh)) 1511 1512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1513 ;; 1514 ;; logging 1515 ;; 1516 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1517 1518 (define logger-panel #f) 1519 (define logger-parent-panel #f) 1520 1521 ;; logger-gui-content-panel: (or/c #f (is-a?/c vertical-panel%)) 1522 ;; this is #f when the GUI has not been built yet. After 1523 ;; it becomes a panel, it is always a panel 1524 ;; (altho the panel might not always be shown) 1525 (define logger-gui-content-panel #f) 1526 (define logger-gui-canvas #f) 1527 (define logger-checkbox #f) 1528 (define logger-text-field #f) 1529 1530 ;; logger-gui-text: (or/c #f (is-a?/c text%)) 1531 ;; this is #f when the GUI has not been built or when the logging panel is hidden 1532 ;; in that case, the logging messages aren't begin saved in an editor anywhere 1533 (define logger-gui-text #f) 1534 1535 (define logger-menu-item #f) 1536 1537 (define/public-final (show/hide-log show?) 1538 (let ([p (preferences:get 'drracket:logging-size-percentage)]) 1539 (begin-container-sequence) 1540 (cond 1541 [logger-gui-content-panel 1542 (send logger-parent-panel change-children 1543 (λ (l) 1544 (cond 1545 [(or (and show? (member logger-panel l)) 1546 (and (not show?) 1547 (not (member logger-panel l)))) 1548 ;; if things are already up to date, only update the logger text 1549 (when show? 1550 (update-logger-window #f)) 1551 l] 1552 [show? 1553 (new-logger-text) 1554 (send logger-gui-canvas set-editor logger-gui-text) 1555 (update-logger-window #f) 1556 (send logger-menu-item set-label (string-constant hide-log)) 1557 (append (remq logger-panel l) (list logger-panel))] 1558 [else 1559 (send logger-menu-item set-label (string-constant show-log)) 1560 (set! logger-gui-text #f) 1561 (send logger-gui-canvas set-editor #f) 1562 (remq logger-panel l)])))] 1563 [else 1564 (when show? ;; if we want to hide and it isn't built yet, do nothing 1565 (define logger-gui-content-panel-parent (new-vertical-panel% 1566 [style '(border)] 1567 [parent logger-panel] 1568 [stretchable-height #t])) 1569 (set! logger-gui-content-panel 1570 (new-horizontal-panel% 1571 [parent logger-gui-content-panel-parent] 1572 [stretchable-height #f])) 1573 (new-logger-text) 1574 (set! logger-gui-canvas 1575 (new editor-canvas% 1576 [parent logger-gui-content-panel-parent] 1577 [style '(transparent no-border)] 1578 [editor logger-gui-text])) 1579 (new message% [label (string-constant log-messages)] [parent logger-gui-content-panel]) 1580 (new button% 1581 [label (string-constant help)] 1582 [callback (λ (x y) 1583 (define-values (path tag) 1584 (xref-tag->path+anchor 1585 (load-collections-xref) 1586 (make-section-tag 1587 "follow-log" 1588 #:doc '(lib "scribblings/drracket/drracket.scrbl")))) 1589 (define url (path->url path)) 1590 (define url2 (if tag 1591 (make-url (url-scheme url) 1592 (url-user url) 1593 (url-host url) 1594 (url-port url) 1595 (url-path-absolute? url) 1596 (url-path url) 1597 (url-query url) 1598 tag) 1599 url)) 1600 (send-url (url->string url2)))] 1601 [parent logger-gui-content-panel]) 1602 (set! logger-text-field 1603 (keymap:call/text-keymap-initializer 1604 (λ () 1605 (new text-field% 1606 [parent logger-gui-content-panel] 1607 [label "‹level›@‹name› ..."] 1608 [init-value 1609 (send (get-interactions-text) get-user-log-receiver-args-str)] 1610 [callback 1611 (λ (tf evt) 1612 (define str (send (send tf get-editor) get-text)) 1613 (define args (parse-logger-args str)) 1614 (preferences:set 'drracket:logger-receiver-string str) 1615 (send (get-interactions-text) set-user-log-receiver-args 1616 str 1617 (if (null? args) #f args)) 1618 (set-logger-text-field-bg-color args))])))) 1619 (set-logger-text-field-bg-color (parse-logger-args (send logger-text-field get-value))) 1620 (set! logger-checkbox 1621 (new check-box% 1622 [label (string-constant logger-scroll-on-output)] 1623 [callback (λ (a b) (preferences:set 'drracket:logger-scroll-to-bottom? 1624 (send logger-checkbox get-value)))] 1625 [parent logger-gui-content-panel] 1626 [value (preferences:get 'drracket:logger-scroll-to-bottom?)])) 1627 (new button% 1628 [label (string-constant hide-log)] 1629 [callback (λ (x y) (send current-tab hide-log))] 1630 [parent logger-gui-content-panel]) 1631 (send logger-menu-item set-label (string-constant hide-log)) 1632 (update-logger-window #f) 1633 (send logger-parent-panel change-children (λ (l) (append l (list logger-panel)))))]) 1634 (with-handlers ([exn:fail? void]) 1635 (send logger-parent-panel set-percentages (list p (- 1 p)))) 1636 (update-logger-button-label) 1637 (end-container-sequence))) 1638 1639 (define/public (set-logger-text-field-value str) 1640 (when logger-text-field 1641 (send logger-text-field set-value str) 1642 (set-logger-text-field-bg-color (parse-logger-args str)))) 1643 1644 (define/private (set-logger-text-field-bg-color good?) 1645 (send logger-text-field set-field-background 1646 (color-prefs:lookup-in-color-scheme 1647 (if good? 1648 'framework:basic-canvas-background 1649 'framework:failed-search-background-color)))) 1650 1651 (define/private (log-shown?) 1652 (and logger-gui-content-panel 1653 (member logger-panel (send logger-parent-panel get-children)))) 1654 1655 (define/private (new-logger-text) 1656 (set! logger-gui-text (new (text:hide-caret/selection-mixin 1657 (editor:standard-style-list-mixin 1658 text:line-spacing%)))) 1659 (send logger-gui-text lock #t)) 1660 1661 (define/public (update-logger-window command) 1662 (when logger-gui-text 1663 (define admin (send logger-gui-text get-admin)) 1664 (define canvas (send logger-gui-text get-canvas)) 1665 (define (adjust-color start) 1666 (when (white-on-black-panel-scheme?) 1667 (define sd (make-object style-delta%)) 1668 (send sd set-delta-foreground "white") 1669 (send logger-gui-text change-style 1670 sd 1671 start 1672 (send logger-gui-text last-position)))) 1673 (when (and canvas admin) 1674 (define logger-messages (send interactions-text get-logger-messages)) 1675 (cond 1676 [(and (pair? command) 1677 (pair? logger-messages) 1678 ;; just flush and redraw everything if there is one (or zero) logger messages 1679 (pair? (cdr logger-messages))) 1680 (define msg (cdr command)) 1681 (define scroll? (if (object? logger-checkbox) 1682 (send logger-checkbox get-value) 1683 #t)) 1684 (send logger-gui-text begin-edit-sequence) 1685 (send logger-gui-text lock #f) 1686 (define start (send logger-gui-text last-position)) 1687 (case (car command) 1688 [(add-line) (void)] 1689 [(clear-last-and-add-line) 1690 (send logger-gui-text delete 1691 0 1692 (send logger-gui-text paragraph-start-position 1) 1693 #f)]) 1694 (send logger-gui-text insert 1695 "\n" 1696 (send logger-gui-text last-position) 1697 (send logger-gui-text last-position) 1698 #f) 1699 (send logger-gui-text insert 1700 msg 1701 (send logger-gui-text last-position) 1702 (send logger-gui-text last-position) 1703 #f) 1704 (when scroll? 1705 (send logger-gui-text scroll-to-position 1706 (send logger-gui-text 1707 paragraph-start-position 1708 (send logger-gui-text last-paragraph)))) 1709 (adjust-color start) 1710 (send logger-gui-text end-edit-sequence) 1711 (send logger-gui-text lock #t)] 1712 [else 1713 (send logger-gui-text begin-edit-sequence) 1714 (send logger-gui-text lock #f) 1715 (send logger-gui-text erase) 1716 (define start (send logger-gui-text last-position)) 1717 1718 (define (insert-one msg) 1719 (send logger-gui-text insert msg 0 0)) 1720 1721 (unless (null? logger-messages) 1722 ;; skip the last newline in the buffer 1723 (insert-one (car logger-messages)) 1724 (for ([msg (in-list (cdr (send interactions-text get-logger-messages)))]) 1725 (insert-one "\n") 1726 (insert-one msg))) 1727 1728 (adjust-color start) 1729 (send logger-gui-text lock #t) 1730 (send logger-gui-text end-edit-sequence)])))) 1731 1732 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1733 ;; 1734 ;; planet status 1735 ;; 1736 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1737 1738 (define planet-status-parent-panel #f) 1739 (define planet-status-panel #f) 1740 (define planet-message #f) 1741 (define planet-logger-button #f) 1742 ;; local-member-name 1743 (define/public (show-planet-status tag package) 1744 (cond 1745 [(and (not tag) 1746 (not package) 1747 (or (not planet-status-parent-panel) 1748 (not (member planet-status-panel 1749 (send planet-status-parent-panel get-children))))) 1750 ;; if there is no information and there is no GUI there, don't do anything 1751 (void)] 1752 [else 1753 (when planet-status-panel 1754 (unless planet-message 1755 (new message% 1756 [parent planet-status-panel] 1757 [label drracket:debug:small-planet-bitmap]) 1758 (set! planet-message (new message% 1759 [parent planet-status-panel] 1760 [label ""] 1761 [stretchable-width #t])) 1762 (set! planet-logger-button 1763 (new button% 1764 [font small-control-font] 1765 [parent planet-status-panel] 1766 [label (string-constant show-log)] 1767 [callback (λ (a b) (send current-tab toggle-log))])) 1768 (update-logger-button-label) 1769 (new close-icon% 1770 [parent planet-status-panel] 1771 [callback (λ () 1772 (send planet-status-parent-panel change-children 1773 (λ (l) 1774 (remq planet-status-panel l))) 1775 (send current-tab clear-planet-status))])) 1776 (send planet-message set-label 1777 (case tag 1778 [(download) 1779 (format (string-constant planet-downloading) package)] 1780 [(install) 1781 (format (string-constant planet-installing) package)] 1782 [(docs-build) 1783 (format (string-constant planet-docs-building) package)] 1784 [(finish) 1785 (format (string-constant planet-finished) package)] 1786 [else 1787 (string-constant planet-no-status)])) 1788 (send planet-status-parent-panel change-children 1789 (λ (l) 1790 (if (memq planet-status-panel l) 1791 l 1792 (append (remq planet-status-panel l) (list planet-status-panel))))))])) 1793 1794 (define/private (update-logger-button-label) 1795 (when planet-logger-button 1796 (send planet-logger-button set-label 1797 (if (and logger-gui-text 1798 (member logger-panel (send logger-parent-panel get-children))) 1799 (string-constant hide-log) 1800 (string-constant show-log))))) 1801 1802 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1803 ;; 1804 ;; transcript 1805 ;; 1806 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1807 1808 1809 ;; transcript : (union #f string[directory-name]) 1810 (field [transcript #f] 1811 [definitions-transcript-counter 0] ;; number 1812 [interactions-transcript-counter 0] ;; number 1813 [transcript-parent-panel #f] ;; panel (unitialized short time only) 1814 [transcript-panel #f] ;; panel (unitialized short time only) 1815 [transcript-menu-item #f]) ;; menu-item (unitialized short time only) 1816 ;; record-definitions : -> void 1817 (define/private (record-definitions) 1818 (when transcript 1819 (set! definitions-transcript-counter (+ definitions-transcript-counter 1)) 1820 (send definitions-text save-file 1821 (build-path transcript (format "~a-definitions" 1822 (pad-two definitions-transcript-counter))) 1823 'copy))) 1824 1825 ;; record-ineractions : -> void 1826 (define/private (record-interactions) 1827 (when transcript 1828 (set! interactions-transcript-counter (+ interactions-transcript-counter 1)) 1829 (send interactions-text save-file 1830 (build-path transcript (format "~a-interactions" 1831 (pad-two interactions-transcript-counter))) 1832 'copy))) 1833 1834 ;; pad-two : number -> string 1835 ;; pads a number to two digits? 1836 (define/private (pad-two n) 1837 (cond 1838 [(<= 0 n 9) (format "0~a" n)] 1839 [else (format "~a" n)])) 1840 1841 ;; start-transcript : -> void 1842 ;; turns on the transcript and shows the transcript gui 1843 (define/private (start-transcript) 1844 (let ([transcript-directory (mred:get-directory 1845 (string-constant please-choose-a-log-directory) 1846 this)]) 1847 (when (and transcript-directory 1848 (ensure-empty transcript-directory)) 1849 (send transcript-menu-item set-label (string-constant stop-logging)) 1850 (set! transcript transcript-directory) 1851 (set! definitions-transcript-counter 0) 1852 (set! interactions-transcript-counter 0) 1853 (build-transcript-panel) 1854 (record-definitions)))) 1855 1856 ;; stop-transcript : -> void 1857 ;; turns off the transcript procedure 1858 (define/private (stop-transcript) 1859 (record-interactions) 1860 (send transcript-menu-item set-label (string-constant log-definitions-and-interactions)) 1861 (set! transcript #f) 1862 (send transcript-panel change-children (λ (l) null))) 1863 1864 ;; build-transcript-panel : -> void 1865 ;; builds the contents of the transcript panel 1866 (define/private (build-transcript-panel) 1867 (define hp (make-object horizontal-panel% transcript-panel '(border))) 1868 (make-object message% (string-constant logging-to) hp) 1869 (send (make-object message% (path->string transcript) hp) stretchable-width #t) 1870 (make-object button% (string-constant stop-logging) hp (λ (x y) (stop-transcript)))) 1871 1872 ;; ensure-empty : string[directory] -> boolean 1873 ;; if the transcript-directory is empty, just return #t 1874 ;; if not, ask the user about emptying it. 1875 ;; if they say yes, try to empty it. 1876 ;; if that fails, report the error and return #f. 1877 ;; if it succeeds, return #t. 1878 ;; if they say no, return #f. 1879 (define/private (ensure-empty transcript-directory) 1880 (let ([dir-list (directory-list transcript-directory)]) 1881 (or (null? dir-list) 1882 (let ([query (message-box 1883 (string-constant drscheme) 1884 (gui-utils:format-literal-label 1885 (string-constant erase-log-directory-contents) 1886 transcript-directory) 1887 this 1888 '(yes-no) 1889 #:dialog-mixin frame:focus-table-mixin)]) 1890 (cond 1891 [(equal? query 'no) 1892 #f] 1893 [(equal? query 'yes) 1894 (with-handlers ([exn:fail:filesystem? 1895 (λ (exn) 1896 (message-box 1897 (string-constant drscheme) 1898 (gui-utils:format-literal-label 1899 (string-constant error-erasing-log-directory) 1900 (if (exn? exn) 1901 (format "~a" (exn-message exn)) 1902 (format "~s" exn))) 1903 this 1904 #:dialog-mixin frame:focus-table-mixin) 1905 #f)]) 1906 (for-each (λ (file) (delete-file (build-path transcript-directory file))) 1907 dir-list) 1908 #t)]))))) 1909 1910 (define/override (make-root-area-container cls parent) 1911 (let* ([_module-browser-parent-panel 1912 (super make-root-area-container 1913 (make-two-way-prefs-dragable-panel% panel:horizontal-dragable% 1914 'drracket:module-browser-size-percentage) 1915 parent)] 1916 [_module-browser-panel (new-vertical-panel% 1917 (parent _module-browser-parent-panel) 1918 (alignment '(left center)) 1919 (stretchable-width #f))] 1920 [planet-status-outer-panel (new vertical-pane% [parent _module-browser-parent-panel])] 1921 [execute-warning-outer-panel (new vertical-pane% [parent planet-status-outer-panel])] 1922 [logger-outer-panel (new (make-two-way-prefs-dragable-panel% 1923 panel:vertical-dragable% 1924 'drracket:logging-size-percentage) 1925 [parent execute-warning-outer-panel])] 1926 [trans-outer-panel (new vertical-pane% [parent logger-outer-panel])] 1927 [root (make-object cls trans-outer-panel)]) 1928 (set! module-browser-parent-panel _module-browser-parent-panel) 1929 (set! module-browser-panel _module-browser-panel) 1930 (send module-browser-parent-panel change-children (λ (l) (remq module-browser-panel l))) 1931 (set! logger-parent-panel logger-outer-panel) 1932 (set! logger-panel (new-vertical-panel% [parent logger-parent-panel])) 1933 (send logger-parent-panel change-children (lambda (x) (remq logger-panel x))) 1934 1935 (set! execute-warning-parent-panel execute-warning-outer-panel) 1936 (set! execute-warning-panel (new-horizontal-panel% 1937 [parent execute-warning-parent-panel] 1938 [stretchable-height #f])) 1939 (send execute-warning-parent-panel change-children (λ (l) (remq execute-warning-panel l))) 1940 1941 (set! transcript-parent-panel (new-horizontal-panel% 1942 (parent trans-outer-panel) 1943 (stretchable-height #f))) 1944 (set! transcript-panel (make-object horizontal-panel% transcript-parent-panel)) 1945 (set! planet-status-parent-panel (new-vertical-panel% 1946 [parent planet-status-outer-panel] 1947 [stretchable-height #f])) 1948 (set! planet-status-panel (new-horizontal-panel% 1949 [parent planet-status-parent-panel])) 1950 (send planet-status-parent-panel change-children (λ (l) (remq planet-status-panel l))) 1951 (unless (toolbar-shown?) 1952 (send transcript-parent-panel change-children (λ (l) '()))) 1953 (send logger-outer-panel enable-two-way-prefs) 1954 (send _module-browser-parent-panel enable-two-way-prefs) 1955 1956 root)) 1957 1958 (inherit show-info hide-info is-info-hidden?) 1959 (field [toolbar-state (preferences:get 'drracket:toolbar-state)] 1960 [toolbar-top-menu-item #f] 1961 [toolbar-top-no-label-menu-item #f] 1962 [toolbar-left-menu-item #f] 1963 [toolbar-right-menu-item #f] 1964 [toolbar-hidden-menu-item #f] 1965 [toolbar-menu #f]) 1966 1967 ;; returns #t if the toolbar is visible, #f otherwise 1968 (define/private (toolbar-shown?) (car toolbar-state)) 1969 1970 (define/private (change-toolbar-state new-state) 1971 (set! toolbar-state new-state) 1972 (preferences:set 'drracket:toolbar-state new-state) 1973 (update-toolbar-visibility)) 1974 1975 (define/override (on-toolbar-button-click) 1976 (change-toolbar-state (cons (not (car toolbar-state)) (cdr toolbar-state)))) 1977 (define/private (set-toolbar-left) (change-toolbar-state (cons #f 'left))) 1978 (define/private (set-toolbar-right) (change-toolbar-state (cons #f 'right))) 1979 (define/private (set-toolbar-top) (change-toolbar-state (cons #f 'top))) 1980 (define/private (set-toolbar-top-no-label) (change-toolbar-state (cons #f 'top-no-label))) 1981 (define/private (set-toolbar-hidden) (change-toolbar-state (cons #t (cdr toolbar-state)))) 1982 1983 (define/public (update-toolbar-visibility) 1984 (let* ([hidden? (toolbar-is-hidden?)] 1985 [left? (toolbar-is-left?)] 1986 [right? (toolbar-is-right?)] 1987 [top? (toolbar-is-top?)] 1988 [top-no-label? (toolbar-is-top-no-label?)]) 1989 1990 (send toolbar-left-menu-item check left?) 1991 (send toolbar-right-menu-item check right?) 1992 (send toolbar-top-menu-item check top?) 1993 (send toolbar-top-no-label-menu-item check top-no-label?) 1994 (send toolbar-hidden-menu-item check hidden?) 1995 1996 (cond 1997 [hidden? 1998 (hide-info) 1999 (send top-outer-panel change-children (λ (l) '())) 2000 (send transcript-parent-panel change-children (λ (l) '()))] 2001 [top? (orient/show #t)] 2002 [top-no-label? (orient/show #t)] 2003 [left? (orient/show #t)] 2004 [right? (orient/show #f)])) 2005 (update-defs/ints-resize-corner)) 2006 2007 (define/private (toolbar-is-hidden?) 2008 (car (preferences:get 'drracket:toolbar-state))) 2009 (define/private (toolbar-is-top?) 2010 (and (not (toolbar-is-hidden?)) 2011 (equal? (cdr (preferences:get 'drracket:toolbar-state)) 2012 'top))) 2013 (define/private (toolbar-is-right?) 2014 (and (not (toolbar-is-hidden?)) 2015 (equal? (cdr (preferences:get 'drracket:toolbar-state)) 2016 'right))) 2017 (define/private (toolbar-is-left?) 2018 (and (not (toolbar-is-hidden?)) 2019 (equal? (cdr (preferences:get 'drracket:toolbar-state)) 2020 'left))) 2021 (define/private (toolbar-is-top-no-label?) 2022 (and (not (toolbar-is-hidden?)) 2023 (equal? (cdr (preferences:get 'drracket:toolbar-state)) 2024 'top-no-label))) 2025 2026 (define/private (orient/show bar-at-beginning?) 2027 (let ([vertical? (or (toolbar-is-left?) (toolbar-is-right?))]) 2028 (begin-container-sequence) 2029 (show-info) 2030 2031 ;; orient the button panel and all panels inside it. 2032 (let loop ([obj button-panel]) 2033 (when (is-a? obj area-container<%>) 2034 (when (or (is-a? obj vertical-panel%) 2035 (is-a? obj horizontal-panel%) 2036 (is-a? obj panel:discrete-sizes<%>)) 2037 (unless (equal? (send obj get-orientation) (not vertical?)) 2038 (send obj set-orientation (not vertical?)))) 2039 (for-each loop (send obj get-children)))) 2040 (sort-toolbar-buttons-panel) 2041 2042 (set-toolbar-label-visibilities/check-registered) 2043 2044 (send top-outer-panel stretchable-height vertical?) 2045 (send top-outer-panel stretchable-width (not vertical?)) 2046 (send top-panel set-orientation (not vertical?)) 2047 (send toolbar/rest-panel set-orientation vertical?) 2048 (send toolbar/rest-panel change-children 2049 (λ (l) 2050 (if bar-at-beginning? 2051 (cons top-outer-panel (remq top-outer-panel l)) 2052 (append (remq top-outer-panel l) (list top-outer-panel))))) 2053 (send top-outer-panel change-children (λ (l) (list top-panel))) 2054 (send transcript-parent-panel change-children (λ (l) (list transcript-panel))) 2055 2056 (let* ([settings (send definitions-text get-next-settings)] 2057 [language (drracket:language-configuration:language-settings-language settings)] 2058 [name (get-define-popup-name 2059 (get-define-popup-info 2060 (send language capability-value 'drscheme:define-popup)) 2061 vertical?)]) 2062 (when name 2063 (send func-defs-canvas set-message #f name))) 2064 (send name-message set-short-title vertical?) 2065 (send name-panel set-orientation (not vertical?)) 2066 (if vertical? 2067 (send name-panel set-alignment 'right 'top) 2068 (send name-panel set-alignment 'left 'center)) 2069 (end-container-sequence))) 2070 2071 ;; this table uses object identity on buttons(!) 2072 (define toolbar-buttons (make-hasheq)) 2073 (define smallest #f) 2074 2075 (define/public (register-toolbar-button b #:number [number/f #f]) 2076 (add-to-toolbar-buttons 'register-toolbar-button b number/f) 2077 (set-toolbar-label-visibilities/check-registered) 2078 (sort-toolbar-buttons-panel)) 2079 2080 (define/public (register-toolbar-buttons bs #:numbers [numbers/fs (make-list (length bs) #f)]) 2081 (for ([b (in-list bs)] 2082 [n (in-list numbers/fs)]) 2083 (add-to-toolbar-buttons 'register-toolbar-buttons b n)) 2084 (set-toolbar-label-visibilities/check-registered) 2085 (sort-toolbar-buttons-panel)) 2086 2087 (define/private (add-to-toolbar-buttons who button number/f) 2088 (define number (or number/f (if smallest (- smallest 1) 100))) 2089 (define prev (hash-ref toolbar-buttons button #f)) 2090 (when (and prev (not (= prev number))) 2091 (error who "cannot add toolbar button ~s with number ~a; already added with ~a" 2092 (send button get-label) 2093 number 2094 prev)) 2095 (when (or (not smallest) (< number smallest)) 2096 (set! smallest number)) 2097 (hash-set! toolbar-buttons button number)) 2098 2099 (define/private (in-toolbar-list? b) (hash-ref toolbar-buttons b #f)) 2100 2101 (define/public (unregister-toolbar-button b) 2102 (hash-remove! toolbar-buttons b) 2103 (set! smallest 2104 (if (zero? (hash-count toolbar-buttons)) 2105 #f 2106 (apply min (hash-map toolbar-buttons (λ (x y) y))))) 2107 (void)) 2108 2109 (define/public (sort-toolbar-buttons-panel) 2110 (define bp (get-button-panel)) 2111 (define (cmp panel) 2112 (cond 2113 [(is-a? panel vertical-pane%) >=] 2114 [(is-a? panel horizontal-pane%) <=] 2115 [else 2116 (if (send panel get-orientation) ;; horizontal is #t 2117 <= 2118 >=)])) 2119 (when (is-a? bp panel%) 2120 (let sort-loop ([panel bp]) 2121 (define min #f) 2122 (send panel change-children 2123 (λ (l) 2124 (define sub-panel-nums (make-hash)) 2125 (for ([x (in-list l)]) 2126 (when (is-a? x area-container<%>) 2127 (define rec-res (sort-loop x)) 2128 (when rec-res 2129 (hash-set! sub-panel-nums x rec-res)))) 2130 (define (key item) 2131 (define missing-num -5000) 2132 (cond 2133 [(is-a? item area-container<%>) 2134 (hash-ref sub-panel-nums item missing-num)] 2135 [else 2136 (hash-ref toolbar-buttons item missing-num)])) 2137 (define ans (sort l (cmp panel) #:key key)) 2138 (set! min (if (null? ans) 2139 #f 2140 (key (car ans)))) 2141 ans)) 2142 min) 2143 (void))) 2144 2145 (define/private (set-toolbar-label-visibilities/check-registered) 2146 (define label-visible? (toolbar-is-top?)) 2147 (for ([(button number) (in-hash toolbar-buttons)]) 2148 (send button set-label-visible label-visible?)) 2149 2150 (let loop ([obj button-panel]) 2151 (cond 2152 [(is-a? obj area-container<%>) 2153 (for-each loop (send obj get-children))] 2154 [(is-a? obj switchable-button%) 2155 (unless (in-toolbar-list? obj) 2156 (error 'register-toolbar-button 2157 "found a switchable-button% that is not registered, label ~s" 2158 (send obj get-label)))] 2159 [else (void)]))) 2160 2161 (field [remove-show-status-line-callback 2162 (preferences:add-callback 2163 'framework:show-status-line 2164 (λ (p v) 2165 (update-defs/ints-resize-corner/pref v)))]) 2166 2167 (define/private (update-defs/ints-resize-corner) 2168 (update-defs/ints-resize-corner/pref 2169 (preferences:get 'framework:show-status-line))) 2170 2171 (define/private (update-defs/ints-resize-corner/pref si-pref) 2172 (let ([bottom-material? (and (not (car toolbar-state)) 2173 si-pref)]) 2174 (let loop ([cs definitions-canvases]) 2175 (cond 2176 [(null? cs) (void)] 2177 [(null? (cdr cs)) 2178 (send (car cs) set-resize-corner (and (not bottom-material?) 2179 (not interactions-shown?)))] 2180 [else 2181 (send (car cs) set-resize-corner #f) 2182 (loop (cdr cs))])) 2183 (let loop ([cs interactions-canvases]) 2184 (cond 2185 [(null? cs) (void)] 2186 [(null? (cdr cs)) 2187 (send (car cs) set-resize-corner (and (not bottom-material?) 2188 interactions-shown?))] 2189 [else 2190 (send (car cs) set-resize-corner #f) 2191 (loop (cdr cs))])))) 2192 2193 [define definitions-item #f] 2194 [define interactions-item #f] 2195 [define name-message #f] 2196 [define save-button #f] 2197 [define save-init-shown? #f] 2198 2199 [define/private set-save-init-shown? (λ (x) (set! save-init-shown? x))] 2200 2201 [define canvas-show-mode #f] 2202 [define allow-split? #f] 2203 [define forced-quit? #f] 2204 [define search-canvas #f] 2205 2206 (define/public (make-searchable canvas) 2207 (update-info) 2208 (set! search-canvas canvas)) 2209 2210 (define was-locked? #f) 2211 2212 (define/public-final (disable-evaluation-in-tab tab) 2213 (when (eq? tab current-tab) 2214 (disable-evaluation))) 2215 2216 (define/pubment (disable-evaluation) 2217 (when execute-menu-item 2218 (send execute-menu-item enable #f)) 2219 (send execute-button enable #f) 2220 (inner (void) disable-evaluation)) 2221 2222 (define/public-final (enable-evaluation-in-tab tab) 2223 (when (eq? tab current-tab) 2224 (enable-evaluation))) 2225 2226 (define/pubment (enable-evaluation) 2227 (when execute-menu-item 2228 (send execute-menu-item enable #t)) 2229 (send execute-button enable #t) 2230 (inner (void) enable-evaluation)) 2231 2232 (inherit set-label) 2233 (inherit modified) 2234 (define/public (update-save-button) 2235 (let ([mod? (send definitions-text is-modified?)]) 2236 (modified mod?) 2237 (if save-button 2238 (unless (equal? mod? (send save-button is-shown?)) 2239 (send save-button show mod?)) 2240 (set! save-init-shown? mod?)) 2241 (update-tab-label current-tab))) 2242 2243 (define/public (language-changed) 2244 (define settings (send definitions-text get-next-settings)) 2245 (define language (drracket:language-configuration:language-settings-language settings)) 2246 (send func-defs-canvas language-changed language (or (toolbar-is-left?) 2247 (toolbar-is-right?))) 2248 (send language-message set-yellow/lang 2249 (not (send definitions-text this-and-next-language-the-same?)) 2250 (string-append (send language get-language-name) 2251 (if (send language default-settings? 2252 (drracket:language-configuration:language-settings-settings 2253 settings)) 2254 "" 2255 (string-append " " (string-constant custom))) 2256 " ")) 2257 (update-teachpack-menu) 2258 (when (is-a? language-specific-menu menu%) 2259 (define label (send language-specific-menu get-label)) 2260 (define new-label (send language capability-value 'drscheme:language-menu-title)) 2261 (unless (equal? label new-label) 2262 (send language-specific-menu set-label new-label)))) 2263 2264 (define/public (get-language-menu) language-specific-menu) 2265 2266 ;; update-save-message : -> void 2267 ;; sets the save message. If input is #f, uses the frame's 2268 ;; title. 2269 (define/public (update-save-message) 2270 (when name-message 2271 (let ([filename (send definitions-text get-filename)]) 2272 (send name-message set-message 2273 (if filename #t #f) 2274 (send definitions-text get-filename/untitled-name)))) 2275 (update-tabs-labels)) 2276 2277 (define/private (update-tabs-labels) 2278 (for-each (λ (tab) (update-tab-label tab)) tabs) 2279 (send tabs-panel set-selection (send current-tab get-i)) 2280 (send (send tabs-panel get-parent) 2281 change-children 2282 (λ (l) 2283 (cond 2284 [(= (send tabs-panel get-number) 1) 2285 (remq tabs-panel l)] 2286 [else 2287 (if (memq tabs-panel l) 2288 l 2289 (cons tabs-panel l))])))) 2290 2291 (define/private (update-tab-label tab) 2292 (let ([label (gui-utils:trim-string (get-defs-tab-label (send tab get-defs) tab) 200)]) 2293 (unless (equal? label (send tabs-panel get-item-label (send tab get-i))) 2294 (send tabs-panel set-item-label (send tab get-i) label)))) 2295 2296 ;; get-tab-filename : (or/c (is-a?/c tab<%>) natural?) -> string? [the tab's label] 2297 (define/public (get-tab-filename _tab) 2298 (define tab 2299 (cond 2300 [(exact-nonnegative-integer? _tab) (list-ref tabs _tab)] 2301 [else _tab])) 2302 (get-defs-tab-filename (send tab get-defs))) 2303 2304 (define/private (get-defs-tab-label defs tab) 2305 (define tab-index 2306 (for/or ([i (in-list tabs)] 2307 [n (in-naturals 1)]) 2308 (and (eq? i tab) n))) 2309 (define i-prefix 2310 (cond 2311 [(not tab-index) ""] 2312 [(<= tab-index 8) (format "~a: " tab-index)] 2313 [(= tab-index (get-tab-count)) "9: "] 2314 [else ""])) 2315 (add-modified-flag 2316 defs 2317 (string-append 2318 i-prefix 2319 (get-defs-tab-filename defs)))) 2320 2321 (define/private (get-defs-tab-filename defs) 2322 (let ([fn (send defs get-filename)]) 2323 (if fn 2324 (get-tab-label-from-filename fn) 2325 (send defs get-filename/untitled-name)))) 2326 2327 ;; tab-label-cache-valid : (listof path) 2328 ;; If the current set of filenames in the tabs is the 2329 ;; same set of filenames as in this list, then the 2330 ;; tab-label-cache is valid; otherwise not 2331 (define tab-label-cache-valid '()) 2332 2333 ;; tab-label-cache : path -o> string 2334 (define tab-label-cache (make-hasheq)) 2335 2336 (define/private (get-tab-label-from-filename fn) 2337 (define current-paths (map (lambda (tab) (send (send tab get-defs) get-filename)) 2338 tabs)) 2339 (unless (and (= (length tab-label-cache-valid) (length current-paths)) 2340 (andmap eq? tab-label-cache-valid current-paths)) 2341 (set! tab-label-cache-valid current-paths) 2342 (set! tab-label-cache (make-hasheq))) 2343 (define nfn (simple-form-path fn)) 2344 (hash-ref! tab-label-cache 2345 fn 2346 (lambda () 2347 (path->string 2348 (or (shrink-path-wrt 2349 nfn 2350 (filter values 2351 (for/list ([other-tab (in-list tabs)]) 2352 (define fn (send (send other-tab get-defs) get-filename)) 2353 (and fn (simple-form-path fn))))) 2354 (let-values ([(base name dir?) (split-path nfn)]) 2355 name)))))) 2356 2357 (define/private (add-modified-flag text string) 2358 (if (send text is-modified?) 2359 (let ([prefix (get-save-diamond-prefix)]) 2360 (if prefix 2361 (string-append prefix string) 2362 string)) 2363 string)) 2364 2365 (define/private (get-save-diamond-prefix) 2366 (let ([candidate-prefixes 2367 ;; be sure asterisk is at the end of each list, 2368 ;; since that's a relatively safe character 2369 (case (system-type) 2370 [(unix windows) '("★ " "◆ " "• " "* ")] 2371 [else '("◆ " "★ " "• " "* ")])]) 2372 (ormap 2373 (lambda (candidate) 2374 (and (andmap (λ (x) (send normal-control-font screen-glyph-exists? x #t)) 2375 (string->list candidate)) 2376 candidate)) 2377 candidate-prefixes))) 2378 2379 [define/override get-canvas% (λ () (drracket:get/extend:get-definitions-canvas))] 2380 2381 (define/public (update-running running?) 2382 (send running-canvas set-running running?)) 2383 (define/public (ensure-defs-shown) 2384 (unless definitions-shown? 2385 (toggle-show/hide-definitions) 2386 (update-shown))) 2387 (define/public (ensure-rep-shown rep) 2388 (unless (is-a? rep drracket:rep:text<%>) 2389 (raise-argument-error 'ensure-rep-shown 2390 (format "~s" '(is-a?/c drracket:rep:text<%>)) 2391 rep)) 2392 (unless (eq? rep interactions-text) 2393 (let loop ([tabs tabs]) 2394 (unless (null? tabs) 2395 (let ([tab (car tabs)]) 2396 (if (eq? (send tab get-ints) rep) 2397 (change-to-tab tab) 2398 (loop (cdr tabs))))))) 2399 (unless interactions-shown? 2400 (toggle-show/hide-interactions) 2401 (update-shown))) 2402 (define/public (ensure-rep-hidden) 2403 (when interactions-shown? 2404 (toggle-show/hide-interactions) 2405 (update-shown))) 2406 2407 (define/override (get-editor%) (drracket:get/extend:get-definitions-text)) 2408 (define/public (still-untouched?) 2409 (and (send definitions-text still-untouched?) 2410 (let* ([prompt (send interactions-text get-prompt)] 2411 [first-prompt-para 2412 (let loop ([n 0]) 2413 (cond 2414 [(n . <= . (send interactions-text last-paragraph)) 2415 (if (string=? 2416 (send interactions-text get-text 2417 (send interactions-text paragraph-start-position n) 2418 (+ (send interactions-text paragraph-start-position n) 2419 (string-length prompt))) 2420 prompt) 2421 n 2422 (loop (+ n 1)))] 2423 [else #f]))]) 2424 (and first-prompt-para 2425 (= first-prompt-para (send interactions-text last-paragraph)) 2426 (equal? 2427 (send interactions-text get-text 2428 (send interactions-text paragraph-start-position first-prompt-para) 2429 (send interactions-text paragraph-end-position first-prompt-para)) 2430 (send interactions-text get-prompt)))))) 2431 (define/public (change-to-file name) 2432 (cond 2433 [(and name (file-exists? name)) 2434 (ensure-rep-hidden) 2435 (send definitions-text begin-edit-sequence #t #f) 2436 (send definitions-text load-file/gui-error name) 2437 (send definitions-text end-edit-sequence) 2438 (send language-message set-yellow #f)] 2439 [name 2440 (send definitions-text set-filename name)] 2441 [else (send definitions-text clear)]) 2442 (send definitions-canvas focus)) 2443 2444 2445 2446 2447 2448 2449 ; 2450 ; 2451 ; 2452 ; ; 2453 ; ; 2454 ; ; 2455 ; ; ;; ;; ;;; ;; ; ;;; ;;; 2456 ; ;; ;; ; ; ; ; ;; ; ; ; 2457 ; ; ; ; ; ; ; ; ; ; ;; 2458 ; ; ; ; ; ; ; ; ;;;;;; ;; 2459 ; ; ; ; ; ; ; ; ; ; 2460 ; ; ; ; ; ; ; ;; ; ; 2461 ; ; ; ; ;;; ;; ; ;;;; ;;; 2462 ; 2463 ; 2464 ; 2465 2466 2467 (define/private (add-modes-submenu edit-menu) 2468 (new menu% 2469 [parent edit-menu] 2470 [label (string-constant mode-submenu-label)] 2471 [demand-callback 2472 (λ (menu) 2473 (for ([item (in-list (send menu get-items))]) 2474 (send item delete)) 2475 (for ([mode (in-list (drracket:modes:get-modes))]) 2476 (define item 2477 (new checkable-menu-item% 2478 (label (drracket:modes:mode-name mode)) 2479 (parent menu) 2480 (callback 2481 (λ (_1 _2) (send definitions-text set-current-mode 2482 mode))))) 2483 (when (send definitions-text is-current-mode? mode) 2484 (send item check #t))))])) 2485 2486 2487 2488 2489 ; 2490 ; 2491 ; 2492 ; ; ; ; ; ; 2493 ; ; ; ; ; 2494 ; ; ; ; ; ; 2495 ; ;;; ; ;; ; ; ;;;; ; ;;; ;;; ; ; ;;; ; ;; ;;; ;;; 2496 ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; 2497 ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; 2498 ; ;; ; ; ; ; ; ; ; ; ; ; ; ;;;; ; ; ;; ;;;;;; 2499 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 2500 ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; 2501 ; ;;; ; ;; ; ; ;; ; ;;; ;;; ; ; ;;;;; ; ;; ;;; ;;;; 2502 ; ; ; ; 2503 ; ; ; ; 2504 ; ; ; 2505 2506 2507 (inherit get-edit-target-window) 2508 2509 (define/public (split) 2510 (let ([canvas-to-be-split (get-edit-target-window)]) 2511 (cond 2512 [(memq canvas-to-be-split definitions-canvases) 2513 (split-definitions canvas-to-be-split)] 2514 [(memq canvas-to-be-split interactions-canvases) 2515 (split-interactions canvas-to-be-split)] 2516 [else (bell)]))) 2517 2518 (define/private (split-definitions canvas-to-be-split) 2519 (handle-split canvas-to-be-split 2520 (λ (x) (set! definitions-canvases x)) 2521 definitions-canvases 2522 (drracket:get/extend:get-definitions-canvas) 2523 definitions-text)) 2524 2525 (define/private (split-interactions canvas-to-be-split) 2526 (handle-split canvas-to-be-split 2527 (λ (x) (set! interactions-canvases x)) 2528 interactions-canvases 2529 (drracket:get/extend:get-interactions-canvas) 2530 interactions-text)) 2531 2532 (define/private (handle-split canvas-to-be-split set-canvases! canvases canvas% text) 2533 (let-values ([(ox oy ow oh cursor-y) 2534 (get-visible-region canvas-to-be-split)]) 2535 (let ([orig-percentages (send resizable-panel get-percentages)] 2536 [orig-canvases (send resizable-panel get-children)] 2537 [new-canvas (new canvas% 2538 (parent resizable-panel) 2539 (editor text) 2540 (style '()))]) 2541 2542 (set-canvases! 2543 (let loop ([canvases canvases]) 2544 (cond 2545 [(null? canvases) (error 'split "couldn't split; didn't find canvas")] 2546 [else 2547 (let ([canvas (car canvases)]) 2548 (if (eq? canvas canvas-to-be-split) 2549 (list* new-canvas 2550 canvas 2551 (cdr canvases)) 2552 (cons canvas (loop (cdr canvases)))))]))) 2553 2554 (update-shown) 2555 2556 ;; with-handlers prevents bad calls to set-percentages 2557 ;; might still leave GUI in bad state, however. 2558 (with-handlers ([exn:fail? (λ (x) (void))]) 2559 (send resizable-panel set-percentages 2560 (let loop ([canvases orig-canvases] 2561 [percentages orig-percentages]) 2562 (cond 2563 [(null? canvases) 2564 (error 'split "couldn't split; didn't find canvas")] 2565 [(null? percentages) 2566 (error 'split "wrong number of percentages: ~s ~s" 2567 orig-percentages 2568 (send resizable-panel get-children))] 2569 [else (let ([canvas (car canvases)]) 2570 (if (eq? canvas-to-be-split canvas) 2571 (list* (/ (car percentages) 2) 2572 (/ (car percentages) 2) 2573 (cdr percentages)) 2574 (cons 2575 (car percentages) 2576 (loop (cdr canvases) 2577 (cdr percentages)))))])))) 2578 2579 (set-visible-region new-canvas ox oy ow oh cursor-y) 2580 (set-visible-region canvas-to-be-split ox oy ow oh cursor-y) 2581 2582 (send new-canvas focus)))) 2583 2584 ;; split-demand : menu-item -> void 2585 ;; enables the menu-item if splitting is allowed, disables otherwise 2586 (define/private (split-demand item) 2587 (let ([canvas-to-be-split (get-edit-target-window)]) 2588 (send item enable 2589 (or (memq canvas-to-be-split definitions-canvases) 2590 (memq canvas-to-be-split interactions-canvases))))) 2591 2592 ;; collapse-demand : menu-item -> void 2593 ;; enables the menu-item if collapsing is allowed, disables otherwise 2594 (define/private (collapse-demand item) 2595 (let ([canvas-to-be-split (get-edit-target-window)]) 2596 (cond 2597 [(memq canvas-to-be-split definitions-canvases) 2598 (send item enable (2 . <= . (length definitions-canvases)))] 2599 [(memq canvas-to-be-split interactions-canvases) 2600 (send item enable (2 . <= . (length interactions-canvases)))] 2601 [else 2602 (send item enable #f)]))) 2603 2604 ;; get-visible-region : editor-canvas -> number number number number (union #f number) 2605 ;; calculates the visible region of the editor in this editor-canvas, returning 2606 ;; four numbers for the x, y, width and height of the visible region 2607 ;; also, the last two booleans indiciate if the beginning and the end 2608 ;; of the selection was visible before the split, respectively. 2609 (define/private (get-visible-region canvas) 2610 (send canvas call-as-primary-owner 2611 (λ () 2612 (let* ([text (send canvas get-editor)] 2613 [admin (send text get-admin)] 2614 [start (send text get-start-position)] 2615 [end (send text get-end-position)]) 2616 (let-values ([(x y w h) (get-visible-area admin)]) 2617 (let ([ysb (box 0)]) 2618 (send text position-location (send text get-start-position) #f ysb) 2619 (values x y w h 2620 (and (= start end) 2621 (<= y (unbox ysb) (+ y h)) 2622 (unbox ysb))))))))) 2623 2624 ;; set-visible-region : editor-canvas number number number number (union #f number) -> void 2625 ;; sets the visible region of the text displayed by the editor canvas 2626 ;; to be the middle of the region (vertically) specified by x, y, w, and h. 2627 ;; if start-visible? and/or end-visible? are true, some special handling 2628 ;; is done to try to keep the start and end visible, with precendence 2629 ;; given to start if both are #t. 2630 (define/private (set-visible-region canvas x y w h cursor-y) 2631 (send canvas call-as-primary-owner 2632 (λ () 2633 (let* ([text (send canvas get-editor)] 2634 [admin (send text get-admin)] 2635 [nwb (box 0)] 2636 [nhb (box 0)]) 2637 (send admin get-view #f #f nwb nhb) 2638 (let* ([nw (unbox nwb)] 2639 [nh (unbox nhb)] 2640 2641 [nx x] 2642 [raw-y (- (+ y (/ h 2)) (/ nh 2))] 2643 [ny (if (and cursor-y 2644 (not (<= raw-y cursor-y (+ raw-y nh)))) 2645 (- cursor-y (/ nh 2)) 2646 raw-y)]) 2647 (send canvas scroll-to nx ny nw nh #t) 2648 (void)))))) 2649 2650 ;; get-visible-area : admin -> number number number number 2651 ;; returns the visible area for this admin 2652 (define/private (get-visible-area admin) 2653 (let ([bx (box 0)] 2654 [by (box 0)] 2655 [bw (box 0)] 2656 [bh (box 0)]) 2657 (send admin get-view bx by bw bh) 2658 (values (unbox bx) 2659 (unbox by) 2660 (unbox bw) 2661 (unbox bh)))) 2662 2663 (define/public (collapse) 2664 (let* ([target (get-edit-target-window)]) 2665 (cond 2666 [(memq target definitions-canvases) 2667 (collapse-definitions target)] 2668 [(memq target interactions-canvases) 2669 (collapse-interactions target)] 2670 [else (bell)]))) 2671 2672 (define/private (collapse-definitions target) 2673 (handle-collapse 2674 target 2675 (λ () definitions-canvases) 2676 (λ (c) (set! definitions-canvases c)))) 2677 2678 (define/private (collapse-interactions target) 2679 (handle-collapse 2680 target 2681 (λ () interactions-canvases) 2682 (λ (c) (set! interactions-canvases c)))) 2683 2684 (define/private (handle-collapse target get-canvases set-canvases!) 2685 (cond 2686 [(= 1 (length (get-canvases))) (bell)] 2687 [else 2688 (define old-percentages (send resizable-panel get-percentages)) 2689 (define soon-to-be-bigger-canvas #f) 2690 (define percentages 2691 (cond 2692 [(and target (eq? (car (get-canvases)) target)) 2693 (set! soon-to-be-bigger-canvas (cadr (get-canvases))) 2694 (cons (+ (car old-percentages) 2695 (cadr old-percentages)) 2696 (cddr old-percentages))] 2697 [else 2698 (let loop ([canvases (cdr (get-canvases))] 2699 [prev-canvas (car (get-canvases))] 2700 [percentages (cdr old-percentages)] 2701 [prev-percentage (car old-percentages)]) 2702 (cond 2703 [(null? canvases) 2704 (error 'collapse "internal error.1")] 2705 [(null? percentages) 2706 (error 'collapse "internal error.2")] 2707 [else 2708 (cond 2709 [(and target (eq? (car canvases) target)) 2710 (set! soon-to-be-bigger-canvas prev-canvas) 2711 (cons (+ (car percentages) 2712 prev-percentage) 2713 (cdr percentages))] 2714 [else 2715 (cons prev-percentage 2716 (loop (cdr canvases) 2717 (car canvases) 2718 (cdr percentages) 2719 (car percentages)))])]))])) 2720 (unless soon-to-be-bigger-canvas 2721 (error 'collapse "internal error.3")) 2722 (set-canvases! (remq target (get-canvases))) 2723 (update-shown) 2724 2725 (define target-admin 2726 (send target call-as-primary-owner 2727 (λ () 2728 (send (send target get-editor) get-admin)))) 2729 (define to-be-bigger-admin 2730 (send soon-to-be-bigger-canvas call-as-primary-owner 2731 (λ () 2732 (send (send soon-to-be-bigger-canvas get-editor) get-admin)))) 2733 (define-values (bx by bw bh) (get-visible-area to-be-bigger-admin)) 2734 2735 ;; this line makes the soon-to-be-bigger-canvas bigger 2736 ;; if it fails, we're out of luck, but at least we don't crash. 2737 (with-handlers ([exn:fail? (λ (x) (void))]) 2738 (send resizable-panel set-percentages percentages)) 2739 2740 (send soon-to-be-bigger-canvas scroll-to bx by bw bh #t) 2741 (send target set-editor #f) 2742 (send soon-to-be-bigger-canvas focus)])) 2743 ; 2744 ; 2745 ; 2746 ; ; 2747 ; ; 2748 ; ; 2749 ; ;;; ; ;; ;;; ; ; ; ; ;; ;; ;;; ; ;; ; ; 2750 ; ; ;; ; ; ; ; ; ; ;; ;; ; ; ; ;; ; ; ; 2751 ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 2752 ; ;; ; ; ; ; ; ; ; ; ; ; ; ;;;;;; ; ; ; ; 2753 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 2754 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; 2755 ; ;;; ; ; ;;; ; ; ; ; ; ;;;; ; ; ;; ; 2756 ; 2757 ; 2758 ; 2759 2760 2761 (define interactions-shown? #t) 2762 (define definitions-shown? #t) 2763 2764 (define/private (toggle-show/hide-definitions) 2765 (set! definitions-shown? (not definitions-shown?)) 2766 (unless definitions-shown? 2767 (set! interactions-shown? #t))) 2768 (define/private (toggle-show/hide-interactions) 2769 (set! interactions-shown? (not interactions-shown?)) 2770 (unless interactions-shown? 2771 (set! definitions-shown? #t))) 2772 2773 (define (immediate-children parent children) 2774 (define (immediate child) 2775 (let loop ([child child]) 2776 (define immediate-parent (send child get-parent)) 2777 (if (and immediate-parent 2778 (eq? immediate-parent parent)) 2779 child 2780 (loop immediate-parent)))) 2781 (for/list ([child children]) 2782 (immediate child))) 2783 2784 (define/override (update-shown) 2785 (super update-shown) 2786 (let ([new-children 2787 (foldl 2788 (λ (shown? children sofar) 2789 (if shown? 2790 (append children sofar) 2791 sofar)) 2792 null 2793 (list interactions-shown? 2794 definitions-shown?) 2795 (list interactions-canvases 2796 definitions-canvases))] 2797 [old-children (send resizable-panel get-children)] 2798 [p (preferences:get 'drracket:unit-window-size-percentage)]) 2799 (update-defs/ints-resize-corner) 2800 (send definitions-item set-label 2801 (if definitions-shown? 2802 (string-constant hide-definitions-menu-item-label) 2803 (string-constant show-definitions-menu-item-label))) 2804 (send interactions-item set-label 2805 (if interactions-shown? 2806 (string-constant hide-interactions-menu-item-label) 2807 (string-constant show-interactions-menu-item-label))) 2808 (send resizable-panel begin-container-sequence) 2809 2810 ;; this might change the unit-window-size-percentage, so save/restore it 2811 (send resizable-panel change-children 2812 (λ (old) 2813 (immediate-children resizable-panel new-children))) 2814 2815 (preferences:set 'drracket:unit-window-size-percentage p) 2816 ;; restore preferred interactions/definitions sizes 2817 (when (and (= 1 (length definitions-canvases)) 2818 (= 1 (length interactions-canvases)) 2819 (= 2 (length new-children))) 2820 (with-handlers ([exn:fail? (λ (x) (void))]) 2821 (send resizable-panel set-percentages 2822 (list p (- 1 p))))) 2823 2824 (send resizable-panel end-container-sequence) 2825 (when (ormap (λ (child) 2826 (and (is-a? child editor-canvas%) 2827 (not (send child has-focus?)))) 2828 (send resizable-panel get-children)) 2829 (let ([new-focus 2830 (let loop ([children (send resizable-panel get-children)]) 2831 (cond 2832 [(null? children) (void)] 2833 [else (let ([child (car children)]) 2834 (if (is-a? child editor-canvas%) 2835 child 2836 (loop (cdr children))))]))] 2837 [old-focus 2838 (ormap (λ (x) (and (is-a? x editor-canvas%) (send x has-focus?) x)) 2839 old-children)]) 2840 2841 ;; conservatively, only scroll when the focus stays in the same place. 2842 (when old-focus 2843 (when (eq? old-focus new-focus) 2844 (let ([ed (send old-focus get-editor)]) 2845 (when ed 2846 (send ed scroll-to-position 2847 (send ed get-start-position) 2848 #f 2849 (send ed get-end-position)))))) 2850 2851 (send new-focus focus))) 2852 2853 (for-each 2854 (λ (get-item) 2855 (let ([item (get-item)]) 2856 (when item 2857 (send item enable definitions-shown?)))) 2858 (list (λ () (file-menu:get-revert-item)) 2859 (λ () (file-menu:get-save-item)) 2860 (λ () (file-menu:get-save-as-item)) 2861 ;(λ () (file-menu:save-as-text-item)) ; Save As Text... 2862 (λ () (file-menu:get-print-item)))) 2863 (send file-menu:print-interactions-item enable interactions-shown?))) 2864 2865 (define/augment (can-close?) 2866 (and (andmap (lambda (tab) 2867 (or (eq? tab current-tab) 2868 (and (send (send tab get-defs) can-close?) 2869 (send (send tab get-ints) can-close?)))) 2870 tabs) 2871 (send interactions-text can-close?) 2872 (inner #t can-close?))) 2873 (define/augment (on-close) 2874 (inner (void) on-close) 2875 (for-each (lambda (tab) 2876 (unless (eq? tab current-tab) 2877 (send (send tab get-defs) on-close) 2878 (send (send tab get-ints) on-close))) 2879 tabs) 2880 (when (eq? this newest-frame) 2881 (set! newest-frame #f)) 2882 (when transcript 2883 (stop-transcript)) 2884 (remove-show-status-line-callback) 2885 (remove-bug-icon-callback) 2886 (send interactions-text on-close)) 2887 2888 ;; execute-callback : -> void 2889 ;; uses the state of the button to determine if an execution is 2890 ;; already running. This function is called from many places, not 2891 ;; just the execute button. 2892 (define/public (execute-callback) 2893 (when (send execute-button is-enabled?) 2894 (when (check-if-unsaved-tabs-and-maybe-save) 2895 2896 ;; if the language is not-a-language, and the buffer looks like a module, 2897 ;; automatically make the switch to the module language 2898 (let ([next-settings (send definitions-text get-next-settings)]) 2899 (when (is-a? (drracket:language-configuration:language-settings-language next-settings) 2900 drracket:language-configuration:not-a-language-language<%>) 2901 (when (looks-like-module? definitions-text) 2902 (define-values (module-language module-language-settings) 2903 (get-module-language/settings)) 2904 (when (and module-language module-language-settings) 2905 (send definitions-text set-next-settings 2906 (drracket:language-configuration:language-settings 2907 module-language 2908 module-language-settings)))))) 2909 2910 (check-if-save-file-up-to-date) 2911 (when (preferences:get 'drracket:show-interactions-on-execute) 2912 (ensure-rep-shown interactions-text)) 2913 (when transcript 2914 (record-definitions) 2915 (record-interactions)) 2916 (send definitions-text just-executed) 2917 (send language-message set-yellow #f) 2918 (send interactions-canvas focus) 2919 (send interactions-text reset-console) 2920 (send interactions-text clear-undos) 2921 2922 (define name (send definitions-text get-port-name)) 2923 (define defs-copy (new text%)) 2924 ;; speeds up the copy 2925 (send defs-copy set-style-list (send definitions-text get-style-list)) 2926 (send definitions-text copy-self-to defs-copy) 2927 (define text-port (open-input-text-editor defs-copy 0 'end values name #t)) 2928 (port-count-lines! text-port) 2929 (send interactions-text evaluate-from-port 2930 text-port 2931 #t 2932 (λ () 2933 (parameterize ([current-eventspace drracket:init:system-eventspace]) 2934 (queue-callback 2935 (λ () 2936 (send interactions-text clear-undos))))))))) 2937 2938 (inherit revert save) 2939 (define/private (check-if-save-file-up-to-date) 2940 (when (send definitions-text save-file-out-of-date?) 2941 (let ([user-choice 2942 (message-box/custom 2943 (string-constant drscheme) 2944 (string-constant definitions-modified) 2945 (string-constant ignore) 2946 (string-constant revert) 2947 #f 2948 this 2949 '(caution default=2 number-order) 2950 1 2951 #:dialog-mixin frame:focus-table-mixin)]) 2952 (case user-choice 2953 [(1) (void)] 2954 [(2) (revert)])))) 2955 2956 ;; returns #f if we should abort `Run`, #t if it is okay to `Run` 2957 (define/private (check-if-unsaved-tabs-and-maybe-save) 2958 (cond 2959 [(preferences:get 'drracket:dont-ask-about-saving-files-on-tab-switch?) #t] 2960 [else 2961 (define save-candidates (get-unsaved-candidate-tabs #t)) 2962 (cond 2963 [(null? save-candidates) #t] 2964 [else 2965 (define-values (cancel-run? do-save?) 2966 (does-user-want-to-save-all-unsaved-files? save-candidates)) 2967 (cond 2968 [cancel-run? #f] 2969 [do-save? 2970 (define continue? 2971 (let/ec k 2972 (for ([tab (in-list save-candidates)]) 2973 (unless (send (send tab get-defs) save-file/gui-error) 2974 (k #f))) 2975 #t)) 2976 (update-tabs-labels) 2977 continue?] 2978 [else #t])])])) 2979 2980 (define/private (save-all-unsaved-files) 2981 (let/ec k 2982 (for ([tab (in-list (get-unsaved-candidate-tabs #f))]) 2983 (parameterize ([editor:silent-cancel-on-save-file-out-of-date? #t]) 2984 (unless (send (send tab get-defs) save-file #f 'same #f) 2985 (k (void)))))) 2986 (update-tabs-labels)) 2987 2988 (define/private (get-unsaved-candidate-tabs skip-me?) 2989 (define focused-frame (or (get-top-level-focus-window) 2990 (let ([ft (frame:lookup-focus-table (get-eventspace))]) 2991 (and (pair? ft) (car ft))))) 2992 (for*/list ([frame (in-list (send (group:get-the-frame-group) get-frames))] 2993 #:when (is-a? frame drracket:unit:frame<%>) 2994 [tab (in-list (send frame get-tabs))] 2995 #:unless (and skip-me? 2996 (eq? focused-frame frame) 2997 (eq? current-tab tab)) 2998 #:when (let ([defs (send tab get-defs)]) 2999 (and (send defs is-modified?) 3000 (send defs get-filename)))) 3001 tab)) 3002 3003 (define/private (does-user-want-to-save-all-unsaved-files? save-candidates) 3004 (define-values (message-box-result checked?) 3005 (message+check-box/custom 3006 (string-constant drracket) 3007 (if (= (length save-candidates) 1) 3008 (format (string-constant one-file-not-saved-do-the-save?) 3009 (get-tab-filename (car save-candidates))) 3010 (apply 3011 string-append 3012 (string-constant many-files-not-saved-do-the-save?) 3013 (for/list ([tab (in-list save-candidates)]) 3014 (~a "\n" (get-tab-filename tab))))) 3015 (string-constant save-after-switching-tabs) 3016 (string-constant save-all-files) 3017 (string-constant dont-save) 3018 #f 3019 this ; parent 3020 (append 3021 (if (preferences:get 'drracket:save-files-on-tab-switch?) 3022 '(checked) 3023 '()) 3024 '(default=1)))) 3025 (preferences:set 'drracket:save-files-on-tab-switch? checked?) 3026 (case message-box-result 3027 [(1) (values #f #t)] ;; clicked save-all -> save (and run) 3028 [(2) (values #f #f)] ;; clicked dont-save -> don't save, but still run 3029 [(#f) (values #t #f)])) ;; closed the dialog (with esc) -> cancel 3030 3031 (inherit get-menu-bar get-focus-object get-edit-target-object) 3032 3033 (define/override (get-editor) definitions-text) 3034 (define/override (get-canvas) 3035 (initialize-definitions-canvas) 3036 definitions-canvas) 3037 3038 (define (create-definitions-canvas) 3039 (new (drracket:get/extend:get-definitions-canvas) 3040 [parent resizable-panel] 3041 [editor definitions-text])) 3042 3043 (define/private (initialize-definitions-canvas) 3044 (unless definitions-canvas 3045 (set! definitions-canvas (create-definitions-canvas)))) 3046 3047 ;; wire the definitions text to the interactions text and initialize it. 3048 (define/private (init-definitions-text tab) 3049 (let ([defs (send tab get-defs)] 3050 [ints (send tab get-ints)]) 3051 (send defs set-interactions-text ints) 3052 (send defs set-tab tab) 3053 (send ints set-definitions-text defs) 3054 (send defs change-mode-to-match) 3055 (send defs insert-auto-text))) 3056 3057 3058 ; 3059 ; 3060 ; @@ 3061 ; @ @ 3062 ; @@@@@ $@$: @-@$ :@@+@ 3063 ; @ -@ @+ *$ @$ -@ 3064 ; @ -$@$@ @ @ :@@$- 3065 ; @ $* @ @ @ *@ 3066 ; @: :$ @- *@ @ +$ @ :@ 3067 ; :@@$- -$$-@@@@+@$ $+@@: 3068 ; 3069 ; 3070 ; 3071 ; 3072 3073 (define/public (get-current-tab) current-tab) 3074 3075 ;; create-new-tab : -> void 3076 ;; creates a new tab and updates the GUI for that new tab 3077 (define/public create-new-tab 3078 (lambda ([filename #f]) 3079 (let* ([defs (new (drracket:get/extend:get-definitions-text))] 3080 [tab-count (length tabs)] 3081 [new-tab (new (drracket:get/extend:get-tab) 3082 (defs defs) 3083 (i tab-count) 3084 (frame this) 3085 (defs-shown? #t) 3086 (ints-shown? (not filename)))] 3087 [ints (make-object (drracket:get/extend:get-interactions-text) new-tab)]) 3088 (send new-tab set-ints ints) 3089 (set! tabs (append tabs (list new-tab))) 3090 (send tabs-panel append 3091 (gui-utils:trim-string 3092 (if filename 3093 (get-tab-label-from-filename filename) 3094 (get-defs-tab-label defs #f)) 3095 200)) 3096 (init-definitions-text new-tab) 3097 (when filename (send defs load-file filename)) 3098 (send defs enable-top-level-window-connection) 3099 (change-to-nth-tab (- (send tabs-panel get-number) 1)) 3100 (send ints initialize-console) 3101 (send tabs-panel set-selection (- (send tabs-panel get-number) 1)) 3102 (set! newest-frame this) 3103 (update-menu-bindings)))) 3104 3105 ;; change-to-tab : tab -> void 3106 ;; updates current-tab, definitions-text, and interactactions-text 3107 ;; to be the nth tab. Also updates the GUI to show the new tab 3108 (inherit begin-container-sequence end-container-sequence) 3109 (define/public (change-to-tab tab) 3110 (unless (eq? current-tab tab) 3111 (let ([old-tab current-tab]) 3112 (save-visible-tab-regions) 3113 (set! current-tab tab) 3114 (set! definitions-text (send current-tab get-defs)) 3115 (set! interactions-text (send current-tab get-ints)) 3116 3117 (begin-container-sequence) 3118 (send definitions-text begin-edit-sequence #t #f) 3119 (send interactions-text begin-edit-sequence #t #f) 3120 (for-each (λ (defs-canvas) (send defs-canvas set-editor definitions-text #f)) 3121 definitions-canvases) 3122 (for-each (λ (ints-canvas) (send ints-canvas set-editor interactions-text #f)) 3123 interactions-canvases) 3124 3125 (update-save-message) 3126 (update-save-button) 3127 (language-changed) 3128 3129 (send definitions-text update-frame-filename) 3130 (update-running (send current-tab is-running?)) 3131 (when (let ([tlw (get-top-level-focus-window)]) 3132 (and tlw (eq? this tlw))) 3133 (send current-tab touched)) 3134 (on-tab-change old-tab current-tab) 3135 (send tab update-log) 3136 (send tab update-planet-status) 3137 (send tab update-execute-warning-gui) 3138 3139 (send old-tab set-panel-percentages-and-orientation 3140 (send resizable-panel get-percentages) 3141 (not (send resizable-panel get-vertical?))) 3142 (restore-visible-tab-regions) 3143 (define-values (panel-percentages panel-orientation) 3144 (send tab get-panel-percentages-and-orientation)) 3145 (when panel-percentages 3146 (send resizable-panel set-percentages panel-percentages) 3147 (send resizable-panel set-orientation panel-orientation)) 3148 3149 (for-each (λ (defs-canvas) (send defs-canvas refresh)) 3150 definitions-canvases) 3151 (for-each (λ (ints-canvas) (send ints-canvas refresh)) 3152 interactions-canvases) 3153 (set-color-status! (send definitions-text is-lexer-valid?)) 3154 3155 (when (preferences:get 'drracket:save-files-on-tab-switch?) 3156 (save-all-unsaved-files)) 3157 (send definitions-text end-edit-sequence) 3158 (send interactions-text end-edit-sequence) 3159 (end-container-sequence) 3160 3161 (case (send current-tab get-focus-d/i) 3162 [(defs) 3163 (send (car definitions-canvases) focus) 3164 (set-text-to-search (send (car definitions-canvases) get-editor))] 3165 [(ints) 3166 (send (car interactions-canvases) focus) 3167 (set-text-to-search (send (car interactions-canvases) get-editor))])))) 3168 3169 (define/pubment (on-tab-change from-tab to-tab) 3170 (let ([old-enabled (send from-tab get-enabled)] 3171 [new-enabled (send to-tab get-enabled)]) 3172 (unless (eq? old-enabled new-enabled) 3173 (if new-enabled 3174 (enable-evaluation) 3175 (disable-evaluation)))) 3176 3177 (inner (void) on-tab-change from-tab to-tab)) 3178 3179 (define/public (next-tab) (change-to-delta-tab +1)) 3180 (define/public (prev-tab) (change-to-delta-tab -1)) 3181 3182 (define/private (change-to-delta-tab dt) 3183 (change-to-nth-tab (modulo (+ (send current-tab get-i) dt) (length tabs)))) 3184 3185 ;; Re-orders the tabs according to the specified order 3186 (define/public (reorder-tabs tab-order) 3187 (unless (and 3188 ((listof exact-nonnegative-integer?) tab-order) 3189 (equal? (sort tab-order <) 3190 (range (length tabs)))) 3191 (raise-argument-error 'reorder-tabs 3192 "list of unique integers from 0 to n where n is the current number of tabs" 3193 tab-order)) 3194 (begin-container-sequence) 3195 (define-values (new-tabs-rev new-labels-rev) 3196 (for/fold ([new-tabs '()] 3197 [new-labels '()]) 3198 ([new-i (in-naturals)] 3199 [old-i tab-order]) 3200 (define t (list-ref tabs old-i)) 3201 (send t set-i new-i) 3202 (values (cons t new-tabs) 3203 (cons (send tabs-panel get-item-label old-i) 3204 new-labels)))) 3205 (set! tabs (reverse new-tabs-rev)) 3206 (send tabs-panel set (reverse new-labels-rev)) 3207 (send tabs-panel set-selection (send current-tab get-i)) 3208 (end-container-sequence) 3209 (update-menu-bindings) 3210 (update-tabs-labels)) 3211 3212 ;; Swaps the current tab with its right-hand neighbor 3213 (define/public (move-current-tab-right) 3214 (define i (send current-tab get-i)) 3215 (unless (= i (- (length tabs) 1)) 3216 (reorder-tabs 3217 (append (range i) 3218 (list (+ i 1) i) 3219 (range (+ i 2) (length tabs)))))) 3220 3221 ;; Swaps the current tab with its left-hand neighbor 3222 (define/public (move-current-tab-left) 3223 (define i (send current-tab get-i)) 3224 (unless (= i 0) 3225 (reorder-tabs 3226 (append (range (- i 1)) 3227 (list i (- i 1)) 3228 (range (+ i 1) (length tabs)))))) 3229 3230 (define/public-final (close-current-tab) 3231 (close-given-tab current-tab)) 3232 3233 (define/public-final (close-ith-tab i) 3234 (when (< i (length tabs)) 3235 (close-given-tab (list-ref tabs i)))) 3236 3237 (define/public-final (close-given-tab tab-to-close) 3238 (define subsequent-tabs 3239 (let loop ([l-tabs tabs]) 3240 (cond 3241 [(null? l-tabs) #f] 3242 [(eq? (car l-tabs) tab-to-close) (cdr l-tabs)] 3243 [else (loop (cdr l-tabs))]))) 3244 ;; make sure we have at least 2 tabs and the tab we're closing exists 3245 (when (and subsequent-tabs (pair? (cdr tabs))) 3246 (when (close-tab tab-to-close) 3247 (for ([tab (in-list subsequent-tabs)]) 3248 (send tab set-i (- (send tab get-i) 1))) 3249 (set! tabs (remq tab-to-close tabs)) 3250 (send tabs-panel delete (send tab-to-close get-i)) 3251 (update-menu-bindings) 3252 (cond 3253 [(eq? tab-to-close current-tab) 3254 (change-to-tab 3255 (argmax (λ (tab) (send tab get-last-touched)) 3256 tabs))] 3257 [else 3258 (update-tabs-labels)])))) 3259 3260 ;; a helper private method for close-current-tab -- doesn't close an arbitrary tab. 3261 (define/private (close-tab tab) 3262 (cond 3263 [(send tab can-close?) 3264 (send tab on-close) 3265 #t] 3266 [else #f])) 3267 3268 (define/public (open-in-new-tab filename) 3269 (create-new-tab filename)) 3270 3271 (define/public (get-tab-count) (length tabs)) 3272 (define/public (change-to-nth-tab n) 3273 (unless (< n (length tabs)) 3274 (error 'change-to-nth-tab "number too big ~s" n)) 3275 (change-to-tab (list-ref tabs n))) 3276 3277 (define/private (save-visible-tab-regions) 3278 (send current-tab set-visible-ints 3279 (get-tab-visible-regions interactions-text) 3280 interactions-shown?) 3281 (send current-tab set-visible-defs 3282 (get-tab-visible-regions definitions-text) 3283 definitions-shown?) 3284 (send current-tab set-focus-d/i 3285 (if (ormap (λ (x) (send x has-focus?)) interactions-canvases) 3286 'ints 3287 'defs))) 3288 3289 (define/private (get-tab-visible-regions txt) 3290 (map (λ (canvas) 3291 (let-values ([(x y w h _) (get-visible-region canvas)]) 3292 (list x y w h))) 3293 (send txt get-canvases))) 3294 3295 (inherit set-text-to-search reflow-container) 3296 (define/private (restore-visible-tab-regions) 3297 (define (fix-up-canvas-numbers txt regions ints?) 3298 (when regions 3299 (let* ([canvases (send txt get-canvases)] 3300 [canvases-count (length canvases)] 3301 [regions-count (length regions)]) 3302 (cond 3303 [(> canvases-count regions-count) 3304 (let loop ([i (- canvases-count regions-count)] 3305 [canvases canvases]) 3306 (unless (zero? i) 3307 (if ints? 3308 (collapse-interactions (car canvases)) 3309 (collapse-definitions (car canvases))) 3310 (loop (- i 1) 3311 (cdr canvases))))] 3312 [(= canvases-count regions-count) 3313 (void)] 3314 [(< canvases-count regions-count) 3315 (let loop ([i (- regions-count canvases-count)] 3316 [canvases canvases]) 3317 (unless (zero? i) 3318 (if ints? 3319 (split-interactions (car canvases)) 3320 (split-definitions (car canvases))) 3321 (loop (- i 1) 3322 (cdr canvases))))])))) 3323 3324 (define (set-visible-regions txt regions) 3325 (when regions 3326 (for-each (λ (canvas region) 3327 (set-visible-region canvas 3328 (first region) 3329 (second region) 3330 (third region) 3331 (fourth region) 3332 #f)) 3333 (send txt get-canvases) 3334 regions))) 3335 3336 (let-values ([(vi is?) (send current-tab get-visible-ints)] 3337 [(vd ds?) (send current-tab get-visible-defs)]) 3338 (set! interactions-shown? is?) 3339 (set! definitions-shown? ds?) 3340 (update-shown) 3341 (reflow-container) ;; without this one, the percentages in the 3342 ;; resizable-panel are not up to date with the children 3343 (when ds? (fix-up-canvas-numbers definitions-text vd #f)) 3344 (when is? (fix-up-canvas-numbers interactions-text vi #t)) 3345 (reflow-container) 3346 (when ds? (set-visible-regions definitions-text vd)) 3347 (when is? (set-visible-regions interactions-text vi)))) 3348 3349 (define/private (pathname-equal? p1 p2) 3350 (with-handlers ([exn:fail? (λ (x) #f)]) 3351 (string=? (path->string (normal-case-path (normalize-path p1))) 3352 (path->string (normal-case-path (normalize-path p2)))))) 3353 3354 (define/override (make-visible filename) 3355 (let ([tab (find-matching-tab filename)]) 3356 (when tab 3357 (change-to-tab tab)))) 3358 3359 (define/public (find-matching-tab filename) 3360 (define fn-path (if (string? filename) 3361 (string->path filename) 3362 filename)) 3363 (for/or ([tab (in-list tabs)]) 3364 (define tab-filename (send (send tab get-defs) get-filename)) 3365 (and tab-filename 3366 (pathname-equal? fn-path tab-filename) 3367 tab))) 3368 3369 (define/override (editing-this-file? filename) 3370 (ormap (λ (tab) 3371 (let ([fn (send (send tab get-defs) get-filename)]) 3372 (and fn 3373 (pathname-equal? fn filename)))) 3374 tabs)) 3375 3376 (define/override (get-menu-item%) 3377 (class (super get-menu-item%) 3378 (inherit get-label get-plain-label) 3379 (define/override (restore-keybinding) 3380 (cond 3381 [(equal? (get-plain-label) (string-constant close)) 3382 (update-close-menu-item-shortcut this)] 3383 [(equal? (get-plain-label) (string-constant close-tab)) 3384 (update-close-tab-menu-item-shortcut this)] 3385 [else (super restore-keybinding)])) 3386 (super-new))) 3387 3388 (define/override (on-activate active?) 3389 (when (preferences:get 'drracket:save-files-on-tab-switch?) 3390 (save-all-unsaved-files)) 3391 (when active? 3392 (send (get-current-tab) touched)) 3393 (super on-activate active?)) 3394 3395 (define/private (update-menu-bindings) 3396 (when close-tab-menu-item 3397 (update-close-tab-menu-item-shortcut close-tab-menu-item)) 3398 (update-close-menu-item-shortcut (file-menu:get-close-item))) 3399 3400 (define/private (update-close-tab-menu-item-shortcut item) 3401 (define just-one? (and (pair? tabs) (null? (cdr tabs)))) 3402 (send item set-label (if just-one? 3403 (string-constant close-tab) 3404 (string-constant close-tab-amp))) 3405 (when (preferences:get 'framework:menu-bindings) 3406 (send item set-shortcut (if just-one? #f #\w)))) 3407 3408 (define/private (update-close-menu-item-shortcut item) 3409 (cond 3410 [(equal? (system-type) 'unix) 3411 (send item set-label (string-constant close-menu-item))] 3412 [else 3413 (define just-one? (and (pair? tabs) (null? (cdr tabs)))) 3414 (send item set-label (if just-one? 3415 (string-constant close-window-menu-item) 3416 (string-constant close-window))) 3417 (when (preferences:get 'framework:menu-bindings) 3418 (send item set-shortcut-prefix (if just-one? 3419 (get-default-shortcut-prefix) 3420 (cons 'shift (get-default-shortcut-prefix)))))])) 3421 3422 (define/override (file-menu:close-callback item control) 3423 (define just-one? (and (pair? tabs) (null? (cdr tabs)))) 3424 (if (and (equal? (system-type) 'unix) 3425 (not just-one?)) 3426 (close-current-tab) 3427 (super file-menu:close-callback item control))) 3428 3429 ;; offer-to-save-file : path -> void 3430 ;; bring the tab that edits the file named by `path' to the front 3431 ;; and opens a dialog asking if it should be saved. 3432 (define/public (offer-to-save-file path) 3433 (let ([original-tab current-tab] 3434 [tab-to-save (find-matching-tab path)]) 3435 (when tab-to-save 3436 (let ([defs-to-save (send tab-to-save get-defs)]) 3437 (when (send defs-to-save is-modified?) 3438 (unless (eq? tab-to-save original-tab) 3439 (change-to-tab tab-to-save)) 3440 (send defs-to-save user-saves-or-not-modified? #f) 3441 (unless (eq? tab-to-save original-tab) 3442 (change-to-tab original-tab))))))) 3443 3444 3445 ;; 3446 ;; end tabs 3447 ;; 3448 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3449 3450 (define/public (get-definitions-text) definitions-text) 3451 (define/public (get-interactions-text) interactions-text) 3452 3453 (define/public (get-definitions/interactions-panel-parent) 3454 toolbar/rest-panel) 3455 3456 (inherit set-show-menu-sort-key) 3457 (define/override (add-show-menu-items show-menu) 3458 (super add-show-menu-items show-menu) 3459 (set! definitions-item 3460 (make-object menu:can-restore-menu-item% 3461 (string-constant hide-definitions-menu-item-label) 3462 (get-show-menu) 3463 (λ (_1 _2) 3464 (toggle-show/hide-definitions) 3465 (update-shown)) 3466 #\d 3467 (string-constant definitions-menu-item-help-string))) 3468 (set-show-menu-sort-key definitions-item 101) 3469 (set! interactions-item 3470 (make-object menu:can-restore-menu-item% 3471 (string-constant show-interactions-menu-item-label) 3472 (get-show-menu) 3473 (λ (_1 _2) 3474 (toggle-show/hide-interactions) 3475 (update-shown)) 3476 #\e 3477 (string-constant interactions-menu-item-help-string))) 3478 (set-show-menu-sort-key interactions-item 102) 3479 3480 (let ([layout-item 3481 (new menu:can-restore-menu-item% 3482 [label (string-constant use-horizontal-layout)] 3483 [parent (get-show-menu)] 3484 [callback (λ (x y) 3485 (define vertical? (send resizable-panel get-vertical?)) 3486 (preferences:set 'drracket:defs/ints-horizontal vertical?) 3487 (send resizable-panel set-orientation vertical?) 3488 (define update-shown? (or (not interactions-shown?) 3489 (not definitions-shown?))) 3490 (unless interactions-shown? 3491 (toggle-show/hide-interactions)) 3492 (unless definitions-shown? 3493 (toggle-show/hide-definitions)) 3494 (when update-shown? 3495 (update-shown)))] 3496 [demand-callback 3497 (λ (mi) (send mi set-label (if (send resizable-panel get-vertical?) 3498 (string-constant use-horizontal-layout) 3499 (string-constant use-vertical-layout))))] 3500 [shortcut (if (member 'shift (get-default-shortcut-prefix)) 3501 #f 3502 #\l)] 3503 [shortcut-prefix (if (member 'shift (get-default-shortcut-prefix)) 3504 (get-default-shortcut-prefix) 3505 (cons 'shift (get-default-shortcut-prefix)))])]) 3506 (set-show-menu-sort-key layout-item 103)) 3507 3508 (let () 3509 (define (overview-shown?) 3510 (send (send (get-current-tab) get-defs) get-inline-overview-enabled?)) 3511 (define overview-menu-item 3512 (new menu:can-restore-menu-item% 3513 (shortcut #\u) 3514 (label 3515 (if (overview-shown?) 3516 (string-constant hide-overview) 3517 (string-constant show-overview))) 3518 (parent (get-show-menu)) 3519 [demand-callback 3520 (λ (mi) 3521 (send mi set-label 3522 (if (overview-shown?) 3523 (string-constant hide-overview) 3524 (string-constant show-overview))))] 3525 (callback 3526 (λ (menu evt) 3527 (cond 3528 [(overview-shown?) 3529 (preferences:set 'drracket:inline-overview-shown? #f) 3530 (send (send (get-current-tab) get-defs) set-inline-overview-enabled? #f)] 3531 [else 3532 (preferences:set 'drracket:inline-overview-shown? #t) 3533 (send (send (get-current-tab) get-defs) set-inline-overview-enabled? #t)]))))) 3534 (set-show-menu-sort-key overview-menu-item 301)) 3535 3536 (set! module-browser-menu-item 3537 (new menu:can-restore-menu-item% 3538 (label (if module-browser-shown? 3539 (string-constant hide-module-browser) 3540 (string-constant show-module-browser))) 3541 (parent (get-show-menu)) 3542 (callback 3543 (λ (menu evt) 3544 (if module-browser-shown? 3545 (hide-module-browser) 3546 (show-module-browser)))))) 3547 (set-show-menu-sort-key module-browser-menu-item 401) 3548 3549 (set! toolbar-menu (new menu% 3550 [parent show-menu] 3551 [label (string-constant toolbar)])) 3552 (set-show-menu-sort-key toolbar-menu 1) 3553 (set! toolbar-left-menu-item 3554 (new checkable-menu-item% 3555 [label (string-constant toolbar-on-left)] 3556 [parent toolbar-menu] 3557 [callback (λ (x y) (set-toolbar-left))] 3558 [checked #f])) 3559 (set! toolbar-top-menu-item 3560 (new checkable-menu-item% 3561 [label (string-constant toolbar-on-top)] 3562 [parent toolbar-menu] 3563 [callback (λ (x y) (set-toolbar-top))] 3564 [checked #f])) 3565 (set! toolbar-top-no-label-menu-item 3566 (new checkable-menu-item% 3567 [label (string-constant toolbar-on-top-no-label)] 3568 [parent toolbar-menu] 3569 [callback (λ (x y) (set-toolbar-top-no-label))] 3570 [checked #f])) 3571 (set! toolbar-right-menu-item 3572 (new checkable-menu-item% 3573 [label (string-constant toolbar-on-right)] 3574 [parent toolbar-menu] 3575 [callback (λ (x y) (set-toolbar-right))] 3576 [checked #f])) 3577 (set! toolbar-hidden-menu-item 3578 (new checkable-menu-item% 3579 [label (string-constant toolbar-hidden)] 3580 [parent toolbar-menu] 3581 [callback (λ (x y) (set-toolbar-hidden))] 3582 [checked #f])) 3583 3584 (set! logger-menu-item 3585 (new menu-item% 3586 [label (string-constant show-log)] 3587 [parent show-menu] 3588 [callback 3589 (λ (x y) (send current-tab toggle-log))])) 3590 (set-show-menu-sort-key logger-menu-item 205) 3591 3592 3593 (set! show-line-numbers-menu-item 3594 (new menu:can-restore-menu-item% 3595 [label (if (show-line-numbers?) 3596 (string-constant hide-line-numbers/menu) 3597 (string-constant show-line-numbers/menu))] 3598 [parent (get-show-menu)] 3599 [callback (lambda (self event) 3600 (define value (preferences:get 'drracket:show-line-numbers?)) 3601 (preferences:set 'drracket:show-line-numbers? (not value)) 3602 (show-line-numbers! (not value)))])) 3603 (set-show-menu-sort-key show-line-numbers-menu-item 302) 3604 3605 (define show-column-guide-menu-item 3606 (new menu:can-restore-menu-item% 3607 [label ""] 3608 [parent (get-show-menu)] 3609 [demand-callback (λ (itm) 3610 (define pv (preferences:get 'framework:column-guide-width)) 3611 (send itm set-label 3612 (format (if (car pv) 3613 (string-constant hide-column-width-guide) 3614 (string-constant show-column-width-guide)) 3615 (cadr pv))))] 3616 [callback (λ (self evt) 3617 (define ov (preferences:get 'framework:column-guide-width)) 3618 (preferences:set 'framework:column-guide-width 3619 (list (not (car ov)) (cadr ov))))])) 3620 (set-show-menu-sort-key show-column-guide-menu-item 303) 3621 3622 (let () 3623 (define (font-adjust adj label key shortcut) 3624 (define (adj-font _1 _2) 3625 (editor:set-current-preferred-font-size 3626 (adj 3627 (editor:get-current-preferred-font-size)))) 3628 (define (on-demand item) 3629 (define lab 3630 (format 3631 label 3632 (adj 3633 (editor:get-current-preferred-font-size)))) 3634 (send item set-label lab) 3635 (send item enable (<= 1 (adj (editor:get-current-preferred-font-size)) 255))) 3636 (define item 3637 (new menu:can-restore-menu-item% 3638 (shortcut shortcut) 3639 (label "") 3640 (parent (get-show-menu)) 3641 (callback adj-font) 3642 (demand-callback on-demand))) 3643 (set-show-menu-sort-key item key)) 3644 (font-adjust add1 (string-constant increase-font-size) -2 #\=) 3645 (font-adjust sub1 (string-constant decrease-font-size) -3 #\-)) 3646 3647 (let ([split 3648 (new menu:can-restore-menu-item% 3649 (shortcut (if (equal? (system-type) 'macosx) #f #\m)) 3650 (label (string-constant split-menu-item-label)) 3651 (parent (get-show-menu)) 3652 (callback (λ (x y) (split))) 3653 (demand-callback (λ (item) (split-demand item))))] 3654 [collapse 3655 (new menu:can-restore-menu-item% 3656 (shortcut (if (or (equal? (system-type) 'macosx) 3657 (member 'shift (get-default-shortcut-prefix))) 3658 #f 3659 #\m)) 3660 (shortcut-prefix (cond 3661 [(or (equal? (system-type) 'macosx) 3662 (member 'shift (get-default-shortcut-prefix))) 3663 (get-default-shortcut-prefix)] 3664 [else 3665 (cons 'shift (get-default-shortcut-prefix))])) 3666 (label (string-constant collapse-menu-item-label)) 3667 (parent (get-show-menu)) 3668 (callback (λ (x y) (collapse))) 3669 (demand-callback (λ (item) (collapse-demand item))))]) 3670 (set-show-menu-sort-key split 2) 3671 (set-show-menu-sort-key collapse 3))) 3672 3673 3674; 3675; 3676; 3677; 3678; ;;; ;;; 3679; ;;; ;;; 3680; ;;; ;; ;;; ;;; ;; ;;; ;;; ;;; ;;; ;;;; 3681; ;;;;;;;;;;; ;;;;; ;;;;;;; ;;; ;;; ;;; ;; ;;; 3682; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 3683; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;;;;; 3684; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 3685; ;;; ;;; ;;; ;;;;; ;;;;;;; ;;;;;;; ;;; ;;;;;; 3686; ;;; ;;; ;;; ;;; ;; ;;; ;; ;;; ;;; ;;;; 3687; 3688; 3689; 3690; 3691; 3692; 3693; 3694; 3695; ;;; 3696; ;;; 3697; ;;; ;; ;;; ;; ;;; ;;; ;;; ;;; ;;;; ;;;; ;;; ; 3698; ;;;;;;; ;;;;; ;;;;; ;;; ;;; ;;;;;; ;; ;; ;;; ;;;;; 3699; ;;; ;;; ;;; ;;; ;;; ;;;;;;;;; ;;; ;;; ;;; ;;; 3700; ;;; ;;; ;;; ;;; ;;; ;;;; ;;;; ;;;; ;;;;;;; ;;; 3701; ;;; ;;; ;;; ;;; ;;; ;;;; ;;;; ;;; ;;; ;;; 3702; ;;;;;;; ;;; ;;;;; ;; ;; ;; ;;; ;;;;;; ;;; 3703; ;;; ;; ;;; ;;; ;; ;; ;;;; ;;;; ;;; 3704; 3705; 3706; 3707; 3708 3709 (field [module-browser-shown? #f] 3710 [module-browser-parent-panel #f] 3711 [module-browser-panel #f] 3712 [module-browser-ec #f] 3713 [module-browser-button #f] 3714 [module-browser-lib-path-check-box #f] 3715 [module-browser-planet-path-check-box #f] 3716 [module-browser-name-length-choice #f] 3717 [module-browser-pb #f] 3718 [module-browser-menu-item 'module-browser-menu-item-unset]) 3719 3720 (inherit open-status-line close-status-line update-status-line) 3721 3722 (define/private (show-module-browser) 3723 (when module-browser-panel 3724 (when (can-browse-language?) 3725 (set! module-browser-shown? #t) 3726 (send module-browser-menu-item set-label (string-constant hide-module-browser)) 3727 (update-module-browser-pane)))) 3728 3729 (define/private (hide-module-browser) 3730 (when module-browser-panel 3731 (set! module-browser-shown? #f) 3732 (send module-browser-menu-item set-label (string-constant show-module-browser)) 3733 (set! module-browser-mouse-over-status-line-open? #f) 3734 (close-status-line 'plt:module-browser:mouse-over) 3735 (send module-browser-parent-panel change-children 3736 (λ (l) 3737 (remq module-browser-panel l))))) 3738 3739 (define/private (can-browse-language?) 3740 (let* ([lang/config (send (get-definitions-text) get-next-settings)] 3741 [lang (drracket:language-configuration:language-settings-language lang/config)] 3742 [strs (send lang get-language-position)] 3743 [can-browse? 3744 (or (is-a? lang drracket:module-language:module-language<%>) 3745 (ormap (λ (x) (regexp-match #rx"PLT" x)) 3746 strs))]) 3747 (unless can-browse? 3748 (message-box (string-constant drscheme) 3749 (string-constant module-browser-only-in-plt-and-module-langs) 3750 #:dialog-mixin frame:focus-table-mixin)) 3751 can-browse?)) 3752 3753 (define module-browser-mouse-over-status-line-open? #f) 3754 (define/private (update-module-browser-pane) 3755 (open-status-line 'plt:module-browser:mouse-over) 3756 (set! module-browser-mouse-over-status-line-open? #t) 3757 (send module-browser-panel begin-container-sequence) 3758 (unless module-browser-ec 3759 (set! module-browser-pb 3760 (drracket:module-overview:make-module-overview-pasteboard 3761 #t 3762 (λ (x) (mouse-currently-over x)))) 3763 (set! module-browser-ec (make-object editor-canvas% 3764 module-browser-panel 3765 module-browser-pb)) 3766 3767 (let* ([show-callback 3768 (λ (cb key) 3769 (if (send cb get-value) 3770 (send module-browser-pb show-visible-paths key) 3771 (send module-browser-pb remove-visible-paths key)) 3772 (preferences:set 'drracket:module-browser:hide-paths 3773 (send module-browser-pb get-hidden-paths)))] 3774 [mk-checkbox 3775 (λ (key label) 3776 (new check-box% 3777 (parent module-browser-panel) 3778 (label label) 3779 (value (not (memq key (preferences:get 3780 'drracket:module-browser:hide-paths)))) 3781 (callback 3782 (λ (cb _) 3783 (show-callback cb key)))))]) 3784 (set! module-browser-lib-path-check-box (mk-checkbox 'lib show-lib-paths)) 3785 (set! module-browser-planet-path-check-box (mk-checkbox 'planet show-planet-paths))) 3786 3787 (set! module-browser-name-length-choice 3788 (new choice% 3789 (parent module-browser-panel) 3790 (label (string-constant module-browser-name-length)) 3791 (choices (list (string-constant module-browser-name-short) 3792 (string-constant module-browser-name-medium) 3793 (string-constant module-browser-name-long) 3794 (string-constant module-browser-name-very-long))) 3795 (selection (preferences:get 'drracket:module-browser:name-length)) 3796 (callback 3797 (λ (x y) 3798 (let ([selection (send module-browser-name-length-choice get-selection)]) 3799 (preferences:set 'drracket:module-browser:name-length selection) 3800 (update-module-browser-name-length selection)))))) 3801 (update-module-browser-name-length 3802 (preferences:get 'drracket:module-browser:name-length)) 3803 3804 (set! module-browser-button 3805 (new button% 3806 (parent module-browser-panel) 3807 (label refresh) 3808 (callback (λ (x y) (update-module-browser-pane))) 3809 (stretchable-width #t)))) 3810 3811 (let ([p (preferences:get 'drracket:module-browser-size-percentage)]) 3812 (send module-browser-parent-panel change-children 3813 (λ (l) 3814 (cons module-browser-panel 3815 (remq module-browser-panel l)))) 3816 (with-handlers ([exn:fail? void]) 3817 (send module-browser-parent-panel set-percentages (list p (- 1 p)))) 3818 (send module-browser-parent-panel end-container-sequence) 3819 (calculate-module-browser))) 3820 3821 (define/private (update-module-browser-name-length i) 3822 (send module-browser-pb set-name-length 3823 (case i 3824 [(0) 'short] 3825 [(1) 'medium] 3826 [(2) 'long] 3827 [(3) 'very-long]))) 3828 3829 (define/private (mouse-currently-over snips) 3830 (when module-browser-mouse-over-status-line-open? 3831 (if (null? snips) 3832 (update-status-line 'plt:module-browser:mouse-over #f) 3833 (let* ([snip (car snips)] 3834 [lines (send snip get-lines)] 3835 [name (or (send snip get-filename) 3836 (send snip get-word))] 3837 [str (if lines 3838 (format (string-constant module-browser-filename-format) name lines) 3839 name)]) 3840 (update-status-line 'plt:module-browser:mouse-over str))))) 3841 3842 (define/private (calculate-module-browser) 3843 (let ([mod-tab current-tab]) 3844 (let-values ([(old-break-thread old-custodian) (send mod-tab get-breakables)]) 3845 (open-status-line 'plt:module-browser) 3846 (update-status-line 'plt:module-browser status-compiling-definitions) 3847 (send module-browser-button enable #f) 3848 (send module-browser-lib-path-check-box enable #f) 3849 (send module-browser-planet-path-check-box enable #f) 3850 (send module-browser-name-length-choice enable #f) 3851 (disable-evaluation-in-tab current-tab) 3852 (drracket:module-overview:fill-pasteboard 3853 module-browser-pb 3854 (drracket:language:make-text/pos 3855 definitions-text 3856 0 3857 (send definitions-text last-position)) 3858 (λ (str) (update-status-line 3859 'plt:module-browser 3860 (gui-utils:trim-string (format module-browser-progress-constant str) 200))) 3861 (λ (user-thread user-custodian) 3862 (send mod-tab set-breakables user-thread user-custodian))) 3863 (send mod-tab set-breakables old-break-thread old-custodian) 3864 (send mod-tab enable-evaluation) 3865 (send module-browser-button enable #t) 3866 (send module-browser-lib-path-check-box enable #t) 3867 (send module-browser-planet-path-check-box enable #t) 3868 (send module-browser-name-length-choice enable #t) 3869 (close-status-line 'plt:module-browser)))) 3870 3871 3872 ; 3873 ; 3874 ; 3875 ; 3876 ; 3877 ; 3878 ; ; ;; ;; ;;; ; ;; ; ; ;;; 3879 ; ;; ;; ; ; ; ;; ; ; ; ; 3880 ; ; ; ; ; ; ; ; ; ; ;; 3881 ; ; ; ; ;;;;;; ; ; ; ; ;; 3882 ; ; ; ; ; ; ; ; ; ; 3883 ; ; ; ; ; ; ; ; ;; ; 3884 ; ; ; ; ;;;; ; ; ;; ; ;;; 3885 ; 3886 ; 3887 ; 3888 3889 (define execute-menu-item #f) 3890 (define file-menu:print-interactions-item #f) 3891 (define file-menu:create-new-tab-item #f) 3892 3893 (define/override (file-menu:between-new-and-open file-menu) 3894 (set! file-menu:create-new-tab-item 3895 (new menu:can-restore-menu-item% 3896 (label (string-constant new-tab)) 3897 (shortcut #\t) 3898 (parent file-menu) 3899 (callback 3900 (λ (x y) 3901 (create-new-tab)))))) 3902 [define/override file-menu:between-open-and-revert 3903 (lambda (file-menu) 3904 (new menu:can-restore-menu-item% 3905 [label (string-constant open-require-path)] 3906 [shortcut (if (member 'shift (get-default-shortcut-prefix)) #f #\o)] 3907 [shortcut-prefix (if (member 'shift (get-default-shortcut-prefix)) 3908 (get-default-shortcut-prefix) 3909 (cons 'shift (get-default-shortcut-prefix)))] 3910 [parent file-menu] 3911 [callback 3912 (λ (x y) 3913 (define editing-path (send (get-definitions-text) get-filename)) 3914 (define editing-module-path 3915 (and editing-path 3916 (match (path->module-path editing-path) 3917 [`(lib ,(? string? s)) 3918 (define m (regexp-match #rx"^(.*/)[^/]*$" s)) 3919 (and m 3920 (list-ref m 1))] 3921 [else #f]))) 3922 ;; editing-module-path won't find anything interesting 3923 ;; if the get-module-path-from-user is using some other 3924 ;; racket binary 3925 (define pth 3926 (get-module-path-from-user 3927 #:init (or editing-module-path 3928 (preferences:get 'drracket:open-module-path-last-used)) 3929 #:pref 'drracket:open-module-path-last-used 3930 #:current-directory 3931 (and editing-path 3932 (let-values ([(base name dir?) (split-path editing-path)]) 3933 base)))) 3934 (when pth (handler:edit-file pth)))]) 3935 (super file-menu:between-open-and-revert file-menu) 3936 (make-object separator-menu-item% file-menu))] 3937 (define close-tab-menu-item #f) 3938 (define/override (file-menu:between-close-and-quit file-menu) 3939 (unless (equal? (system-type) 'unix) 3940 (set! close-tab-menu-item 3941 (new (get-menu-item%) 3942 (label (string-constant close-tab)) 3943 (demand-callback 3944 (λ (item) 3945 (send item enable (1 . < . (send tabs-panel get-number))))) 3946 (parent file-menu) 3947 (callback 3948 (λ (x y) 3949 (close-current-tab)))))) 3950 (super file-menu:between-close-and-quit file-menu)) 3951 3952 (define/override (file-menu:save-string) (string-constant save-definitions)) 3953 (define/override (file-menu:save-as-string) (string-constant save-definitions-as)) 3954 (define/override (file-menu:between-save-as-and-print file-menu) 3955 (let ([sub-menu (make-object menu% (string-constant save-other) file-menu)]) 3956 (make-object menu:can-restore-menu-item% 3957 (string-constant save-definitions-as-text) 3958 sub-menu 3959 (λ (_1 _2) 3960 (let ([filename (send definitions-text put-file #f #f)]) 3961 (when filename 3962 (send definitions-text save-file/gui-error filename 'text))))) 3963 (make-object menu:can-restore-menu-item% 3964 (string-constant save-interactions) 3965 sub-menu 3966 (λ (_1 _2) 3967 (send interactions-text save-file/gui-error))) 3968 (make-object menu:can-restore-menu-item% 3969 (string-constant save-interactions-as) 3970 sub-menu 3971 (λ (_1 _2) 3972 (let ([filename (send interactions-text put-file #f #f)]) 3973 (when filename 3974 (send interactions-text save-file/gui-error filename 'standard))))) 3975 (make-object menu:can-restore-menu-item% 3976 (string-constant save-interactions-as-text) 3977 sub-menu 3978 (λ (_1 _2) 3979 (let ([filename (send interactions-text put-file #f #f)]) 3980 (when filename 3981 (send interactions-text save-file/gui-error filename 'text))))) 3982 (make-object separator-menu-item% file-menu) 3983 (set! transcript-menu-item 3984 (make-object menu:can-restore-menu-item% 3985 (string-constant log-definitions-and-interactions) 3986 file-menu 3987 (λ (x y) 3988 (if transcript 3989 (stop-transcript) 3990 (start-transcript))))) 3991 (make-object separator-menu-item% file-menu) 3992 (super file-menu:between-save-as-and-print file-menu))) 3993 3994 [define/override file-menu:print-string (λ () (string-constant print-definitions))] 3995 (define/override (file-menu:between-print-and-close file-menu) 3996 (set! file-menu:print-interactions-item 3997 (make-object menu:can-restore-menu-item% 3998 (string-constant print-interactions) 3999 file-menu 4000 (λ (_1 _2) 4001 (send interactions-text print 4002 #t 4003 #t 4004 (preferences:get 'framework:print-output-mode))))) 4005 (super file-menu:between-print-and-close file-menu)) 4006 4007 (define/override (edit-menu:between-find-and-preferences edit-menu) 4008 (super edit-menu:between-find-and-preferences edit-menu) 4009 4010 (define (aspell-callback f) 4011 (define problem (aspell-problematic?)) 4012 (cond 4013 [problem 4014 (message-box (string-constant drscheme) problem) 4015 (f #t)] 4016 [else 4017 (f #f)])) 4018 4019 (define (mk-menu-item checking-turned-on? 4020 turn-checking-on 4021 pref-sym 4022 shortcut 4023 label) 4024 (new menu:can-restore-checkable-menu-item% 4025 [label label] 4026 [shortcut (if (member 'shift (get-default-shortcut-prefix)) 4027 #f 4028 shortcut)] 4029 [shortcut-prefix (if (member 'shift (get-default-shortcut-prefix)) 4030 (get-default-shortcut-prefix) 4031 (cons 'shift (get-default-shortcut-prefix)))] 4032 [parent edit-menu] 4033 [demand-callback 4034 (λ (item) 4035 (define ed (get-edit-target-object)) 4036 (define on? (and ed (is-a? ed color:text<%>))) 4037 (send item enable ed) 4038 (send item check (and on? (checking-turned-on? ed))))] 4039 [callback 4040 (λ (item evt) 4041 (aspell-callback 4042 (λ (problem?) 4043 (cond 4044 [problem? (preferences:set pref-sym #f)] 4045 [else 4046 (define ed (get-edit-target-object)) 4047 (define old-val (checking-turned-on? ed)) 4048 (preferences:set pref-sym (not old-val)) 4049 (turn-checking-on ed (not old-val))]))))])) 4050 (mk-menu-item (λ (ed) (send ed get-spell-check-strings)) 4051 (λ (ed new-val) (send ed set-spell-check-strings new-val)) 4052 'framework:spell-check-strings? 4053 #\c 4054 (string-constant spell-check-string-constants)) 4055 (mk-menu-item (λ (ed) (send ed get-spell-check-text)) 4056 (λ (ed new-val) (send ed set-spell-check-text new-val)) 4057 'framework:spell-check-text? 4058 #\t 4059 (string-constant spell-check-scribble-text)) 4060 4061 (new menu:can-restore-menu-item% 4062 [label (string-constant spell-skip-to-next-misspelled-word)] 4063 [shortcut (if (member 'shift (get-default-shortcut-prefix)) 4064 #f 4065 #\n)] 4066 [shortcut-prefix (if (member 'shift (get-default-shortcut-prefix)) 4067 (get-default-shortcut-prefix) 4068 (cons 'shift (get-default-shortcut-prefix)))] 4069 [parent edit-menu] 4070 [demand-callback 4071 (λ (item) 4072 (define ed (get-edit-target-object)) 4073 (define on? (and ed 4074 (is-a? ed color:text<%>) 4075 (= (send ed get-start-position) (send ed get-end-position)))) 4076 (send item enable on?))] 4077 [callback 4078 (λ (item evt) 4079 (aspell-callback 4080 (λ (problem?) 4081 (unless problem? 4082 (define ed (get-edit-target-object)) 4083 (define orig-pos (send ed get-start-position)) 4084 4085 (define (search start end mispelled?) 4086 (let loop ([p start]) 4087 (cond 4088 [(< p end) 4089 (define sp (send ed get-spell-suggestions p)) 4090 (define found-something? (if mispelled? 4091 (list? sp) 4092 (not (list? sp)))) 4093 (cond 4094 [found-something? p] 4095 [else (loop (+ p 1))])] 4096 [else #f]))) 4097 4098 (define first-well-spelled (or (search orig-pos (send ed last-position) #f) 4099 (search 0 orig-pos #f))) 4100 (cond 4101 [first-well-spelled 4102 (define mispelled (or (search first-well-spelled (send ed last-position) #t) 4103 (search 0 first-well-spelled #t))) 4104 (cond 4105 [mispelled (send ed set-position mispelled)] 4106 [else (bell)])] 4107 [else (bell)])))))]) 4108 4109 (new menu:can-restore-menu-item% 4110 [label (string-constant spell-suggest-corrections)] 4111 [shortcut (if (member 'shift (get-default-shortcut-prefix)) 4112 #f 4113 #\k)] 4114 [shortcut-prefix (if (member 'shift (get-default-shortcut-prefix)) 4115 (get-default-shortcut-prefix) 4116 (cons 'shift (get-default-shortcut-prefix)))] 4117 [parent edit-menu] 4118 [demand-callback 4119 (λ (item) 4120 (define ed (get-edit-target-object)) 4121 (define on? (and ed 4122 (is-a? ed color:text<%>) 4123 (= (send ed get-start-position) (send ed get-end-position)))) 4124 (send item enable on?))] 4125 [callback 4126 (λ (item evt) 4127 (aspell-callback 4128 (λ (problem?) 4129 (unless problem? 4130 (define ed (get-edit-target-object)) 4131 (define orig-pos (send ed get-start-position)) 4132 (match (send ed get-spell-suggestions orig-pos) 4133 [(list start end (cons first rest)) 4134 (define suggestions (cons first rest)) 4135 (define choice 4136 (get-choices-from-user (string-constant spell-correction-suggestions) 4137 (string-constant spell-choose-replacement-word) 4138 suggestions 4139 this 4140 '(0))) 4141 (when choice 4142 (send ed begin-edit-sequence) 4143 (send ed delete start end) 4144 (send ed insert (list-ref suggestions (car choice)) start start) 4145 (send ed end-edit-sequence))] 4146 [_ (bell)])))))]) 4147 4148 (define dicts (get-aspell-dicts)) 4149 (when dicts 4150 (define dicts-menu (new menu:can-restore-underscore-menu% 4151 [parent edit-menu] 4152 [label (string-constant spelling-dictionaries)])) 4153 (define (mk-item dict label) 4154 (new menu:can-restore-checkable-menu-item% 4155 [parent dicts-menu] 4156 [label label] 4157 [callback 4158 (λ (item evt) 4159 (define ed (get-edit-target-object)) 4160 (when (and ed (is-a? ed color:text<%>)) 4161 (preferences:set 'framework:aspell-dict dict) 4162 (send ed set-spell-current-dict dict)))] 4163 [demand-callback 4164 (λ (item) 4165 (define ed (get-edit-target-object)) 4166 (send item enable (and ed (is-a? ed color:text<%>))) 4167 (send item check 4168 (and ed 4169 (is-a? ed color:text<%>) 4170 (equal? dict (send ed get-spell-current-dict)))))])) 4171 (mk-item #f (string-constant default-spelling-dictionary)) 4172 (new separator-menu-item% [parent dicts-menu]) 4173 (for ([dict (in-list dicts)]) 4174 (mk-item dict dict))) 4175 (new menu:can-restore-menu-item% 4176 [label (string-constant complete-word)] 4177 [shortcut #\/] 4178 [parent edit-menu] 4179 [demand-callback 4180 (λ (mi) 4181 (send mi enable 4182 (let ([ed (get-edit-target-object)]) 4183 (and ed 4184 (is-a? ed text:autocomplete<%>)))))] 4185 [callback (λ (x y) 4186 (send (get-edit-target-object) auto-complete))]) 4187 (add-modes-submenu edit-menu)) 4188 4189 (define/override (edit-menu:between-select-all-and-find edit-menu) 4190 (new menu:can-restore-checkable-menu-item% 4191 [label (string-constant overwrite-mode)] 4192 [parent edit-menu] 4193 [demand-callback 4194 (λ (mi) 4195 (let ([target (get-edit-target-object)]) 4196 (send mi enable (is-a? target text%)) 4197 (when (is-a? target text%) 4198 (send mi check (and target (send target get-overwrite-mode))))))] 4199 [callback (λ (x y) 4200 (let ([target (get-edit-target-object)]) 4201 (send target set-overwrite-mode 4202 (not (send target get-overwrite-mode)))))]) 4203 (super edit-menu:between-select-all-and-find edit-menu)) 4204 4205 (define/override (edit-menu:between-paste-and-clear edit-menu) 4206 (new menu:can-restore-menu-item% 4207 [label (string-constant paste-and-indent-menu-item)] 4208 [parent edit-menu] 4209 [shortcut #\v] 4210 [shortcut-prefix (cons 'shift (get-default-shortcut-prefix))] 4211 [demand-callback 4212 (λ (item) 4213 (define editor (get-edit-target-object)) 4214 (send item enable 4215 (and editor 4216 (is-a? editor racket:text<%>) 4217 (send editor can-do-edit-operation? 'paste))))] 4218 [callback (λ (x y) 4219 (define target (get-edit-target-object)) 4220 (send target begin-edit-sequence) 4221 (define start-pos-before (send target get-start-position)) 4222 (define end-pos-before (send target get-start-position)) 4223 (define selection-size (- end-pos-before start-pos-before)) 4224 (define positions-before (- (send target last-position) selection-size)) 4225 (send target do-edit-operation 'paste) 4226 (define amount-to-tabify (- (send target last-position) positions-before)) 4227 (send target tabify-selection 4228 start-pos-before 4229 (+ start-pos-before amount-to-tabify)) 4230 (send target end-edit-sequence))]) 4231 (super edit-menu:between-paste-and-clear edit-menu)) 4232 4233 ;; capability-menu-items : hash-table[menu -o> (listof (list menu-item number key))) 4234 (define capability-menu-items (make-hasheq)) 4235 (define/public (register-capability-menu-item key menu) 4236 (let ([items (send menu get-items)]) 4237 (when (null? items) 4238 (error 'register-capability-menu-item "menu ~e has no items" menu)) 4239 (let* ([menu-item (last items)] 4240 [this-one (list menu-item (- (length items) 1) key)] 4241 [old-ones (hash-ref capability-menu-items menu (λ () '()))]) 4242 (hash-set! capability-menu-items menu (cons this-one old-ones))))) 4243 4244 (define/private (update-items/capability menu) 4245 (let* ([old-items (send menu get-items)] 4246 [new-items (begin '(get-items/capability menu) 4247 old-items)]) 4248 (unless (equal? old-items new-items) 4249 (for-each (λ (i) (send i delete)) old-items) 4250 (for-each (λ (i) (send i restore)) new-items)))) 4251 (define/private (get-items/capability menu) 4252 (let loop ([capability-items (reverse (hash-ref capability-menu-items menu '()))] 4253 [all-items (send menu get-items)] 4254 [i 0]) 4255 (cond 4256 [(null? capability-items) all-items] 4257 [(pair? capability-items) 4258 (let* ([cap-item-list (car capability-items)] 4259 [cap-item (list-ref cap-item-list 0)] 4260 [cap-num (list-ref cap-item-list 1)] 4261 [cap-key (list-ref cap-item-list 2)]) 4262 (cond 4263 [(= cap-num i) 4264 (let ([is-on? (get-current-capability-value cap-key)]) 4265 (cond 4266 [is-on? 4267 (cond 4268 [(null? all-items) 4269 (cons cap-item (loop (cdr capability-items) null (+ i 1)))] 4270 [(pair? all-items) 4271 (if (eq? (car all-items) cap-item) 4272 (cons cap-item (loop (cdr capability-items) (cdr all-items) (+ i 1))) 4273 (cons cap-item (loop (cdr capability-items) all-items (+ i 1))))])] 4274 [else 4275 (cond 4276 [(null? all-items) 4277 (loop (cdr capability-items) null (+ i 1))] 4278 [(pair? all-items) 4279 (if (eq? (car all-items) cap-item) 4280 (loop (cdr capability-items) (cdr all-items) (+ i 1)) 4281 (loop (cdr capability-items) all-items (+ i 1)))])]))] 4282 [else (cons (car all-items) 4283 (loop capability-items 4284 (cdr all-items) 4285 (+ i 1)))]))]))) 4286 4287 (define/private (get-current-capability-value key) 4288 (define language-settings (send (get-definitions-text) get-next-settings)) 4289 (define new-language 4290 (drracket:language-configuration:language-settings-language language-settings)) 4291 (send new-language capability-value key)) 4292 4293 (define language-menu 'uninited-language-menu) 4294 (define language-specific-menu 'language-specific-menu-not-yet-init) 4295 (define insert-menu 'insert-menu-not-yet-init) 4296 (define/public (get-insert-menu) insert-menu) 4297 (define/public (get-special-menu) insert-menu) 4298 4299 (define/public (choose-language-callback) 4300 (let ([new-settings (drracket:language-configuration:language-dialog 4301 #f 4302 (send definitions-text get-next-settings) 4303 this)]) 4304 (when new-settings 4305 (send definitions-text set-next-settings new-settings)))) 4306 4307 ;; must be called from on-demand (on each menu click), or the state won't be handled properly 4308 (define/private (update-teachpack-menu) 4309 (for-each (λ (item) (send item delete)) teachpack-items) 4310 (let ([tp-callbacks (get-current-capability-value 'drscheme:teachpack-menu-items)]) 4311 (cond 4312 [tp-callbacks 4313 (let* ([language (drracket:language-configuration:language-settings-language 4314 (send (get-definitions-text) get-next-settings))] 4315 [settings (drracket:language-configuration:language-settings-settings 4316 (send (get-definitions-text) get-next-settings))] 4317 [tp-names ((teachpack-callbacks-get-names tp-callbacks) settings)] 4318 [update-settings 4319 (λ (settings) 4320 (send (get-definitions-text) set-next-settings 4321 (drracket:language-configuration:language-settings language settings)) 4322 (send (get-definitions-text) teachpack-changed) 4323 (update-teachpack-menu))]) 4324 (set! teachpack-items 4325 (list* 4326 (make-object separator-menu-item% language-menu) 4327 (new menu:can-restore-menu-item% 4328 [label (string-constant add-teachpack-menu-item-label)] 4329 [parent language-menu] 4330 [callback 4331 (λ (_1 _2) 4332 (update-settings ((teachpack-callbacks-add tp-callbacks) 4333 settings 4334 this)))]) 4335 (let ([mi (new menu:can-restore-menu-item% 4336 [label (string-constant clear-all-teachpacks-menu-item-label)] 4337 [parent language-menu] 4338 [callback 4339 (λ (_1 _2) 4340 (update-settings 4341 ((teachpack-callbacks-remove-all tp-callbacks) 4342 settings)))])]) 4343 (send mi enable (not (null? tp-names))) 4344 mi) 4345 (map (λ (name) 4346 (new menu:can-restore-menu-item% 4347 [label (gui-utils:format-literal-label 4348 (string-constant clear-teachpack) 4349 name)] 4350 [parent language-menu] 4351 [callback 4352 (λ (item evt) 4353 (update-settings 4354 ((teachpack-callbacks-remove tp-callbacks) 4355 settings name)))])) 4356 tp-names))))] 4357 [else 4358 (set! teachpack-items 4359 (list 4360 (new menu:can-restore-menu-item% 4361 [label (string-constant add-teachpack-menu-item-label)] 4362 [parent language-menu] 4363 [callback 4364 (λ (_1 _2) 4365 (message-box 4366 (string-constant drscheme) 4367 (gui-utils:format-literal-label 4368 (string-constant teachpacks-only-in-languages) 4369 (apply 4370 string-append 4371 (reverse 4372 (filter 4373 values 4374 (map (λ (l) 4375 (and 4376 (send l capability-value 'drscheme:teachpack-menu-items) 4377 (format "\n ~a" (send l get-language-name)))) 4378 (drracket:language-configuration:get-languages)))))) 4379 this 4380 #:dialog-mixin frame:focus-table-mixin))])))]))) 4381 4382 (define/private (initialize-menus) 4383 (define mb (get-menu-bar)) 4384 (set! language-menu (new (get-menu%) 4385 [label (string-constant language-menu-name)] 4386 [parent mb])) 4387 (set! language-specific-menu (new (get-menu%) 4388 [label (drracket:language:get-capability-default 4389 'drscheme:language-menu-title)] 4390 [parent mb])) 4391 (define ((send-method method) _1 _2) 4392 (define text (get-edit-target-object)) 4393 (when (is-a? text racket:text<%>) 4394 (method text))) 4395 (define (show/hide-capability-menus) 4396 (for ([menu (in-list (send (get-menu-bar) get-items))]) 4397 (update-items/capability menu))) 4398 4399 (make-object menu:can-restore-menu-item% 4400 (string-constant choose-language-menu-item-label) 4401 language-menu 4402 (λ (_1 _2) (choose-language-callback)) 4403 #\l) 4404 4405 (set! execute-menu-item 4406 (make-object menu:can-restore-menu-item% 4407 (string-constant execute-menu-item-label) 4408 language-specific-menu 4409 (λ (_1 _2) (execute-callback)) 4410 #\r 4411 (string-constant execute-menu-item-help-string))) 4412 (make-object menu:can-restore-menu-item% 4413 (string-constant ask-quit-menu-item-label) 4414 language-specific-menu 4415 (λ (_1 _2) (send current-tab break-callback)) 4416 #\b 4417 (string-constant ask-quit-menu-item-help-string)) 4418 (make-object menu:can-restore-menu-item% 4419 (string-constant force-quit-menu-item-label) 4420 language-specific-menu 4421 (λ (_1 _2) (send interactions-text kill-evaluation)) 4422 #\k 4423 (string-constant force-quit-menu-item-help-string)) 4424 (new menu:can-restore-menu-item% 4425 [label (string-constant module-language-#lang-flush-cache-menu-item)] 4426 [parent language-specific-menu] 4427 [callback (λ (_1 _2) (send (send current-tab get-defs) move-to-new-language #t))] 4428 [shortcut #\d] 4429 [shortcut-prefix (cons 'shift (get-default-shortcut-prefix))]) 4430 (when (custodian-memory-accounting-available?) 4431 (new menu-item% 4432 [label (string-constant limit-memory-menu-item-label)] 4433 [parent language-specific-menu] 4434 [callback 4435 (λ (item b) 4436 (let ([num (get-mbytes this 4437 (let ([limit (send interactions-text get-custodian-limit)]) 4438 (and limit 4439 (floor (/ limit 1024 1024)))))]) 4440 (when num 4441 (cond 4442 [(equal? num #t) 4443 (preferences:set 'drracket:child-only-memory-limit #f) 4444 (send interactions-text set-custodian-limit #f)] 4445 [else 4446 (preferences:set 'drracket:child-only-memory-limit 4447 (* 1024 1024 num)) 4448 (send interactions-text set-custodian-limit 4449 (* 1024 1024 num))]))))])) 4450 4451 (new menu:can-restore-menu-item% 4452 (label (string-constant clear-error-highlight-menu-item-label)) 4453 (parent language-specific-menu) 4454 (callback 4455 (λ (_1 _2) 4456 (let* ([tab (get-current-tab)] 4457 [ints (send tab get-ints)] 4458 [defs (send tab get-defs)]) 4459 (send ints reset-error-ranges) 4460 (send defs clear-test-coverage)))) 4461 (help-string (string-constant clear-error-highlight-item-help-string)) 4462 (demand-callback 4463 (λ (item) 4464 (let* ([tab (get-current-tab)] 4465 [ints (send tab get-ints)]) 4466 (send item enable (or (send ints get-error-ranges) 4467 (send tab get-test-coverage-info-visible?))))))) 4468 4469 (new menu:can-restore-menu-item% 4470 (label (string-constant jump-to-next-error-highlight-menu-item-label)) 4471 (parent language-specific-menu) 4472 (shortcut #\.) 4473 (callback (λ (_1 _2) (jump-to-next-error-loc))) 4474 (demand-callback 4475 (λ (item) 4476 (let* ([tab (get-current-tab)] 4477 [ints (send tab get-ints)]) 4478 (send item enable (send ints get-error-ranges)))))) 4479 (new menu:can-restore-menu-item% 4480 (label (string-constant jump-to-prev-error-highlight-menu-item-label)) 4481 (parent language-specific-menu) 4482 (shortcut (if (equal? (system-type) 'macosx) #\. #\,)) 4483 (shortcut-prefix (if (equal? (system-type) 'macosx) 4484 (cons 'shift (get-default-shortcut-prefix)) 4485 (get-default-shortcut-prefix))) 4486 (callback (λ (_1 _2) (jump-to-previous-error-loc))) 4487 (demand-callback 4488 (λ (item) 4489 (let* ([tab (get-current-tab)] 4490 [ints (send tab get-ints)]) 4491 (send item enable (send ints get-error-ranges)))))) 4492 (make-object separator-menu-item% language-specific-menu) 4493 (make-object menu:can-restore-menu-item% 4494 (string-constant create-executable-menu-item-label) 4495 language-specific-menu 4496 (λ (x y) (create-executable this))) 4497 (make-object menu:can-restore-menu-item% 4498 (string-constant module-browser...) 4499 language-specific-menu 4500 (λ (x y) (drracket:module-overview:module-overview this))) 4501 (let () 4502 (define (update-menu-item i) 4503 (define fn (send definitions-text get-filename)) 4504 (define lab-str (compute-label-string fn)) 4505 (send i set-label lab-str) 4506 (send i enable fn)) 4507 (define i (new menu:can-restore-menu-item% 4508 [label ""] 4509 [parent language-specific-menu] 4510 [demand-callback update-menu-item] 4511 [callback (λ (x y) 4512 (define fn (send definitions-text get-filename)) 4513 (when fn 4514 (drracket:module-overview:module-overview/file fn this)))])) 4515 (update-menu-item i)) 4516 (make-object separator-menu-item% language-specific-menu) 4517 4518 (let ([cap-val 4519 (λ () 4520 (define tab (get-current-tab)) 4521 (define defs (send tab get-defs)) 4522 (define settings (send defs get-next-settings)) 4523 (define language 4524 (drracket:language-configuration:language-settings-language settings)) 4525 (send language capability-value 'drscheme:tabify-menu-callback))]) 4526 (new menu:can-restore-menu-item% 4527 [label (string-constant reindent-menu-item-label)] 4528 [parent language-specific-menu] 4529 [demand-callback (λ (m) (send m enable (cap-val)))] 4530 [callback (send-method 4531 (λ (x) 4532 (let ([f (cap-val)]) 4533 (when f 4534 (f x 4535 (send x get-start-position) 4536 (send x get-end-position))))))]) 4537 4538 (new menu:can-restore-menu-item% 4539 [label (string-constant reindent-all-menu-item-label)] 4540 [parent language-specific-menu] 4541 [callback 4542 (send-method 4543 (λ (x) 4544 (let ([f (cap-val)]) 4545 (when f 4546 (f x 0 (send x last-position))))))] 4547 [shortcut #\i] 4548 [demand-callback (λ (m) (send m enable (cap-val)))])) 4549 4550 (make-object menu:can-restore-menu-item% 4551 (string-constant box-comment-out-menu-item-label) 4552 language-specific-menu 4553 (send-method (λ (x) (send x box-comment-out-selection)))) 4554 (make-object menu:can-restore-menu-item% 4555 (string-constant semicolon-comment-out-menu-item-label) 4556 language-specific-menu 4557 (send-method (λ (x) (send x comment-out-selection)))) 4558 (make-object menu:can-restore-menu-item% 4559 (string-constant uncomment-menu-item-label) 4560 language-specific-menu 4561 (λ (x y) 4562 (let ([text (get-focus-object)]) 4563 (when (is-a? text text%) 4564 (let ([admin (send text get-admin)]) 4565 (cond 4566 [(is-a? admin editor-snip-editor-admin<%>) 4567 (let ([es (send admin get-snip)]) 4568 (cond 4569 [(is-a? es comment-box:snip%) 4570 (let ([es-admin (send es get-admin)]) 4571 (when es-admin 4572 (let ([ed (send es-admin get-editor)]) 4573 (when (is-a? ed racket:text<%>) 4574 (send ed uncomment-box/selection)))))] 4575 [else (send text uncomment-selection)]))] 4576 [else (send text uncomment-selection)])))))) 4577 4578 (set! insert-menu 4579 (new (get-menu%) 4580 [label (string-constant insert-menu)] 4581 [parent mb] 4582 [demand-callback 4583 (λ (insert-menu) 4584 ;; just here for convience -- it actually 4585 ;; works on all menus, not just the special menu 4586 (show/hide-capability-menus))])) 4587 4588 (let ([has-editor-on-demand 4589 (λ (menu-item) 4590 (let ([edit (get-edit-target-object)]) 4591 (send menu-item enable (and edit (is-a? edit editor<%>)))))] 4592 [callback 4593 (λ (menu evt) 4594 (let ([edit (get-edit-target-object)]) 4595 (when (and edit 4596 (is-a? edit editor<%>)) 4597 (let ([number (get-fraction-from-user this)]) 4598 (when number 4599 (send edit insert 4600 (number-snip:make-fraction-snip number #f))))) 4601 #t))] 4602 [insert-lambda 4603 (λ () 4604 (let ([edit (get-edit-target-object)]) 4605 (when (and edit 4606 (is-a? edit editor<%>)) 4607 (send edit insert "\u03BB"))) 4608 #t)] 4609 [insert-large-semicolon-letters 4610 (λ () 4611 (let ([edit (get-edit-target-object)]) 4612 (when edit 4613 (define language-settings (send definitions-text get-next-settings)) 4614 (define-values(comment-prefix comment-character) 4615 (if language-settings 4616 (send (drracket:language-configuration:language-settings-language 4617 language-settings) 4618 get-comment-character) 4619 (values ";" #\;))) 4620 (insert-large-letters comment-prefix comment-character edit this))))] 4621 [c% (get-menu-item%)]) 4622 4623 (frame:add-snip-menu-items 4624 insert-menu 4625 c% 4626 (λ (item) 4627 (let ([label (send item get-label)]) 4628 (cond 4629 [(equal? label (string-constant insert-comment-box-menu-item-label)) 4630 (register-capability-menu-item 'drscheme:special:insert-comment-box insert-menu)] 4631 [(equal? label (string-constant insert-image-item)) 4632 (register-capability-menu-item 'drscheme:special:insert-image insert-menu)])))) 4633 4634 (make-object c% (string-constant insert-fraction-menu-item-label) 4635 insert-menu callback 4636 #f #f 4637 has-editor-on-demand) 4638 (register-capability-menu-item 'drscheme:special:insert-fraction insert-menu) 4639 4640 (make-object c% (string-constant insert-large-letters...) 4641 insert-menu 4642 (λ (x y) (insert-large-semicolon-letters)) 4643 #f #f 4644 has-editor-on-demand) 4645 (register-capability-menu-item 'drscheme:special:insert-large-letters insert-menu) 4646 4647 (make-object c% (string-constant insert-lambda) 4648 insert-menu 4649 (λ (x y) (insert-lambda)) 4650 #\\ 4651 #f 4652 has-editor-on-demand) 4653 (register-capability-menu-item 'drscheme:special:insert-lambda insert-menu)) 4654 4655 (frame:reorder-menus this)) 4656 4657 (define/public (jump-to-previous-error-loc) 4658 (define-values (before after sorted) (find-before-and-after)) 4659 (unless (null? sorted) 4660 (jump-to-source-loc (or before (last sorted))))) 4661 4662 (define/public (jump-to-next-error-loc) 4663 (define-values (before after sorted) (find-before-and-after)) 4664 (unless (null? sorted) 4665 (jump-to-source-loc (or after (car sorted))))) 4666 4667 (define/private (find-before-and-after) 4668 (define tab (get-current-tab)) 4669 (define pos (send (send tab get-defs) get-start-position)) 4670 (define ranges (or (send (send tab get-ints) get-error-ranges) '())) 4671 (define sorted (sort ranges < #:key srcloc-position)) 4672 (let loop ([before #f] 4673 [lst sorted]) 4674 (cond 4675 [(null? lst) 4676 (values before #f sorted)] 4677 [else 4678 (define fst (car lst)) 4679 (cond 4680 [(= pos (- (srcloc-position fst) 1)) 4681 (values before 4682 (if (null? (cdr lst)) 4683 #f 4684 (cadr lst)) 4685 sorted)] 4686 [(< pos (- (srcloc-position fst) 1)) 4687 (values before fst sorted)] 4688 [else (loop (car lst) (cdr lst))])]))) 4689 4690 (define/private (jump-to-source-loc srcloc) 4691 (define ed (srcloc-source srcloc)) 4692 (send ed set-position (- (srcloc-position srcloc) 1)) 4693 (send ed set-caret-owner #f 'global) 4694 (send (get-interactions-text) highlight-a-single-error srcloc)) 4695 4696 (define/public (move-to-interactions) 4697 (ensure-rep-shown (get-interactions-text)) 4698 (send (get-interactions-canvas) focus)) 4699 4700 4701 ; 4702 ; 4703 ; 4704 ; 4705 ; ++-@@- -+@+- +++: :++ 4706 ; +@@-+@ -@-:-@--@- -@ 4707 ; :@: @: @+ ++ @::@::@ 4708 ; :@ @: @@@@@@@ +--@--* 4709 ; :@ @: @- -@+*+@: 4710 ; -@: :@- +@:::+@ :@@:@@ 4711 ; @@@ +@@: +@@@+: ++ ++ 4712 ; 4713 ; 4714 ; 4715 4716 (define definitions-text (new (drracket:get/extend:get-definitions-text))) 4717 4718 ;; tabs : (listof tab) 4719 (define tabs (list (new (drracket:get/extend:get-tab) 4720 (defs definitions-text) 4721 (frame this) 4722 (i 0) 4723 (defs-shown? #t) 4724 (ints-shown? #t)))) 4725 (define/public-final (get-tabs) tabs) 4726 4727 ;; current-tab : tab 4728 ;; corresponds to the tabs-panel's active button. 4729 (define current-tab (car tabs)) 4730 4731 (define interactions-text (new (drracket:get/extend:get-interactions-text) 4732 (context (car tabs)))) 4733 (send (car tabs) set-ints interactions-text) 4734 4735 (init-definitions-text (car tabs)) 4736 4737 (define/override (adjust-size-when-monitor-setup-changes?) 4738 (= 1 (for/sum ([f (in-list (get-top-level-windows))]) 4739 (if (is-a? f drracket:unit:frame<%>) 4740 1 4741 0)))) 4742 4743 (define/override (find-editor predicate) 4744 (or (findf predicate (map (lambda (tab) (send tab get-defs)) 4745 tabs)) 4746 (findf predicate (map (lambda (tab) (send tab get-ints)) 4747 tabs)))) 4748 4749 (super-new 4750 [filename filename] 4751 [style '(toolbar-button fullscreen-button)] 4752 [size-preferences-key 'drracket:window-size] 4753 [position-preferences-key 'drracket:window-position]) 4754 4755 (initialize-menus) 4756 4757 4758 ; 4759 ; 4760 ; 4761 ; ; ; 4762 ; ; ; 4763 ; ; ; ; 4764 ; ; ;; ;;; ; ;; ;;; ; ; ;;; ; ; ;;; ; ; ;;;; 4765 ; ;; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4766 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4767 ; ; ; ;;;; ; ; ;;;;;; ; ; ;;;; ; ; ; ; ; ; ; 4768 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4769 ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; 4770 ; ; ;; ;;;;; ; ; ;;;; ; ; ;;;;; ; ;;; ;; ; ;; 4771 ; ; ; 4772 ; ; ; 4773 ; ; ; 4774 4775 4776 (define toolbar/rest-panel (new-vertical-panel% [parent (get-area-container)])) 4777 4778 ;; most contain only top-panel (or nothing) 4779 (define top-outer-panel (new horizontal-pane% 4780 [parent toolbar/rest-panel] 4781 [alignment '(right top)] 4782 [stretchable-height #f])) 4783 4784 [define top-panel (make-object horizontal-panel% top-outer-panel)] 4785 [define name-panel (new-horizontal-panel% 4786 (parent top-panel) 4787 (alignment '(left center)) 4788 (stretchable-width #f) 4789 (stretchable-height #f))] 4790 (define panel-with-tabs (new vertical-pane% 4791 (parent (get-definitions/interactions-panel-parent)))) 4792 (define tabs-panel (new 4793 (class tab-panel% 4794 (define/override (on-close-request i) 4795 (close-ith-tab i)) 4796 (define/augment (on-reorder former-indicies) 4797 (reorder-tabs former-indicies)) 4798 (super-new 4799 (font small-control-font) 4800 (parent panel-with-tabs) 4801 (stretchable-height #f) 4802 (style '(deleted no-border can-reorder can-close)) 4803 (choices '("first name")) 4804 (callback (λ (x y) 4805 (define sel (send tabs-panel get-selection)) 4806 (when sel 4807 (change-to-nth-tab sel)))))))) 4808 (set! resizable-panel (new (if (preferences:get 'drracket:defs/ints-horizontal) 4809 horizontal-dragable/def-int% 4810 vertical-dragable/def-int%) 4811 (unit-frame this) 4812 (parent panel-with-tabs))) 4813 4814 [set! definitions-canvas #f] 4815 (initialize-definitions-canvas) 4816 (set! definitions-canvases (list definitions-canvas)) 4817 4818 (set! interactions-canvas (new (drracket:get/extend:get-interactions-canvas) 4819 (parent resizable-panel) 4820 (editor interactions-text))) 4821 (set! interactions-canvases (list interactions-canvas)) 4822 4823 4824 (define/public (get-definitions-canvases) 4825 ;; before definition, just return null 4826 (if (pair? definitions-canvases) 4827 definitions-canvases 4828 null)) 4829 (define/public (get-interactions-canvases) 4830 ;; before definition, just return null 4831 (if (pair? interactions-canvases) 4832 interactions-canvases 4833 null)) 4834 4835 (define/public (get-definitions-canvas) definitions-canvas) 4836 (define/public (get-interactions-canvas) interactions-canvas) 4837 4838 (set! save-button 4839 (new switchable-button% 4840 [parent top-panel] 4841 [callback (λ (x) (when definitions-text 4842 (save) 4843 (send definitions-canvas focus)))] 4844 [bitmap save-bitmap] 4845 [alternate-bitmap small-save-bitmap] 4846 [label (string-constant save-button-label)])) 4847 (register-toolbar-button save-button) 4848 4849 (set! name-message (new drs-name-message% [parent name-panel])) 4850 (send name-message stretchable-width #t) 4851 (send name-message set-allow-shrinking 160) 4852 [define teachpack-items null] 4853 [define break-button (void)] 4854 [define execute-button (void)] 4855 (set! button-panel (new panel:horizontal-discrete-sizes% 4856 [parent top-panel] 4857 [stretchable-width #t] 4858 [alignment '(right center)])) 4859 (define/public (get-execute-button) execute-button) 4860 (define/public (get-break-button) break-button) 4861 (define/public (get-button-panel) button-panel) 4862 4863 ;; #t => "break"; #f => "kill" in button label 4864 (define showing-break? #t) 4865 (define/public (update-kill-button-label) 4866 (unless (equal? showing-break? (not (send (get-current-tab) does-break-kill?))) 4867 (set! showing-break? (not (send (get-current-tab) does-break-kill?))) 4868 (send break-button set-label (if showing-break? 4869 (string-constant break-button-label) 4870 (string-constant break-button-kill-label))))) 4871 4872 (inherit get-info-panel) 4873 4874 (define color-status-canvas 4875 (let () 4876 (define on-string "()") 4877 (define color-status-canvas 4878 (new canvas% 4879 [parent (get-info-panel)] 4880 [style '(transparent)] 4881 [stretchable-width #f] 4882 [paint-callback 4883 (λ (c dc) 4884 (when (number? th) 4885 (unless color-valid? 4886 (define-values (cw ch) (send c get-client-size)) 4887 (send dc set-text-foreground (get-label-foreground-color)) 4888 (send dc set-font small-control-font) 4889 (send dc draw-text on-string 0 (- (/ ch 2) (/ th 2))))))])) 4890 (define-values (tw th ta td) 4891 (send (send color-status-canvas get-dc) get-text-extent 4892 on-string small-control-font)) 4893 (send color-status-canvas min-width (inexact->exact (ceiling tw))) 4894 color-status-canvas)) 4895 (define color-valid? #t) 4896 (define/public (set-color-status! v?) 4897 (when color-status-canvas 4898 (set! color-valid? v?) 4899 (send color-status-canvas refresh-now))) 4900 4901 (define running-canvas 4902 (new running-canvas% [parent (get-info-panel)])) 4903 4904 (define bug-icon 4905 (let* ([info-panel (get-info-panel)] 4906 [btn 4907 (new switchable-button% 4908 [parent info-panel] 4909 [callback (λ (x) (show-saved-bug-reports-window))] 4910 [bitmap very-small-planet-bitmap] 4911 [vertical-tight? #t] 4912 [label (string-constant show-planet-contract-violations)])]) 4913 (send btn set-label-visible #f) 4914 (send info-panel change-children 4915 (λ (l) 4916 (cons btn (remq* (list btn) l)))) 4917 btn)) 4918 (define/private (set-bug-label v) 4919 (if (null? v) 4920 (send bug-icon show #f) 4921 (send bug-icon show #t))) 4922 (set-bug-label (preferences:get 'drracket:saved-bug-reports)) 4923 (define remove-bug-icon-callback 4924 (preferences:add-callback 4925 'drracket:saved-bug-reports 4926 (λ (p v) 4927 (set-bug-label v)))) 4928 4929 [define func-defs-canvas (new func-defs-canvas% 4930 (parent name-panel) 4931 (frame this))] 4932 4933 (set! execute-button 4934 (new switchable-button% 4935 [parent button-panel] 4936 [callback (λ (x) (execute-callback))] 4937 [bitmap execute-bitmap] 4938 [label (string-constant execute-button-label)])) 4939 (register-toolbar-button execute-button #:number 100) 4940 4941 (set! break-button 4942 (new switchable-button% 4943 [parent button-panel] 4944 [callback (λ (x) (send current-tab break-callback))] 4945 [bitmap break-bitmap] 4946 [label (string-constant break-button-label)])) 4947 (register-toolbar-button break-button #:number 101) 4948 4949 (send top-panel change-children 4950 (λ (l) 4951 (list name-panel save-button button-panel))) 4952 4953 (send top-panel stretchable-height #f) 4954 (inherit get-label) 4955 (let ([m (send definitions-canvas get-editor)]) 4956 (set-save-init-shown? 4957 (and m (send m is-modified?)))) 4958 4959 (define language-message 4960 (let* ([info-panel (get-info-panel)] 4961 [p (new-vertical-panel% 4962 [parent info-panel] 4963 [alignment '(left center)])] 4964 [language-message (new language-label-message% [parent p] [frame this])]) 4965 (send info-panel change-children 4966 (λ (l) 4967 (list* p 4968 (remq* (list p) 4969 l)))) 4970 language-message)) 4971 4972 (update-save-message) 4973 (update-save-button) 4974 (language-changed) 4975 4976 (cond 4977 [filename 4978 (set! definitions-shown? #t) 4979 (set! interactions-shown? #f)] 4980 [else 4981 (set! definitions-shown? #t) 4982 (set! interactions-shown? #t)]) 4983 4984 (update-shown) 4985 4986 (when (= 2 (length (send resizable-panel get-children))) 4987 (send resizable-panel set-percentages 4988 (let ([p (preferences:get 'drracket:unit-window-size-percentage)]) 4989 (list p (- 1 p))))) 4990 4991 (set-label-prefix (string-constant drscheme)) 4992 (set! newest-frame this) 4993 ;; a callback might have happened that initializes set-color-status! before the 4994 ;; definitions text is connected to the frame, so we do an extra initialization 4995 ;; now, once we know we have the right connection 4996 (set-color-status! (send definitions-text is-lexer-valid?)) 4997 (send definitions-canvas focus) 4998 (send definitions-text enable-top-level-window-connection))) 4999 5000 (define (get-define-popup-name infos vertical?) 5001 (cond 5002 [infos 5003 (define hidden-prefixes (preferences:get 'drracket:define-popup-hidden-prefixes)) 5004 (define visible-infos 5005 (for/list ([info (in-list infos)] 5006 #:unless (member (define-popup-info-long-name info) 5007 hidden-prefixes)) 5008 info)) 5009 (define the-info (if (null? visible-infos) (car infos) (car visible-infos))) 5010 (if vertical? 5011 (define-popup-info-short-name the-info) 5012 (define-popup-info-long-name the-info))] 5013 [else 5014 #f])) 5015 5016 5017 (define execute-warning-canvas% 5018 (class canvas% 5019 (inherit stretchable-height get-dc get-client-size min-height) 5020 (init-field message) 5021 (define/public (set-message _msg) (set! message _msg)) 5022 5023 (define/override (on-paint) 5024 (let ([dc (get-dc)]) 5025 (let-values ([(w h) (get-client-size)]) 5026 (send dc set-pen "yellow" 1 'solid) 5027 (send dc set-brush "yellow" 'solid) 5028 (send dc draw-rectangle 0 0 w h) 5029 (when message 5030 (let* ([base normal-control-font] 5031 [face (send base get-face)]) 5032 (if face 5033 (send dc set-font (send the-font-list find-or-create-font 5034 (send base get-point-size) 5035 face 5036 (send base get-family) 5037 (send base get-style) 5038 'bold)) 5039 (send dc set-font (send the-font-list find-or-create-font 5040 (send base get-point-size) 5041 (send base get-family) 5042 (send base get-style) 5043 'bold)))) 5044 (let-values ([(tw th _1 _2) (send dc get-text-extent message)]) 5045 (send dc draw-text message 5046 (floor (- (/ w 2) (/ tw 2))) 5047 (floor (- (/ h 2) (/ th 2))))))))) 5048 (super-new [style '(no-focus)]) 5049 (let-values ([(w h d a) (send (get-dc) get-text-extent "Xy")]) 5050 (min-height (+ 4 (floor (inexact->exact h))))))) 5051 5052 5053 ; 5054 ; 5055 ; 5056 ; 5057 ; ;;; 5058 ; 5059 ; ;;; ;;;; ;;; ;;; ;; ;;; ;; ;;; ;;; ;; ;; ;;; 5060 ; ;;;;;;;; ;;; ;;;;;;; ;;;;;;; ;;; ;;;;;;; ;;;;;;; 5061 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 5062 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 5063 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 5064 ; ;;; ;;;;;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;;;;; 5065 ; ;;; ;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;; ;;; 5066 ; ;;; 5067 ; ;;;;;; 5068 ; 5069 ; 5070 5071 (define running-canvas% 5072 (class canvas% 5073 (inherit get-dc refresh get-client-size) 5074 5075 (define running-frame-delay 200) ; 5 FPS at the most (if user program is blocked or waiting) 5076 (define num-running-frames (vector-length running-frames)) 5077 (define is-running? #f) 5078 (define frame 0) 5079 (define timer (make-object logging-timer% (λ () (refresh) (yield)) #f)) 5080 5081 (define/public (set-running r?) 5082 (cond [r? (unless is-running? (set! frame 4)) 5083 (send timer start running-frame-delay #f)] 5084 [else (send timer stop) 5085 (refresh)]) 5086 (set! is-running? r?)) 5087 5088 (define/override (on-paint) 5089 (define dc (get-dc)) 5090 (define bm (cond [is-running? (define bm (vector-ref running-frames frame)) 5091 (set! frame (modulo (+ frame 1) num-running-frames)) 5092 bm] 5093 [else standing-frame])) 5094 (define-values (w h) (get-client-size)) 5095 (send dc draw-bitmap bm 5096 (- (/ w 2) (/ (send bm get-width) 2)) 5097 (- (/ h 2) (/ (send bm get-height) 2)))) 5098 5099 (super-new [stretchable-width #f] 5100 [stretchable-height #f] 5101 [style '(transparent no-focus)]) 5102 5103 (inherit min-width min-height) 5104 5105 (define all-running-frames (cons standing-frame running-frame-list)) 5106 (min-width (apply max (map (λ (x) (send x get-width)) all-running-frames))) 5107 (min-height (apply max (map (λ (x) (send x get-height)) all-running-frames))))) 5108 5109 ;; get-mbytes : top-level-window -> (union #f ;; cancel 5110 ;; integer[>=100] ;; a limit 5111 ;; #t) ;; no limit 5112 (define (get-mbytes parent current-limit) 5113 (define d (new dialog% 5114 [label (string-constant drscheme)] 5115 [parent parent])) 5116 (define msg1 (new message% 5117 [parent d] 5118 [label (string-constant limit-memory-msg-1)])) 5119 (define msg1.5 (new message% 5120 [parent d] 5121 [label (string-constant limit-memory-msg-2)])) 5122 5123 (define top-hp (new-horizontal-panel% 5124 [parent d] 5125 [stretchable-height #f] 5126 [alignment '(left center)])) 5127 (define bot-hp (new-horizontal-panel% 5128 [parent d] 5129 [stretchable-height #f] 5130 [alignment '(left bottom)])) 5131 (define limited-rb 5132 (new radio-box% 5133 [label #f] 5134 [choices (list (string-constant limit-memory-limited))] 5135 [callback (λ (a b) 5136 (send unlimited-rb set-selection #f) 5137 (cb-checked))] 5138 [parent top-hp])) 5139 (define unlimited-rb 5140 (new radio-box% 5141 [label #f] 5142 [choices (list (string-constant limit-memory-unlimited))] 5143 [callback (λ (a b) 5144 (send limited-rb set-selection #f) 5145 (cb-checked))] 5146 [parent bot-hp])) 5147 5148 (define unlimited-warning-panel (new-horizontal-panel% 5149 [parent d] 5150 [stretchable-width #t] 5151 [stretchable-height #f])) 5152 5153 (define (show-unlimited-warning) 5154 (when (null? (send unlimited-warning-panel get-children)) 5155 (send d begin-container-sequence) 5156 (define t (new text%)) 5157 (send t insert (string-constant limit-memory-warning-prefix)) 5158 (define between-pos (send t last-position)) 5159 (send t insert (string-constant limit-memory-warning)) 5160 5161 (define sdb (make-object style-delta% 'change-family 'system)) 5162 (send sdb set-delta-face (send normal-control-font get-face)) 5163 (send sdb set-size-mult 0) 5164 (send sdb set-size-add (send normal-control-font get-point-size)) 5165 (send sdb set-size-in-pixels-off #t) 5166 (send sdb set-weight-on 'bold) 5167 (when (white-on-black-panel-scheme?) 5168 (send sdb set-delta-foreground "white")) 5169 (define sd (make-object style-delta%)) 5170 (send sd copy sdb) 5171 (send sd set-weight-on 'normal) 5172 5173 (send t change-style sdb 0 between-pos) 5174 (send t change-style sd between-pos (send t last-position)) 5175 (define ec (new editor-canvas% 5176 [editor t] 5177 [parent unlimited-warning-panel] 5178 [style '(no-border no-focus hide-hscroll hide-vscroll transparent)] 5179 [horiz-margin 12])) 5180 (send t auto-wrap #t) 5181 (send d reflow-container) 5182 (send ec set-line-count (+ 1 (send t position-line (send t last-position)))) 5183 (send t hide-caret #t) 5184 (send t lock #t) 5185 (send d end-container-sequence) 5186 (send unlimited-rb focus))) 5187 5188 (define (cb-checked) 5189 (cond 5190 [(send limited-rb get-selection) 5191 (send tb enable #t) 5192 (send msg2 enable #t) 5193 (background black-foreground-sd) 5194 (let ([e (send tb get-editor)]) 5195 (send e set-position 0 (send e last-position))) 5196 (send tb focus)] 5197 [else 5198 (show-unlimited-warning) 5199 (send tb enable #f) 5200 (send msg2 enable #f) 5201 (background gray-foreground-sd)]) 5202 (update-ok-button-state)) 5203 5204 (define tb 5205 (keymap:call/text-keymap-initializer 5206 (λ () 5207 (new text-field% 5208 [label #f] 5209 [parent top-hp] 5210 [init-value (if current-limit 5211 (format "~a" current-limit) 5212 "128")] 5213 [stretchable-width #f] 5214 [min-width 100] 5215 [callback 5216 (λ (tf e) 5217 (let ([ed (send tf get-editor)]) 5218 (cond 5219 [(is-valid-number? ed) 5220 (background clear-sd)] 5221 [else 5222 (background yellow-sd)])) 5223 (update-ok-button-state))])))) 5224 5225 (define (update-ok-button-state) 5226 (cond 5227 [(send limited-rb get-selection) 5228 (send ok-button enable (is-valid-number? (send tb get-editor)))] 5229 [else 5230 (send ok-button enable #t)])) 5231 5232 (define msg2 (new message% [parent top-hp] [label (string-constant limit-memory-megabytes)])) 5233 (define bp (new-horizontal-panel% [parent d])) 5234 (define-values (ok-button cancel-button) 5235 (gui-utils:ok/cancel-buttons 5236 bp 5237 (λ (a b) 5238 (cond 5239 [(send limited-rb get-selection) 5240 (set! result (string->number (send (send tb get-editor) get-text)))] 5241 [else 5242 (set! result #t)]) 5243 (send d show #f)) 5244 (λ (a b) (send d show #f)))) 5245 5246 (define result #f) 5247 5248 (define clear-sd (make-object style-delta%)) 5249 (define yellow-sd (make-object style-delta%)) 5250 5251 (define black-foreground-sd (make-object style-delta%)) 5252 (define gray-foreground-sd (make-object style-delta%)) 5253 5254 (define (is-valid-number? txt) 5255 (let* ([n (string->number (send txt get-text))]) 5256 (and n 5257 (exact-positive-integer? n) 5258 (8 . <= . n)))) 5259 5260 (define (background sd) 5261 (let ([txt (send tb get-editor)]) 5262 (send txt change-style sd 0 (send txt last-position)))) 5263 5264 (send clear-sd set-delta-background 5265 (if (white-on-black-panel-scheme?) "black" "white")) 5266 (send yellow-sd set-delta-background "yellow") 5267 (send black-foreground-sd set-delta-foreground 5268 (if (white-on-black-panel-scheme?) "white" "black")) 5269 (send gray-foreground-sd set-delta-foreground "gray") 5270 (send d set-alignment 'left 'center) 5271 (send bp set-alignment 'right 'center) 5272 (cond 5273 [current-limit 5274 (send limited-rb set-selection 0) 5275 (send unlimited-rb set-selection #f)] 5276 [else 5277 (send unlimited-rb set-selection 0) 5278 (send limited-rb set-selection #f)]) 5279 (update-ok-button-state) 5280 (cb-checked) 5281 (let ([e (send tb get-editor)]) 5282 (send e set-position 0 (send e last-position))) 5283 (cond 5284 [current-limit (send tb focus)] 5285 [else (send unlimited-rb focus)]) 5286 (send d show #t) 5287 result) 5288 5289 (define (limit-length l n) 5290 (let loop ([l l] 5291 [n n]) 5292 (cond 5293 [(or (null? l) (zero? n)) null] 5294 [else (cons (car l) (loop (cdr l) (- n 1)))]))) 5295 (define (remove-duplicate-languages l) 5296 (reverse 5297 (let loop ([l (reverse l)]) 5298 (cond 5299 [(null? l) l] 5300 [else 5301 (if (member (car (car l)) (map car (cdr l))) 5302 (loop (cdr l)) 5303 (cons (car l) (loop (cdr l))))])))) 5304 5305 (define language-label-message% 5306 (class name-message% 5307 (init-field frame) 5308 (inherit refresh) 5309 5310 (inherit set-message) 5311 (define yellow? #f) 5312 (define/override (get-background-color) 5313 (and yellow? 5314 (color-prefs:lookup-in-color-scheme 5315 'framework:warning-background-color))) 5316 (define/public (set-yellow y?) 5317 (set! yellow? y?) 5318 (refresh)) 5319 (define/public (set-yellow/lang y? lang) 5320 (set-message #f lang) 5321 (set-yellow y?)) 5322 5323 (define/override (fill-popup menu reset) 5324 (let ([added-one? #f]) 5325 (send (new menu-item% 5326 [label (string-constant recent-languages)] 5327 [callback void] 5328 [parent menu]) 5329 enable #f) 5330 (for-each 5331 (λ (name/settings) 5332 (let* ([name (car name/settings)] 5333 [marshalled-settings (cdr name/settings)] 5334 [lang (ormap 5335 (λ (l) (and (equal? (send l get-language-name) name) l)) 5336 (drracket:language-configuration:get-languages))]) 5337 (when lang 5338 ;; this test can fail when a language has been added wrongly via the tools interface 5339 ;; just ignore that menu item, in that case. 5340 (let ([settings (or (send lang unmarshall-settings marshalled-settings) 5341 (send lang default-settings))]) 5342 (when lang 5343 (set! added-one? #t) 5344 (new menu-item% 5345 [parent menu] 5346 [label (send lang get-language-name)] 5347 [callback 5348 (λ (x y) 5349 (send (send frame get-definitions-text) 5350 set-next-settings 5351 (drracket:language-configuration:language-settings 5352 lang 5353 settings)))])))))) 5354 (preferences:get 'drracket:recent-language-names)) 5355 (unless added-one? 5356 (send (new menu-item% 5357 [label (string-append 5358 " << " 5359 (string-constant no-recently-chosen-languages) 5360 " >>")] 5361 [parent menu] 5362 [callback void]) 5363 enable #f)) 5364 (new separator-menu-item% [parent menu])) 5365 (new menu-item% 5366 [label (string-constant choose-language-menu-item-label)] 5367 [parent menu] 5368 [callback 5369 (λ (x y) 5370 (send frame choose-language-callback))])) 5371 5372 (super-new [label ""] 5373 [font small-control-font] 5374 [string-constant-untitled (string-constant untitled)] 5375 [string-constant-no-full-name-since-not-saved 5376 (string-constant no-full-name-since-not-saved)]) 5377 5378 (inherit set-allow-shrinking) 5379 (set-allow-shrinking 50))) 5380 5381 5382 5383 ; 5384 ; 5385 ; 5386 ; 5387 ; ;;; ; 5388 ; ;;; ;;; 5389 ; ;;; ;; ;;; ;;; ;; ;;; ;;; ;; ;;;; ;;; ;; ;;; ;;; ;;;;; ;;;; 5390 ; ;;;;;;; ;;; ;;; ;;;;;;; ;;;;; ;; ;;; ;;;;;;; ;;;;; ;;;;;;;;; ;;; ;; 5391 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 5392 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;;;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;; 5393 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; 5394 ; ;;;;;;; ;;;;;;; ;;;;;;; ;;; ;;;;;; ;;;;;;; ;;;;; ;;; ;;;; ;; ;;; 5395 ; ;;; ;; ;; ;;; ;; ;;; ;;; ;;;; ;;; ;; ;;; ;;; ;;; ;;;; 5396 ; ;;; ;;; 5397 ; ;;;;;; ;;; 5398 ; 5399 ; 5400 5401 5402 ;; record-saved-bug-report : (listof (cons symbol string)) -> void 5403 ;; =Kernel= =Handler= 5404 (define (record-saved-bug-report table) 5405 (let ([recorded (preferences:get 'drracket:saved-bug-reports)]) 5406 (unless (member table recorded) 5407 (preferences:set 'drracket:saved-bug-reports (shorten-to (cons table recorded) 15))))) 5408 5409 ;; shorten-to : (listof X) number -> (listof X) 5410 ;; drops items from the end of the list to bring it back down to `n' items 5411 (define (shorten-to l n) 5412 (let loop ([l l] 5413 [n n]) 5414 (cond 5415 [(zero? n) '()] 5416 [(null? l) '()] 5417 [else (cons (car l) (loop (cdr l) (- n 1)))]))) 5418 5419 (define saved-bug-reports-window #f) 5420 (define saved-bug-reports-panel #f) 5421 (define (init-saved-bug-reports-window) 5422 (unless saved-bug-reports-window 5423 (let () 5424 (set! saved-bug-reports-window (new frame:basic% 5425 [label (string-constant drscheme)] 5426 [width 600])) 5427 (set! saved-bug-reports-panel 5428 (new-vertical-panel% [parent (send saved-bug-reports-window get-area-container)])) 5429 (define hp (new-horizontal-panel% 5430 [parent (send saved-bug-reports-window get-area-container)] 5431 [stretchable-width #f] 5432 [alignment '(right center)])) 5433 (define forget-all (new button% 5434 [label (string-constant bug-track-forget-all)] 5435 [callback 5436 (λ (_1 _2) 5437 (send saved-bug-reports-window show #f) 5438 (preferences:set 'drracket:saved-bug-reports '()))] 5439 [parent hp])) 5440 (void)))) 5441 5442 (preferences:add-callback 5443 'drracket:saved-bug-reports 5444 (λ (p v) 5445 (when saved-bug-reports-window 5446 (when (send saved-bug-reports-window is-shown?) 5447 (cond 5448 [(null? v) 5449 (send saved-bug-reports-window show #f)] 5450 [else 5451 (refresh-saved-bug-reports-window v)]))))) 5452 5453 (define (refresh-saved-bug-reports-window pref) 5454 (send saved-bug-reports-window begin-container-sequence) 5455 (send saved-bug-reports-panel change-children (λ (l) '())) 5456 (for-each 5457 (λ (item) 5458 (let () 5459 (define (lookup k [default ""]) 5460 (let loop ([item item]) 5461 (cond 5462 [(null? item) default] 5463 [else (let ([rib (car item)]) 5464 (if (eq? (car rib) k) 5465 (cdr rib) 5466 (loop (cdr item))))]))) 5467 (define vp 5468 (new-vertical-panel% 5469 [style '(border)] 5470 [parent saved-bug-reports-panel] 5471 [stretchable-height #f])) 5472 (define hp 5473 (new-horizontal-panel% 5474 [parent vp] 5475 [stretchable-height #f])) 5476 (define first-line-msg 5477 (let ([desc (lookup 'description #f)]) 5478 (and desc 5479 (new message% 5480 [label (read-line (open-input-string desc))] 5481 [parent vp] 5482 [stretchable-width #t] 5483 [font (send (send (editor:get-standard-style-list) find-named-style 5484 "Standard") 5485 get-font)])))) 5486 (define msg (new message% 5487 [stretchable-width #t] 5488 [label (string-append (lookup 'component "<<unknown component>>") 5489 (let ([v (lookup 'version #f)]) 5490 (if v 5491 (string-append " " v) 5492 "")))] 5493 [parent hp])) 5494 (define forget (new button% 5495 [parent hp] 5496 [callback (λ (x y) (forget-saved-bug-report item))] 5497 [label (string-constant bug-track-forget)])) 5498 (define report (new button% 5499 [parent hp] 5500 [callback (λ (x y) 5501 (forget-saved-bug-report item) 5502 (send-url 5503 (url->string 5504 (drracket:debug:bug-info->ticket-url item))))] 5505 [label (string-constant bug-track-report)])) 5506 (void))) 5507 pref) ;; reverse list so first elements end up on top of list 5508 (send saved-bug-reports-window reflow-container) 5509 (send saved-bug-reports-window end-container-sequence)) 5510 5511 (define (forget-saved-bug-report item) 5512 (preferences:set 'drracket:saved-bug-reports 5513 (remove item (preferences:get 'drracket:saved-bug-reports)))) 5514 5515 (define (show-saved-bug-reports-window) 5516 (init-saved-bug-reports-window) 5517 (unless (send saved-bug-reports-window is-shown?) 5518 (refresh-saved-bug-reports-window (preferences:get 'drracket:saved-bug-reports))) 5519 (send saved-bug-reports-window show #t)) 5520 5521 5522 5523 ; 5524 ; 5525 ; 5526 ; 5527 ; ;;;; ;; ; 5528 ; ;;; ; ; ; 5529 ; ;;;; ;;; ;;;;;;; ;;; ;; ;;; ;;;; ; ; ; 5530 ; ;;;; ;;;;;;;;;;;; ;;;;;;;;;;; ;; ;;; ; ; ; 5531 ; ;;; ;;; ;; ;;; ;;; ;;; ;;; ;;; ;;; ;; ;; ;; 5532 ; ;;; ;;; ;;;;; ;;; ;;; ;;; ;;;;;;; ; ; ; 5533 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ; ; ; 5534 ; ;;; ;;; ;;; ;;; ;;; ;;; ;;; ;;;;;; ; ; ; 5535 ; ;;; ;;; ;;;;;; ;;; ;;; ;;; ;;;; ; ;; 5536 ; 5537 ; 5538 ; 5539 ; 5540 5541 5542 (define -frame% 5543 (drracket:module-language:module-language-online-expand-frame-mixin 5544 (frame-mixin 5545 (drracket:frame:mixin 5546 (drracket:frame:basics-mixin 5547 (frame:size-pref-mixin 5548 (frame:searchable-text-mixin 5549 (frame:searchable-mixin 5550 (frame:text-info-mixin 5551 (frame:status-line-mixin 5552 (frame:info-mixin 5553 (frame:text-mixin 5554 (frame:editor-mixin 5555 (frame:standard-menus-mixin 5556 (frame:register-group-mixin 5557 (frame:focus-table-mixin 5558 (frame:basic-mixin 5559 frame%))))))))))))))))) 5560 5561 (define-local-member-name enable-two-way-prefs) 5562 (define (make-two-way-prefs-dragable-panel% % pref-key) 5563 (class % 5564 (inherit get-percentages) 5565 5566 (define save-prefs? #f) 5567 (define/public (enable-two-way-prefs) (set! save-prefs? #t)) 5568 5569 (define/augment (after-percentage-change) 5570 (when save-prefs? 5571 (let ([percentages (get-percentages)]) 5572 (when (and (pair? percentages) 5573 (pair? (cdr percentages)) 5574 (null? (cddr percentages))) 5575 (preferences:set pref-key (car percentages))))) 5576 (inner (void) after-percentage-change)) 5577 (super-new))) 5578 5579 (define drs-name-message% 5580 (class name-message% 5581 (define/override (on-choose-directory dir) 5582 (let ([file (finder:get-file dir 5583 (string-constant select-file) 5584 #f 5585 "" 5586 (send this get-top-level-window))]) 5587 (when file 5588 (handler:edit-file file)))) 5589 (super-new 5590 [string-constant-untitled (string-constant untitled)] 5591 [string-constant-no-full-name-since-not-saved 5592 (string-constant no-full-name-since-not-saved)]))) 5593 5594 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5595 ;; 5596 ;; lambda-snipclass is for backwards compatibility 5597 ;; 5598 (define lambda-snipclass 5599 (make-object (class snip-class% 5600 (define/override (read p) (make-object string-snip% "λ")) 5601 (super-new)))) 5602 (send lambda-snipclass set-version 1) 5603 (send lambda-snipclass set-classname "drscheme:lambda-snip%") 5604 (send (get-the-snip-class-list) add lambda-snipclass) 5605 5606 (define newest-frame 'nothing-yet) 5607 5608 (define (open-drscheme-window [name #f] #:show? [show? #t]) 5609 (cond 5610 [(and newest-frame 5611 name 5612 (not (equal? newest-frame 'nothing-yet)) 5613 (send newest-frame still-untouched?)) 5614 (send newest-frame change-to-file name) 5615 (when show? (send newest-frame show #t)) 5616 (begin0 newest-frame 5617 (set! newest-frame #f))] 5618 [(and name ;; only open a tab if we have a filename 5619 (preferences:get 'drracket:open-in-tabs)) 5620 (define frs (send (group:get-the-frame-group) get-frames)) 5621 (let ([ac (send (group:get-the-frame-group) get-active-frame)]) 5622 (when (and ac (send ac is-shown?)) 5623 (set! frs (cons ac (remove ac frs))))) 5624 (define fr (let loop ([frs frs]) 5625 (cond 5626 [(null? frs) #f] 5627 [else (let ([fr (car frs)]) 5628 (or (and (is-a? fr drracket:unit:frame<%>) 5629 fr) 5630 (loop (cdr frs))))]))) 5631 (cond 5632 [fr 5633 (send fr open-in-new-tab name) 5634 (when show? (send fr show #t)) 5635 fr] 5636 [else 5637 (create-new-drscheme-frame name #:show? show?)])] 5638 [else 5639 (create-new-drscheme-frame name #:show? show?)])) 5640 5641 (define (create-new-drscheme-frame filename #:show? [show? #t]) 5642 (let* ([drs-frame% (drracket:get/extend:get-unit-frame)] 5643 [frame (new drs-frame% (filename filename))]) 5644 (send frame update-toolbar-visibility) 5645 (send frame initialize-module-language) 5646 (when show? (send frame show #t)) 5647 (send (send frame get-interactions-text) initialize-console) 5648 frame))) 5649 5650(define/contract (compute-label-string fn) 5651 (-> (or/c path? #f) label-string?) 5652 (cond 5653 [fn 5654 (define base-title (format (string-constant module-browser-in-file) "")) 5655 (define str (path->string fn)) 5656 (define limit (- 200 (string-length base-title))) 5657 (define str-to-use 5658 (if (<= (string-length str) limit) 5659 str 5660 (string-append "..." 5661 (substring str 5662 (+ (- (string-length str) limit) 3) 5663 (string-length str))))) 5664 (format (string-constant module-browser-in-file) str-to-use)] 5665 [else (string-constant module-browser-no-file)])) 5666 5667 5668;; is-lang-line? : string -> boolean 5669;; given the first line in the editor, this returns #t if it is a #lang line. 5670(define (is-lang-line? l) 5671 (let ([m (regexp-match #rx"^#(!|(lang ))([-+_/a-zA-Z0-9]+)(.|$)" l)]) 5672 (and m 5673 (let ([lang-name (list-ref m 3)] 5674 [last-char (list-ref m 4)]) 5675 (and (not (char=? #\/ (string-ref lang-name 0))) 5676 (not (char=? #\/ (string-ref lang-name (- (string-length lang-name) 1)))) 5677 (or (string=? "" last-char) 5678 (char-whitespace? (string-ref last-char 0)))))))) 5679 5680(module+ test 5681 (require rackunit) 5682 (check-equal? (compute-label-string (string->path "x")) 5683 (format (string-constant module-browser-in-file) "x")) 5684 (check-equal? (compute-label-string #f) 5685 (string-constant module-browser-no-file)) 5686 (check-equal? (string-length (compute-label-string (string->path (make-string 200 #\x)))) 5687 200) 5688 (for ([i (in-range 100 300)]) 5689 (let/ec k 5690 (parameterize ([error-escape-handler k]) 5691 (check-true (string? 5692 (compute-label-string 5693 (string->path (make-string i #\x)))))))) 5694 5695 5696 (check-true (is-lang-line? "#lang x")) 5697 (check-true (is-lang-line? "#lang racket")) 5698 (check-true (is-lang-line? "#lang racket ")) 5699 (check-false (is-lang-line? "#lang racketα")) 5700 (check-false (is-lang-line? "#lang racket/ ")) 5701 (check-false (is-lang-line? "#lang /racket ")) 5702 (check-true (is-lang-line? "#lang rac/ket ")) 5703 (check-true (is-lang-line? "#lang r6rs")) 5704 (check-true (is-lang-line? "#!r6rs")) 5705 (check-true (is-lang-line? "#!r6rs ")) 5706 (check-false (is-lang-line? "#!/bin/sh"))) 5707