1# File: recall.tcl 2 3# Purpose: the Recall Window and related commands 4 5# 6# Copyright (c) 1997-2001 Tim Baker 7# 8# This software may be copied and distributed for educational, research, and 9# not for profit purposes provided that this copyright and statement are 10# included in all such copies. 11# 12 13namespace eval NSRecall { 14 15 variable Priv 16 17# namespace eval NSRecall 18} 19 20# NSRecall::InitModule -- 21# 22# One-time-only-ever initialization. 23# 24# Arguments: 25# arg1 about arg1 26# 27# Results: 28# What happened. 29 30proc NSRecall::InitModule {} { 31 32 variable Priv 33 34 set Priv(icon,valid) 0 35 set Priv(icon,known) 0 36 37 set oop [NSObject::New NSRecall] 38 39 # Update ourself when the font for the Recall Window changes 40 NSValueManager::AddClient font,recall \ 41 "NSRecall::ValueChanged_font_recall $oop" 42 43 return 44} 45 46# NSRecall::NSRecall -- 47# 48# Object constructor called by NSObject::New(). 49# 50# Arguments: 51# oop OOP ID. See above. 52# 53# Results: 54# What happened. 55 56proc NSRecall::NSRecall {oop} { 57 58 Info $oop showIcon [Value recall,showicon] 59 60 InitWindow $oop 61 62 set win [Info $oop win] 63 64 NSWindowManager::RegisterWindow recall $win \ 65 "NSRecall::GeometryCmd $oop" \ 66 "" \ 67 "NSRecall::DisplayCmd $oop" 68 69 # If the Choice Window is displayed, we don't show choices in 70 # the Recall Window. 71 Info $oop clientId,choicewindow \ 72 [NSValueManager::AddClient choicewindow,show { 73 NSRecall::SetHook [Global recall,oop] "" 74 }] 75 76 if {$::DEBUG} { 77 set ::debug_display 0 78 } 79 80 Info $oop hook "" 81 Info $oop busy 0 82 Info $oop expanded 0 83 Info $oop current "" 84 Info $oop inConfigure 0 85 86 # Kind of information currently displayed 87 Info $oop display "" 88 89Info $oop monsterMem "" 90 91 # 92 # Global list of application windows 93 # 94 95 Global recall,oop $oop 96 Window recall $win 97 98 return 99} 100 101# NSRecall::Info -- 102# 103# Query and modify info. 104# 105# Arguments: 106# arg1 about arg1 107# 108# Results: 109# What happened. 110 111proc NSRecall::Info {oop info args} { 112 113 global NSRecall 114 115 # Verify the object 116 NSObject::CheckObject NSRecall $oop 117 118 # Set info 119 if {[llength $args]} { 120 switch -- $info { 121 default { 122 set NSRecall($oop,$info) [lindex $args 0] 123 } 124 } 125 126 # Get info 127 } else { 128 switch -- $info { 129 default { 130 return $NSRecall($oop,$info) 131 } 132 } 133 } 134 135 return 136} 137 138# NSRecall::InitWindow -- 139# 140# Create a recall window. 141# 142# Arguments: 143# oop OOP ID. See above. 144# 145# Results: 146# What happened. 147 148proc NSRecall::InitWindow {oop} { 149 150 set win .recall$oop 151 toplevel $win 152 wm title $win "Recall" 153 154 wm transient $win [Window main] 155 156 # Feed the Term when keys are pressed 157 Term_KeyPress_Bind $win 158 159 # Do stuff when window closes 160 wm protocol $win WM_DELETE_WINDOW "NSRecall::Close $oop" 161 162 # Start out withdrawn (hidden) 163 wm withdraw $win 164 165 # Turn off geometry propagation for the window 166 pack propagate $win no 167 168 # Set instance variables 169 Info $oop win $win 170 171 set frame $win.frame 172 frame $frame -relief sunken -borderwidth 1 -background Black 173 174 # Canvas to display icon 175 set iconSize [expr {[icon size] + 8}] 176 set canvas $frame.icon 177 canvas $canvas \ 178 -borderwidth 0 -width $iconSize -height $iconSize -background Black \ 179 -highlightthickness 0 180if 0 { 181 $canvas create widget \ 182 6 6 -tags icon 183} 184 $canvas create rectangle \ 185 4 4 [expr {6 + [icon size] + 1}] [expr {6 + [icon size] + 1}] \ 186 -outline Black -tags focus 187if 0 { 188# Problems with highlight when Knowledge window appears, so skip it 189 $canvas bind icon <Enter> { 190# %W itemconfigure focus -outline gray60 191 } 192 $canvas bind icon <Leave> { 193 %W itemconfigure focus -outline Black 194 } 195 $canvas bind icon <ButtonPress-1> " 196 $canvas move icon 1 1 197 set CanvasButtonDown 1 198 " 199 $canvas bind icon <Button1-Enter> " 200 $canvas move icon 1 1 201 set CanvasButtonDown 1 202 " 203 $canvas bind icon <Button1-Leave> " 204 $canvas move icon -1 -1 205 set CanvasButtonDown 0 206 " 207 $canvas bind icon <ButtonRelease-1> " 208 if {\$CanvasButtonDown} { 209 $canvas move icon -1 -1 210 update idletasks 211 NSRecall::DisplayKnowledge $oop 212 } 213 " 214} 215 # Create an arrow which appears when there is content out of site 216 set x [expr {$iconSize / 2}] 217 $canvas create polygon [expr {$x - 3}] 46 [expr {$x + 3}] 46 \ 218 $x 49 -fill Red -outline Red -tags arrow 219 220 set wrap word 221 text $frame.text \ 222 -wrap $wrap -width 1 -height 1 -font [Value font,recall] \ 223 -borderwidth 0 -setgrid no -highlightthickness 0 \ 224 -padx 4 -pady 2 -background Black -foreground White -cursor "" 225 bindtags $frame.text [list $frame.text $win all] 226 227 pack $frame \ 228 -expand yes -fill both 229 230 grid rowconfig $frame 0 -weight 1 231 grid columnconfig $frame 0 -weight 0 232 grid columnconfig $frame 1 -weight 1 233 234 grid $frame.icon -in $frame \ 235 -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky ns 236 grid $frame.text -in $frame \ 237 -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news 238 239 if {![Info $oop showIcon]} { 240 grid remove $frame.icon 241 } 242 243 # Set instance variables 244 Info $oop icon $frame.icon 245 Info $oop text $frame.text 246 247 # Window expands and contracts as the mouse enters and leaves it 248 bindtags $win [concat [bindtags $win] RecallBindTag] 249 bind RecallBindTag <Enter> "NSRecall::Expand $oop" 250 bind RecallBindTag <Leave> "NSRecall::Contract $oop" 251 252 # When the window changes size, reposition the indicator arrow 253 bind $frame.text <Configure> \ 254 "NSRecall::Configure $oop" 255 256 # Fiddle with the selection for list behaviour 257 $frame.text tag configure HOT -foreground White \ 258 -background [Value listHilite] 259 260 $frame.text tag bind HOT <ButtonPress-1> \ 261 "NSRecall::Invoke $oop \[$frame.text index {@%x,%y linestart}]" 262 $frame.text tag bind TEXT <Motion> \ 263 "NSRecall::Motion $oop \[$frame.text index {@%x,%y linestart}]" 264 $frame.text tag bind HOT <Leave> \ 265 "NSRecall::Motion $oop {}" 266 267 if {[Platform unix]} { 268 269 # When the inactive window is clicked, I get a <Leave> event 270 # followed by an <Enter> event. The <Leave> Contract()'s the window 271 # and removes the highlight (if any). 272 273 bind RecallWindowBindTag <Leave> " 274 if {!\[NSRecall::HasCursor $oop]} { 275 NSRecall::Contract $oop 276 } 277 " 278 $frame.text tag bind HOT <Leave> " 279 if {!\[NSRecall::CursorHot $oop %x %y]} { 280 NSRecall::Motion $oop {} 281 } 282 " 283 bind $win <Leave> " 284 if {!\[NSRecall::HasCursor $oop]} { 285 NSRecall::Motion $oop {} 286 } 287 " 288 289 proc CursorHot {oop x y} { 290 set text [Info $oop text] 291 if {![llength [$text tag ranges HOT]]} {return 0} 292 set index [$text index @$x,$y] 293 if {[$text compare $index < HOT.first] || 294 [$text compare $index > HOT.last]} {return 0} 295 return 1 296 } 297 } 298 299 # 300 # Context Menu 301 # 302 303 set menu $win.context 304 menu $menu -tearoff 0 305 bind $frame.icon <ButtonPress-3> \ 306 "NSRecall::ContextMenu $oop $menu %X %Y" 307 bind $frame.text <ButtonPress-3> \ 308 "NSRecall::ContextMenu $oop $menu %X %Y" 309 310 return 311} 312 313# NSRecall::DisplayCmd -- 314# 315# Called by NSWindowManager::Display(). 316# 317# Arguments: 318# arg1 about arg1 319# 320# Results: 321# What happened. 322 323proc NSRecall::DisplayCmd {oop message first args} { 324 325 switch -- $message { 326 preDisplay { 327 } 328 postDisplay { 329 Value recall,show 1 330 } 331 postWithdraw { 332 SetHook $oop "" 333 Value recall,show 0 334 } 335 } 336 337 return 338} 339 340# NSRecall::GeometryCmd -- 341# 342# Called by NSWindowManager::Setup(). Returns the desired (default) 343# geometry for the window. 344# 345# Arguments: 346# arg1 about arg1 347# 348# Results: 349# What happened. 350 351proc NSRecall::GeometryCmd {oop} { 352 353 set win [Info $oop win] 354 set winMain [Window main] 355 set spacing 0 356 357 set left 0 358 set top 0 359 set right [winfo screenwidth .] 360 set bottom [winfo screenheight .] 361 362 set x [NSToplevel::FrameLeft $winMain] 363 if {[Value choicewindow,show]} { 364 set width [NSToplevel::ContentWidth $win \ 365 [expr {[NSToplevel::TotalWidth $winMain] / 2}]] 366 } else { 367 set width [NSToplevel::TotalWidth $winMain] 368 if {$width > 400} { 369 set width 400 370 } 371 set width [NSToplevel::ContentWidth $win $width] 372 } 373 374 set y [expr {[NSToplevel::FrameBottom $winMain] + $spacing}] 375 if {$bottom - $y < 100} { 376 set y [expr {$bottom - 100}] 377 set height [NSToplevel::ContentHeight $win 100] 378 } elseif {($y + [NSToplevel::TotalHeight $win]) < $bottom} { 379 set height [winfo height $win] 380 } else { 381 set height [expr {$bottom - [NSToplevel::FrameBottom $winMain]}] 382 set height [NSToplevel::ContentHeight $win $height] 383 } 384 385 return ${width}x$height+$x+$y 386} 387 388# NSRecall::Close -- 389# 390# Description. 391# 392# Arguments: 393# oop OOP ID. See above. 394# 395# Results: 396# What happened. 397 398proc NSRecall::Close {oop} { 399 400 NSWindowManager::Undisplay recall 401 402 return 403} 404 405 406 407# NSRecall::RecallSpell -- 408# 409# Show info about a spell. 410# 411# Arguments: 412# arg1 about arg1 413# 414# Results: 415# What happened. 416 417proc NSRecall::RecallSpell {bookNum index} { 418 419 variable Priv 420 421 if {![Value recall,show]} return 422 423 # Hack -- Get the object id 424 set oop [Global recall,oop] 425 426 # If we are in "list mode", don't clobber the text 427 if {[string length [Info $oop hook]]} return 428 429 # Get information about the spell 430 angband spell info $bookNum $index attrib 431 432 # Get the book icon 433 set icon [angband k_info info $bookNum icon] 434 435 # Color 436 switch -- $attrib(info) { 437 unknown { 438 set color gray70 439 440 # The character can learn this spell 441 if {[angband player new_spells] && 442 ($attrib(level) <= [angband player level])} { 443 set color [Value TERM_L_GREEN] 444 } 445 } 446 untried { 447 set color [Value TERM_L_BLUE] 448 } 449 default { 450 set color White 451 } 452 } 453 454 # Get the name 455 set name $attrib(name): 456 457 # Get the memory 458 set memory [angband spell memory $bookNum $index] 459 460 # Extra info 461 if {[string length $memory]} { 462 append memory \n 463 } 464 append memory "Level $attrib(level) Mana $attrib(mana) \ 465 Fail $attrib(chance)%" 466 if {[string length $attrib(info)]} { 467 append memory "\n$attrib(info)" 468 } 469 470 # Set the text 471 SetText $oop $icon $color $name $memory 472 473 return 474} 475 476 477# NSRecall::SetText -- 478# 479# Description. 480# 481# Arguments: 482# oop OOP ID. See above. 483# 484# Results: 485# What happened. 486 487proc NSRecall::SetText {oop icon color title text} { 488 489 global NSRecall 490 variable Priv 491 492 set win [Info $oop win] 493 set textBox [Info $oop text] 494 495 # If we are in "list mode", then do not set the text. This may 496 # happen if we are waiting for an object to be chosen, and the 497 # user highlights an object in the Inventory Window, which would 498 # ordinarily display the object memory. 499 if {[string length [Info $oop hook]]} { 500 return 501 } 502 503 # Display the icon 504 [Info $oop icon] itemconfigure icon -assign $icon 505 506 # Delete 507 $textBox delete 1.0 end 508 509 # Insert title if any 510 if {[string length $title]} { 511 512 # Title (color?) 513 $textBox insert end $title\n 514 $textBox tag add TAG_STYLE 1.0 {end -1 chars} 515 $textBox tag configure TAG_STYLE -foreground $color 516 } 517 518 # Insert text if any 519 set text [string trim $text] 520 if {[string length $text]} { 521 522 # Text 523 $textBox insert end $text 524 } 525 526 set Priv(icon,valid) 0 527 528 # Synchronize the indicator arrow 529 ContentChanged $oop 530 531 return 532} 533 534# NSRecall::IconChanged -- 535# 536# The icon of the recalled monster/object is displayed in the 537# Recall Window. If that monster or object is assigned a different 538# icon, we want to update the display. This is called as a 539# qebind command on the "Assign" quasi-event. 540# 541# Arguments: 542# oop OOP ID. See above. 543# 544# Results: 545# What happened. 546 547proc NSRecall::IconChanged {oop to toindex assign} { 548 549 variable Priv 550 551 if {!$Priv(icon,valid)} return 552 if {[string equal $to $Priv(icon,to)] && ($toindex == $Priv(icon,toindex))} { 553 [Info $oop icon] itemconfigure icon -assign $assign 554 } 555 556 return 557} 558 559 560# NSRecall::DisplayKnowledge -- 561# 562# Display the Knowledge Window for the displayed monster or object. 563# 564# Arguments: 565# arg1 about arg1 566# 567# Results: 568# What happened. 569 570proc NSRecall::DisplayKnowledge {oop} { 571 572 variable Priv 573 574 if {!$Priv(icon,valid)} return 575 576 # This can't work when an unknown flavored object is displayed 577 if {!$Priv(icon,known)} return 578 579 if {[string compare $Priv(icon,to) monster] && 580 [string compare $Priv(icon,to) object]} { 581 return 582 } 583 584 angband_display knowledge show $Priv(icon,to) $Priv(icon,toindex) 585 586 return 587} 588 589 590# NSRecall::SetHook -- 591# 592# Set the hook. 593# 594# Arguments: 595# arg1 about arg1 596# 597# Results: 598# What happened. 599 600proc NSRecall::SetHook {oop hook} { 601 602 if {[string length $hook]} { 603 Info $oop hook NSRecall::$hook 604 CallHook $oop open 605 if {$::DEBUG} { 606 set ::debug_display 1 607 } 608 } elseif {[string length [Info $oop hook]]} { 609 Info $oop hook "" 610 Restore $oop 611 if {$::DEBUG} { 612 set ::debug_display 0 613 } 614 } 615 616 return 617} 618 619# NSRecall::CallHook -- 620# 621# Call the hook. 622# 623# Arguments: 624# arg1 about arg1 625# 626# Results: 627# What happened. 628 629proc NSRecall::CallHook {oop message args} { 630 631 return [uplevel #0 [Info $oop hook] $oop $message $args] 632} 633 634# NSRecall::Fresh_Display -- 635# 636# Calls the hook to set the list, if required. Called as a command 637# on the "Term-fresh" quasi-event. 638# 639# Arguments: 640# arg1 about arg1 641# 642# Results: 643# What happened. 644 645proc NSRecall::Fresh_Display {oop} { 646 647 ASSERT {$::debug_display == 1} \ 648 "Fresh_Display called with debug_display=0!" 649 650 CallHook $oop fresh 651 652 # If the cursor is inside the Recall Window, we will attempt to 653 # expand it. 654 set pointerx [winfo pointerx .] 655 set pointery [winfo pointery .] 656 set toplevel [winfo containing $pointerx $pointery] 657 if {[string length $toplevel] && \ 658 [string equal [winfo toplevel $toplevel] [Info $oop win]]} { 659 Expand $oop 660 } 661 662 return 663} 664 665# NSRecall::SetList -- 666# 667# Clears the recall text, sets the icon to "none 0" and calls the 668# hook to set the text. 669# 670# Arguments: 671# arg1 about arg1 672# 673# Results: 674# What happened. 675 676proc NSRecall::SetList {oop} { 677 678 set win [Info $oop win] 679 set textBox [Info $oop text] 680 681 # Clear the text 682 $textBox delete 1.0 end 683 684 # Clear the icon 685 [Info $oop icon] itemconfigure icon -assign {icon none 0} 686 687 # Call the hook to set the list 688 CallHook $oop set_list 689 690 # Something is displayed 691 Info $oop display something 692 693 # No item is highlighted 694 Info $oop current "" 695 696 # Synchronize the indicator arrow 697 ContentChanged $oop 698 699 return 700} 701 702# NSRecall::Invoke -- 703# 704# Called when a list item is clicked. 705# 706# Arguments: 707# arg1 about arg1 708# 709# Results: 710# What happened. 711 712proc NSRecall::Invoke {oop index} { 713 714 set textBox [Info $oop text] 715set index [Info $oop current] 716 set row [expr {[lindex [split $index .] 0] - 1}] 717 718 CallHook $oop invoke $row 719 720 return 721} 722 723# NSRecall::Motion -- 724# 725# Called when the mouse moves in a list item. 726# 727# Arguments: 728# arg1 about arg1 729# 730# Results: 731# What happened. 732 733proc NSRecall::Motion {oop index} { 734 735 # If you invoke an item, hold down the mouse, and drag... 736 if {![string length [Info $oop hook]]} return 737 738 # No tracking while menu is up 739 if {[Info $oop busy]} return 740 741 # See if the item has changed 742 if {$index == [Info $oop current]} return 743 744 # An item is highlighted 745 if {[string length [Info $oop current]]} { 746 747 # Remove highlighting 748 UnhighlightItem $oop [Info $oop current] 749 } 750 751 # An item is under the pointer 752 if {[string length $index]} { 753 754 # Highlight the item 755 HighlightItem $oop $index 756 } 757 758 # Remember which item is highlighted 759 Info $oop current $index 760 761 return 762} 763 764# NSRecall::HighlightItem -- 765# 766# Highlights a list item. 767# 768# Arguments: 769# arg1 about arg1 770# 771# Results: 772# What happened. 773 774proc NSRecall::HighlightItem {oop index} { 775 776 set textBox [Info $oop text] 777 set row [expr {[lindex [split $index .] 0] - 1}] 778 779 # Highlight the item 780 $textBox tag add HOT $index "$index lineend" 781 $textBox tag raise HOT 782 783 # Call the hook (to set the icon, for example) 784 CallHook $oop highlight $row 785 786 return 787} 788 789# NSRecall::UnhighlightItem -- 790# 791# Removes highlighting from a list item. 792# 793# Arguments: 794# arg1 about arg1 795# 796# Results: 797# What happened. 798 799proc NSRecall::UnhighlightItem {oop index} { 800 801 set win [Info $oop win] 802 set textBox [Info $oop text] 803 804 # Unhighlight the item 805 $textBox tag remove HOT 1.0 end 806 807 # Clear the icon 808 [Info $oop icon] itemconfigure icon -assign {icon none 0} 809 810 return 811} 812 813# NSRecall::HasCursor -- 814# 815# See if the cursor is over the window. 816# 817# Arguments: 818# arg1 about arg1 819# 820# Results: 821# What happened. 822 823proc NSRecall::HasCursor {oop} { 824 825 set pointerx [winfo pointerx .] 826 set pointery [winfo pointery .] 827 set window [winfo containing $pointerx $pointery] 828 if {![string length $window]} { 829 return 0 830 } 831 if {[string compare [winfo toplevel $window] [Info $oop win]]} { 832 return 0 833 } 834 return 1 835} 836 837# NSRecall::Expand -- 838# 839# Resizes the Recall Window to display all of the information in it. 840# Does nothing if the window is already expanded. 841# 842# Arguments: 843# arg1 about arg1 844# 845# Results: 846# What happened. 847 848proc NSRecall::Expand {oop} { 849 850 variable Priv 851 852# if {![string length [Info $oop hook]]} return 853 if {[Info $oop busy]} return 854 if {[Info $oop expanded]} return 855 856 set win [Info $oop win] 857 set textBox [Info $oop text] 858 859 set textHeight [winfo height $textBox] 860 set lineHeight [font metrics [Value font,recall] -linespace] 861 862 # Hack -- In order to find out how much space is taken up by the 863 # text in the text widget, I create a canvas text item with the 864 # proper attributes and calculate its size. The width is width-8 865 # and height-4 because of the internal padding of the text 866 # widget. I added 2 to each adjustment as a hack. 867 set padx [$textBox cget -padx] 868 set pady [$textBox cget -pady] 869 set itemId [[Info $oop icon] create text 1 1 -font [Value font,recall] \ 870 -width [expr {[winfo width $textBox] - $padx * 2 - 1}] -anchor nw \ 871 -text [$textBox get 1.0 end]] 872 set bbox [[Info $oop icon] bbox $itemId] 873 set height [expr {[lindex $bbox 3] - [lindex $bbox 1] + $pady * 2 + 2}] 874 875 # Hmmm... Is there a trailing newline, or what? 876 incr height -$lineHeight 877 878 # Delete the temp canvas item 879 [Info $oop icon] delete $itemId 880 881 set winHeight [winfo height $win] 882 set winWidth [winfo width $win] 883 884 if {$height <= $winHeight} return 885 886 # If the window is closer to the top of the screen, then 887 # expand downwards, otherwise expand upwards. 888 set top [NSToplevel::FrameTop $win] 889 set topDist $top 890 if {$topDist < 0} {set topDist 0} 891 set bottom [NSToplevel::FrameBottom $win] 892 set bottomDist [expr {[winfo screenheight $win] - $bottom}] 893 if {$bottomDist < 0} {set bottomDist 0} 894 if {$topDist < $bottomDist} { 895 set expandUp 0 896 } else { 897 set expandUp 1 898 } 899 900 # Save the current window geometry 901 Info $oop geometry [wm geometry $win] 902 903 Info $oop busy 1 904 905 raise $win 906 set x [NSToplevel::FrameLeft $win] 907 if {$expandUp} { 908 set y [expr {[NSToplevel::FrameTop $win] - ($height - $winHeight)}] 909 } else { 910 set y [NSToplevel::FrameTop $win] 911 } 912 wm geometry $win ${winWidth}x$height+$x+$y 913 update 914 915 Info $oop expanded 1 916 Info $oop busy 0 917 918 # If the cursor moved outside the Recall Window, collapse it 919 if {![HasCursor $oop]} { 920 Contract $oop 921 } 922 923 return 924} 925 926# NSRecall::Contract -- 927# 928# Restores the window geometry to the size it was before it was 929# expanded. Does nothing if the window is not expanded. 930# 931# Arguments: 932# arg1 about arg1 933# 934# Results: 935# What happened. 936 937proc NSRecall::Contract {oop} { 938 939 if {[Info $oop busy]} return 940 if {![Info $oop expanded]} return 941 942 Info $oop busy 1 943 944 set win [Info $oop win] 945 wm geometry $win [Info $oop geometry] 946 update 947 948 Info $oop expanded 0 949 Info $oop busy 0 950 951 return 952} 953 954# NSRecall::Restore -- 955# 956# Description. 957# 958# Arguments: 959# arg1 about arg1 960# 961# Results: 962# What happened. 963 964proc NSRecall::Restore {oop} { 965 966 if {![string length [Info $oop display]]} return 967 SetText $oop {icon none 0} {} {} {} 968 Contract $oop 969 Info $oop display "" 970 971 return 972} 973 974# NSRecall::ContextMenu -- 975# 976# When the window is right-clicked, pop up a menu of options. 977# 978# Arguments: 979# arg1 about arg1 980# 981# Results: 982# What happened. 983 984proc NSRecall::ContextMenu {oop menu x y} { 985 986 set text [Info $oop text] 987 988 $menu delete 0 end 989 990 $menu add command -label "Set Font" \ 991 -command "NSModule::LoadIfNeeded NSFont ; NSWindowManager::Display font recall" 992 $menu add checkbutton -label "Show Icon" \ 993 -variable ::NSRecall($oop,showIcon) \ 994 -command "NSRecall::OptionChanged $oop showIcon showicon" 995 $menu add separator 996 $menu add command -label "Cancel" 997 998 # Hack -- Try to prevent collapsing while popup is visible. 999 # It would be nice if "winfo ismapped $menu" worked 1000 Info $oop busy 1 1001 1002 # Pop up the menu 1003 tk_popup $menu $x $y 1004 1005 if {[Platform unix]} { 1006 tkwait variable ::tkPriv(popup) 1007 } 1008 1009 Info $oop busy 0 1010 1011 set index "" 1012 if {[NSUtils::HasCursor $text]} { 1013 set x [expr {[winfo pointerx $text] - [winfo rootx $text]}] 1014 set y [expr {[winfo pointery $text] - [winfo rooty $text]}] 1015 set index2 [$text index @$x,$y] 1016 foreach tag [$text tag names $index2] { 1017 if {[string equal $tag TEXT]} { 1018 set index "$index2 linestart" 1019 break 1020 } 1021 } 1022 } 1023 Motion $oop $index 1024 1025 return 1026} 1027 1028# NSRecall::OptionChanged -- 1029# 1030# Description. 1031# 1032# Arguments: 1033# arg1 about arg1 1034# 1035# Results: 1036# What happened. 1037 1038proc NSRecall::OptionChanged {oop info keyword} { 1039 1040 set setting [Info $oop $info] 1041 Value recall,$keyword $setting 1042 switch -- $keyword { 1043 showicon { 1044 if {$setting} { 1045 grid [Info $oop icon] 1046 } else { 1047 grid remove [Info $oop icon] 1048 } 1049 } 1050 } 1051 1052 return 1053} 1054 1055# NSRecall::Configure -- 1056# 1057# Called as a <Configure> event script. Positions the indicator 1058# arrow (the one which tells us if there is more information out 1059# of site) near the bottom of the window. 1060# 1061# Arguments: 1062# arg1 about arg1 1063# 1064# Results: 1065# What happened. 1066 1067proc NSRecall::Configure {oop} { 1068 1069 set win [Info $oop win] 1070 set canvas [Info $oop icon] 1071 set text [Info $oop text] 1072 1073 scan [$canvas bbox arrow] "%s %s %s %s" left top right bottom 1074 set height [winfo height $text] 1075 $canvas move arrow 0 [expr {$height - $bottom - 4}] 1076 1077 ContentChanged $oop 1078 1079 return 1080} 1081 1082# NSRecall::ContentChanged -- 1083# 1084# Called when the information displayed has changed. 1085# 1086# Arguments: 1087# arg1 about arg1 1088# 1089# Results: 1090# What happened. 1091 1092proc NSRecall::ContentChanged {oop} { 1093 1094 set win [Info $oop win] 1095 set canvas [Info $oop icon] 1096 set text [Info $oop text] 1097 1098 scan [$text yview] "%f %f" top bottom 1099 if {$bottom < 1} { 1100 set fill Red 1101 } else { 1102 set fill [$canvas cget -background] 1103 } 1104 1105 $canvas itemconfigure arrow -fill $fill -outline $fill 1106 1107 return 1108} 1109 1110# NSRecall::Choose -- 1111# 1112# Handle <Choose> quasi-event. 1113# 1114# Arguments: 1115# arg1 about arg1 1116# 1117# Results: 1118# What happened. 1119 1120proc NSRecall::Choose {oop what show args} { 1121 1122 if {[lsearch -exact [list cmd_pet ele_attack item] \ 1123 $what] == -1} return 1124 1125 if {!$show} { 1126 SetHook $oop {} 1127 return 1128 } 1129 1130 switch -- $what { 1131 cmd_pet { 1132 SetHook $oop hook_cmd_pet 1133 } 1134 ele_attack { 1135 SetHook $oop hook_ele_attack 1136 } 1137 } 1138 1139 return 1140} 1141 1142 1143proc NSRecall::MenuSelect {menu hook} { 1144 1145 set index [$menu index active] 1146 eval $hook [Global recall,oop] menu_select $menu $index 1147 1148 return 1149} 1150 1151 1152proc NSRecall::PetCmdInfo {_mode} { 1153 1154 upvar $_mode mode 1155 1156 set letters abcdefgh 1157 set index -1 1158 1159 if {[llength [angband player pets]]} { 1160 set char [string index $letters [incr index]] 1161 lappend data $char "Dismiss pets" 1162 } 1163 1164# set dist [struct set player_type 0 pet_follow_distance] 1165 set mode "" 1166 1167 set char [string index $letters [incr index]] 1168 lappend data $char "Stay close" 1169 if {$dist == [const PET_CLOSE_DIST]} { 1170 set mode $char 1171 } 1172 set char [string index $letters [incr index]] 1173 lappend data $char "Follow me" 1174 if {$dist == [const PET_FOLLOW_DIST]} { 1175 set mode $char 1176 } 1177 set char [string index $letters [incr index]] 1178 lappend data $char "Seek and destroy" 1179 if {$dist == [const PET_DESTROY_DIST]} { 1180 set mode $char 1181 } 1182 set char [string index $letters [incr index]] 1183 lappend data $char "Give me space" 1184 if {$dist == [const PET_SPACE_DIST]} { 1185 set mode $char 1186 } 1187 set char [string index $letters [incr index]] 1188 lappend data $char "Stay away"] if {$dist == [const PET_AWAY_DIST]} { 1189 set mode $char 1190 } 1191 1192 set char [string index $letters [incr index]] 1193 lappend data $char "Allow open doors" 1194 1195 set char [string index $letters [incr index]] 1196 lappend data $char "Allow pickup items" 1197 1198 return $data 1199} 1200 1201proc NSRecall::hook_cmd_pet {oop message args} { 1202 1203 switch -- $message { 1204 1205 open { 1206 } 1207 1208 fresh { 1209 SetList $oop 1210 } 1211 1212 close { 1213 } 1214 1215 set_list { 1216 1217 set textBox [Info $oop text] 1218 1219 # Keep a list of invoke chars 1220 set match {} 1221 1222 # Process each command 1223 foreach {char label} [PetCmdInfo mode] { 1224 1225 if {[string equal $char $mode]} { 1226 set color [Value TERM_L_BLUE] 1227 } else { 1228 set color White 1229 } 1230 1231 # Append the character and description 1232 $textBox insert end "$char\) " TEXT $label \ 1233 [list ITEM_$char TEXT] "\n" 1234 $textBox tag configure ITEM_$char -foreground $color 1235 1236 # Keep a list of chars and colors 1237 lappend match $char 1238 lappend colors $color 1239 } 1240 1241 # Delete trailing newline 1242 $textBox delete "end - 1 chars" 1243 1244 # Keep a list of chars and colors 1245 Info $oop match $match 1246 Info $oop color $colors 1247 } 1248 1249 get_color { 1250 set row [lindex $args 0] 1251 return [lindex [Info $oop color] $row] 1252 } 1253 1254 invoke { 1255 set row [lindex $args 0] 1256 set char [lindex [Info $oop match] $row] 1257 angband keypress $char 1258 } 1259 1260 highlight { 1261 } 1262 } 1263 1264 return 1265} 1266 1267# NSRecall::PopupSelect_CmdPet -- 1268# 1269# Show a pop-up menu of pet commands. 1270# 1271# Arguments: 1272# arg1 about arg1 1273# 1274# Results: 1275# What happened. 1276 1277proc NSRecall::PopupSelect_CmdPet {menu x y} { 1278 1279 global PopupResult 1280 1281 set PopupResult 0 1282 1283 # Clear the menu 1284 $menu delete 0 end 1285 1286 set num 0 1287 foreach {char name} [PetCmdInfo mode] { 1288 1289 if {[string equal $char $mode]} { 1290 set ::PopupCheck 1 1291 $menu add checkbutton -label "$char $name" \ 1292 -command "angband keypress $char ; set PopupResult 1" \ 1293 -underline 0 -variable ::PopupCheck 1294 } else { 1295 $menu add command -label "$char $name" \ 1296 -command "angband keypress $char ; set PopupResult 1" \ 1297 -underline 0 1298 } 1299 1300 incr num 1301 } 1302 1303 $menu add separator 1304 $menu add command -label "Cancel" 1305 1306 # Pressing and holding Button-3, popping up, then letting go selects 1307 # an item, so wait a bit if it was a quick press-release 1308 after 100 1309 1310 tk_popup $menu $x $y [expr {$num / 2}] 1311 1312 if {[Platform unix]} { 1313 tkwait variable ::tkPriv(popup) 1314 } 1315 1316 # If the user unposts the menu without choosing an entry, then 1317 # I want to feed Escape into the Term. I tried binding to the <Unmap> 1318 # event but it isn't called on Windows(TM). 1319 after idle { 1320 if {!$PopupResult} { 1321 angband keypress \033 1322 } 1323 } 1324 1325 return 1326} 1327 1328 1329proc NSRecall::hook_xxx {oop message args} { 1330 1331 switch -- $message { 1332 1333 set_list { 1334 } 1335 1336 get_color { 1337 } 1338 } 1339 1340 return 1341} 1342 1343# NSRecall::ValueChanged_font_recall -- 1344# 1345# Called when the font,recall value changes. 1346# Updates the Recall Window. 1347# 1348# Arguments: 1349# arg1 about arg1 1350# 1351# Results: 1352# What happened. 1353 1354proc NSRecall::ValueChanged_font_recall {oop} { 1355 1356 [Info $oop text] configure -font [Value font,recall] 1357 1358 return 1359} 1360