1# File: autobar.tcl 2 3# Purpose: the Autobar display 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 NSAutobar { 14 15# namespace eval NSAutobar 16} 17 18# NSAutobar::InitModule -- 19# 20# One-time-only-ever initialization. 21# 22# Arguments: 23# arg1 about arg1 24# 25# Results: 26# What happened. 27 28proc NSAutobar::InitModule {} { 29 30 InitImageIfNeeded Image_ButtonActivate button-activate.gif 31 InitImageIfNeeded Image_ButtonFood button-food.gif 32 InitImageIfNeeded Image_ButtonPotion button-potion.gif 33 InitImageIfNeeded Image_ButtonScroll button-scroll.gif 34 InitImageIfNeeded Image_ButtonRod button-rod.gif 35 InitImageIfNeeded Image_ButtonWand button-wand.gif 36 InitImageIfNeeded Image_ButtonStaff button-staff.gif 37 InitImageIfNeeded Image_ButtonDown button-down.gif 38 InitImageIfNeeded Image_ButtonUp button-up.gif 39 40 InitImageIfNeeded Image_ButtonBook button-book.gif 41 42 NSObject::New NSAutobar 43 44 return 45} 46 47# NSAutobar::CloseModule -- 48# 49# One-time-only-ever cleanup. 50# 51# Arguments: 52# arg1 about arg1 53# 54# Results: 55# What happened. 56 57proc NSAutobar::CloseModule {} { 58 59 catch { 60 destroy [Global autobar,canvas] 61 } 62 63 return 64} 65 66# NSAutobar::MInfo -- 67# 68# Query and modify info. 69# 70# Arguments: 71# arg1 about arg1 72# 73# Results: 74# What happened. 75 76proc NSAutobar::MInfo {info args} { 77 78 variable Priv 79 80 # Set info 81 if {[llength $args]} { 82 set Priv($info) [lindex $args 0] 83 84 # Get info 85 } else { 86 return $Priv($info) 87 } 88 89 return 90} 91 92# NSAutobar::NSAutobar -- 93# 94# Object constructor called by NSObject::New(). 95# 96# Arguments: 97# oop OOP ID. See above. 98# 99# Results: 100# What happened. 101 102proc NSAutobar::NSAutobar {oop} { 103 104 Info $oop busy 0 105 Info $oop current "" 106 Info $oop request,id "" 107 Info $oop showing 0 108 109 Info $oop bar,visible 0 110 Info $oop win,visible 0 111 Info $oop whoHasCursor "" 112 Info $oop after "" 113 114 Info $oop nextButton 0 115 116 InitDisplay $oop 117 118 set canvas [Info $oop canvas] 119 set wText [Info $oop text] 120 121 # Update ourself when the list highlight color changes 122 Info $oop clientId,listHilite \ 123 [NSValueManager::AddClient listHilite \ 124 "$wText tag configure HOT \ 125 -background \[Value listHilite]"] 126 127 # Update ourself when the font changes 128 Info $oop clientId,font,autobar \ 129 [NSValueManager::AddClient font,autobar \ 130 "NSAutobar::ValueChanged_font_autobar $oop"] 131 132 # Destroy the object along with the toplevel (later) 133 NSUtils::DestroyObjectWithWidget NSAutobar $oop $canvas 134 135 Global autobar,canvas $canvas 136 Global autobar,oop $oop 137 138 return 139} 140 141# NSAutobar::~NSAutobar -- 142# 143# Object destructor called by NSObject::Delete(). 144# 145# Arguments: 146# arg1 about arg1 147# 148# Results: 149# What happened. 150 151proc NSAutobar::~NSAutobar {oop} { 152 153 NSValueManager::RemoveClient font,autobar [Info $oop clientId,font,autobar] 154 NSValueManager::RemoveClient listHilite [Info $oop clientId,listHilite] 155 156 return 157} 158 159# NSAutobar::Info -- 160# 161# Query and modify info. 162# 163# Arguments: 164# arg1 about arg1 165# 166# Results: 167# What happened. 168 169proc NSAutobar::Info {oop info args} { 170 171 global NSAutobar 172 173 # Set info 174 if {[llength $args]} { 175 switch -- $info { 176 default { 177 set NSAutobar($oop,$info) [lindex $args 0] 178 } 179 } 180 181 # Get info 182 } else { 183 switch -- $info { 184 default { 185 return $NSAutobar($oop,$info) 186 } 187 } 188 } 189 190 return 191} 192 193# NSAutobar::InitDisplay -- 194# 195# Create the display. 196# 197# Arguments: 198# oop OOP ID. See above. 199# 200# Results: 201# What happened. 202 203proc NSAutobar::InitDisplay {oop} { 204 205 set widget [Global main,widget] 206 207 # 208 # The main canvas, holding the buttons 209 # 210 211 set canvas $widget.autobar$oop 212 canvas $canvas \ 213 -borderwidth 0 -relief flat -highlightthickness 0 \ 214 -background Black -height 22 -width 200 \ 215 -scrollregion {0 0 0 0} 216 217 Info $oop canvas $canvas 218 219 bind $canvas <Enter> \ 220 "NSAutobar::Event $oop enter-bar" 221 bind $canvas <Leave> \ 222 "NSAutobar::Event $oop leave-bar" 223 224 # 225 # Buttons 226 # Some buttons invoke a command when clicked, such as "go down". 227 # Other buttons display a list of item or spell choices. 228 # If a pop-up button has no valid choices, then it isn't displayed 229 # in the bar. 230 # 231 232 set x 2 233 NewButton $oop -image Image_ButtonActivate -popup 1 -hook item \ 234 -args [list equipment A -activate yes] \ 235 -message "Activate an equipment item" 236 237 $canvas configure -width [incr x 20] 238 239 $canvas create rectangle \ 240 0 0 [expr {$x - 1}] 21 -outline gray60 -tags border 241 242 # 243 # Popup window of choices 244 # 245 246 set win $canvas.popup 247 toplevel $win 248 $win configure -borderwidth 1 -relief flat -background gray60 249 wm overrideredirect $win yes 250 wm transient $win [Window main] 251 252 if {[Platform unix]} { 253 $win configure -cursor arrow 254 } 255 256 # Start out withdrawn (hidden) 257 wm withdraw $win 258 259 Info $oop win $win 260 261 set wText $win.text 262 text $wText \ 263 -wrap none -font [Value font,autobar] \ 264 -borderwidth 0 -setgrid no -highlightthickness 0 \ 265 -padx 4 -pady 2 -background Black -foreground White -cursor "" 266 267 # Bypass default Text bindings 268 bindtags $wText [list $wText $win all] 269 270 pack $wText \ 271 -expand yes -fill both 272 273 Info $oop text $wText 274 275 # Fiddle with the selection for list behaviour 276 $wText tag configure HOT -foreground White \ 277 -background [Value listHilite] 278 279 $wText tag bind HOT <ButtonPress-1> \ 280 "NSAutobar::Invoke $oop" 281 $wText tag bind TEXT <Motion> \ 282 "NSAutobar::Motion $oop \[$wText index {@%x,%y linestart}]" 283 $wText tag bind HOT <Leave> \ 284 "NSAutobar::Motion $oop {}" 285 286 bind $win <Enter> \ 287 "NSAutobar::Event $oop enter-win" 288 bind $win <Leave> " 289 NSAutobar::Motion $oop {} 290 NSAutobar::Event $oop leave-win 291 " 292 293 return 294} 295 296# NSAutobar::NewButton -- 297# 298# Add a new button to the Autobar. 299# 300# Arguments: 301# arg1 about arg1 302# 303# Results: 304# What happened. 305 306proc NSAutobar::NewButton {oop args} { 307 308 set canvas [Info $oop canvas] 309 310 # Get the next unique id for this button 311 set num [incr ::NSAutobar($oop,nextButton)] 312 313 set config(-command) "" 314 array set config $args 315 316 set image $config(-image) 317 set command $config(-command) 318 set message $config(-message) 319 320 # The buttons are positioned in ShowBar(). 321 set x 0 322 set y 0 323 324 # Focus rectangle 325 $canvas create rectangle $x $y [expr {$x + 17}] [expr {$y + 17}] \ 326 -tags [list button button$num border$num] 327 328 # Image 329 $canvas create image [expr {$x + 1}] [expr {$y + 1}] -image $image \ 330 -anchor nw -tags "button button$num img$num" 331 332 # Show popup on mouse-over 333 if {![string length $command]} { 334 335 $canvas bind img$num <Enter> " 336 $canvas itemconfigure border$num -outline gray60 337 NSMainWindow::StatusText $oop [list $message] 338 NSAutobar::EnterButton $oop $num 339 " 340 341 Info $oop button,hook,$num $config(-hook) 342 Info $oop button,args,$num $config(-args) 343 344 # Click to invoke command 345 } else { 346 $canvas bind img$num <Enter> " 347 $canvas itemconfigure border$num -outline gray60 348 NSMainWindow::StatusText $oop [list $message] 349 NSAutobar::Event $oop enter-button2 350 " 351 $canvas bind img$num <ButtonPress-1> " 352 $canvas move button$num 1 1 353 $command 354 " 355 $canvas bind img$num <ButtonRelease-1> \ 356 "$canvas move button$num -1 -1" 357 358 Info $oop button,hook,$num "" 359 } 360 361 $canvas bind img$num <Leave> " 362 $canvas itemconfigure border$num -outline Black 363 NSAutobar::Event $oop leave-button 364 NSMainWindow::StatusText $oop {} 365 " 366 367 return 368} 369 370# NSAutobar::SetHook -- 371# 372# Set the hook. 373# 374# Arguments: 375# arg1 about arg1 376# 377# Results: 378# What happened. 379 380proc NSAutobar::SetHook {oop hook} { 381 382 if {[string length $hook]} { 383 Info $oop hook $hook 384 CallHook $oop open 385 } elseif {[string length [Info $oop hook]]} { 386 Info $oop hook "" 387 } 388 389 return 390} 391 392# NSAutobar::CallHook -- 393# 394# Call the hook. 395# 396# Arguments: 397# arg1 about arg1 398# 399# Results: 400# What happened. 401 402proc NSAutobar::CallHook {oop message args} { 403 404 return [uplevel #0 NSAutobar::[Info $oop hook] $oop $message $args] 405} 406 407# NSAutobar::EnterButton -- 408# 409# Display popup of choices. 410# 411# Arguments: 412# arg1 about arg1 413# 414# Results: 415# What happened. 416 417proc NSAutobar::EnterButton {oop buttonNum} { 418 419 set win [Info $oop win] 420 set canvas [Info $oop canvas] 421 set wText [Info $oop text] 422 423 set hook [Info $oop button,hook,$buttonNum] 424 set hookArgs [Info $oop button,args,$buttonNum] 425 426 if {[lsearch -exact [angband inkey_flags] INKEY_CMD] == -1} return 427 428 set x [Info $oop button,x,$buttonNum] 429 incr x [expr {[winfo rootx $canvas] + 9}] 430 set y [winfo rooty $canvas] 431 432 # Set the list 433 SetHook $oop hook_$hook 434 $wText delete 1.0 end 435 eval CallHook $oop set_list $hookArgs 436 437 set width [Info $oop maxWidth] 438 incr width [expr {[$wText cget -padx] * 2}] 439 440 set height [Info $oop maxHeight] 441 incr height [expr {[$wText cget -pady] * 2}] 442 443 incr width [expr {[$win cget -borderwidth] * 2}] 444 incr height [expr {[$win cget -borderwidth] * 2}] 445 446 # x is middle 447 incr x [expr {0 - $width / 2}] 448 if {$x < [winfo rootx $canvas]} { 449 set x [winfo rootx $canvas] 450 } 451 452 # Given y is bottom 453 incr y -$height 454 455 set screenWidth [winfo screenwidth .] 456 if {$x + $width > $screenWidth} { 457 incr x [expr {$screenWidth - ($x + $width)}] 458 } 459 set screenHeight [winfo screenheight .] 460 if {$y + $height > $screenHeight} { 461 incr y [expr {$screenHeight - ($y + $height)}] 462 } 463 464 wm geometry $win ${width}x${height}+${x}+$y 465 466 # Perhaps show the window later 467 Event $oop enter-button 468 469 return 470} 471 472# NSAutobar::Event -- 473# 474# Description. 475# 476# Arguments: 477# arg1 about arg1 478# 479# Results: 480# What happened. 481 482proc NSAutobar::Event {oop event} { 483 484 set who [Info $oop whoHasCursor] 485 486 switch -- $event { 487 enter-status { 488 if {[lsearch -exact [angband inkey_flags] INKEY_CMD] == -1} return 489 set who status 490 } 491 leave-status { 492 set who "" 493 } 494 enter-bar { 495 # The <Enter> binding for a button is invoked before 496 # the binding for the canvas. So we don't want to 497 # forget we are in a button 498 if {[string compare $who button]} { 499 set who bar 500 } 501 } 502 leave-bar { 503 set who "" 504 } 505 enter-win { 506 set who win 507 } 508 leave-win { 509 set who "" 510 } 511 enter-button { 512 set who button 513 } 514 enter-button2 { 515 set who button2 516 } 517 leave-button { 518 set who bar 519 } 520 } 521 522 Info $oop whoHasCursor $who 523 if {[string match enter-* $event]} { 524 set delay 10 525 } else { 526 set delay 200 527 } 528 after cancel [Info $oop after] 529 Info $oop after [after $delay NSAutobar::CheckWhoHasCursor $oop] 530 531 return 532} 533 534# NSAutobar::CheckWhoHasCursor -- 535# 536# Description. 537# 538# Arguments: 539# arg1 about arg1 540# 541# Results: 542# What happened. 543 544proc NSAutobar::CheckWhoHasCursor {oop} { 545 546 set who [Info $oop whoHasCursor] 547 548 switch -- $who { 549 bar { 550 HideWin $oop 551 } 552 button { 553 ShowWin $oop 554 } 555 button2 { 556 HideWin $oop 557 } 558 status { 559 HideWin $oop 560 ShowBar $oop 561 } 562 win { 563 564 } 565 default { 566 HideWin $oop 567 HideBar $oop 568 } 569 } 570 571 Info $oop after "" 572 573 return 574} 575 576# NSAutobar::ShowBar -- 577# 578# Description. 579# 580# Arguments: 581# arg1 about arg1 582# 583# Results: 584# What happened. 585 586proc NSAutobar::ShowBar {oop} { 587 588 set canvas [Info $oop canvas] 589 590 # The bar is already shown 591 if {[Info $oop bar,visible]} return 592 593 # Hide all the buttons 594 $canvas itemconfigure button -state hidden 595 596 # Display buttons which have some commands 597 set x 3 598 set y 3 599 600 # Check each button 601 for {set i 1} {$i <= [Info $oop nextButton]} {incr i} { 602 603 # Get the hook for this button (if any) 604 set hook [Info $oop button,hook,$i] 605 606 # This button has a hook 607 if {[string length $hook]} { 608 609 # Set the hook 610 SetHook $oop hook_$hook 611 612 # Get the extra args to pass to the hook 613 set args [Info $oop button,args,$i] 614 615 # See if there are any valid choices 616 if {[eval CallHook $oop has_cmd $args]} { 617 618 # Position the button horizontally 619 scan [$canvas coords img$i] "%s %s" cx cy 620 $canvas move button$i [expr {$x - $cx}] [expr {$y - $cy}] 621 $canvas itemconfigure button$i -state "" 622 623 # Remember the x coordinate 624 Info $oop button,x,$i $x 625 626 # Leave space for another button 627 incr x 20 628 } 629 630 # Button has no hook, always show it 631 } else { 632 633 # Position the button horizontally 634 scan [$canvas coords img$i] "%s %s" cx cy 635 $canvas move button$i [expr {$x - $cx}] [expr {$y - $cy}] 636 $canvas itemconfigure button$i -state "" 637 638 # Remember the x coordinate 639 Info $oop button,x,$i $x 640 641 # Leave space for another button 642 incr x 20 643 } 644 } 645 646 # Resize the bar, and position the border rectangle 647 set width [expr {$x - 1}] 648 $canvas configure -width $width 649 $canvas coords border 0 0 [expr {$width - 1}] 21 650 651 # Now slide the bar into view 652 set height [winfo reqheight $canvas] 653 foreach frac [list 0.1 0.2 0.3 0.5 0.7 1] { 654 set dy [expr {0 - $height * $frac}] 655 place $canvas -relx 0.5 -rely 1.0 -y $dy -anchor n 656 update idletasks 657 } 658 659 Info $oop bar,visible 1 660 661 return 662} 663 664# NSAutobar::HideBar -- 665# 666# Description. 667# 668# Arguments: 669# arg1 about arg1 670# 671# Results: 672# What happened. 673 674proc NSAutobar::HideBar {oop} { 675 676 if {![Info $oop bar,visible]} return 677 678 set canvas [Info $oop canvas] 679 680 # Now slide the bar out of view 681 set height [winfo reqheight $canvas] 682 foreach frac [list 0.7 0.4 0.1] { 683 set dy [expr {0 - $height * $frac}] 684 place $canvas -relx 0.5 -rely 1.0 -y $dy -anchor n 685 686 # Kind of slow if mouse is whizzing around... 687 update 688 } 689 690 place forget $canvas 691 692 Info $oop bar,visible 0 693 694 return 695} 696 697# NSAutobar::ShowWin -- 698# 699# Description. 700# 701# Arguments: 702# arg1 about arg1 703# 704# Results: 705# What happened. 706 707proc NSAutobar::ShowWin {oop} { 708 709 if {[Info $oop win,visible]} return 710 711 set win [Info $oop win] 712 713 wm deiconify $win 714 if {[Platform unix]} { 715 raise $win 716 } 717 718 Info $oop win,visible 1 719 720 return 721} 722 723# NSAutobar::HideWin -- 724# 725# Description. 726# 727# Arguments: 728# arg1 about arg1 729# 730# Results: 731# What happened. 732 733proc NSAutobar::HideWin {oop} { 734 735 if {![Info $oop win,visible]} return 736 737 set win [Info $oop win] 738 739 wm withdraw $win 740 741 Info $oop win,visible 0 742 743 return 744} 745 746# NSAutobar::Invoke -- 747# 748# Called when a list item is clicked. 749# 750# Arguments: 751# arg1 about arg1 752# 753# Results: 754# What happened. 755 756proc NSAutobar::Invoke {oop} { 757 758 set textBox [Info $oop text] 759 set index [Info $oop current] 760 set row [expr {[lindex [split $index .] 0] - 1}] 761 762 HideWin $oop 763 HideBar $oop 764 765 CallHook $oop invoke $row 766 767 return 768} 769 770# NSAutobar::Motion -- 771# 772# Called when the mouse moves in a list item. 773# 774# Arguments: 775# arg1 about arg1 776# 777# Results: 778# What happened. 779 780proc NSAutobar::Motion {oop index} { 781 782 set textBox [Info $oop text] 783 784 # If you invoke an item, hold down the mouse, and drag... 785 if {![string length [Info $oop hook]]} return 786 787 # No tracking while menu is up 788# if {[Info $oop busy]} return 789 790 # See if the item has changed 791 if {$index == [Info $oop current]} return 792 793 # An item is highlighted 794 if {[string length [Info $oop current]]} { 795 796 # Remove highlighting 797 UnhighlightItem $oop [Info $oop current] 798 } 799 800 # An item is under the pointer 801 if {[string length $index]} { 802 803 # Highlight the item 804 HighlightItem $oop $index 805 } 806 807 # Remember which item is highlighted 808 Info $oop current $index 809 810 return 811} 812 813# NSAutobar::HighlightItem -- 814# 815# Highlights a list item. 816# 817# Arguments: 818# arg1 about arg1 819# 820# Results: 821# What happened. 822 823proc NSAutobar::HighlightItem {oop index} { 824 825 set textBox [Info $oop text] 826 set row [expr {[lindex [split $index .] 0] - 1}] 827 828 # Highlight the item 829 $textBox tag add HOT $index "$index lineend" 830 $textBox tag raise HOT 831 832 # Call the hook (to set the icon, for example) 833 CallHook $oop highlight $row 834 835 return 836} 837 838# NSAutobar::UnhighlightItem -- 839# 840# Removes highlighting from a list item. 841# 842# Arguments: 843# arg1 about arg1 844# 845# Results: 846# What happened. 847 848proc NSAutobar::UnhighlightItem {oop index} { 849 850 set win [Info $oop win] 851 set textBox [Info $oop text] 852 853 # Unhighlight the item 854 $textBox tag remove HOT 1.0 end 855 856 return 857} 858 859# NSAutobar::HasCursor -- 860# 861# See if the cursor is over the window. 862# 863# Arguments: 864# arg1 about arg1 865# 866# Results: 867# What happened. 868 869proc NSAutobar::HasCursor {oop} { 870 871 set pointerx [winfo pointerx .] 872 set pointery [winfo pointery .] 873 set window [winfo containing $pointerx $pointery] 874 if {![string length $window]} { 875 return 0 876 } 877 if {[string compare [winfo toplevel $window] [Info $oop win]]} { 878 return 0 879 } 880 return 1 881} 882 883 884# NSAutobar::ValueChanged_font_autobar -- 885# 886# Called when the font,autobar value changes. 887# Updates the Recall Window. 888# 889# Arguments: 890# arg1 about arg1 891# 892# Results: 893# What happened. 894 895proc NSAutobar::ValueChanged_font_autobar {oop} { 896 897 set text [Info $oop text] 898 $text configure -font [Value font,autobar] 899 900 return 901} 902