# power.tcl --
#
#	The Power Window and related commands. The Power Window displays
#	a list of racial and mutation powers.
#

namespace eval NSPower {

# NSPower::InitModule --
#
#	One-time-only-ever initialization.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitModule {} {

	NSObject::New NSPower
}

# NSPower::NSPower --
#
#	Object constructor called by NSObject::New().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NSPower oop {

	global Windows

	InitWindow $oop

	#
	# Global list of application windows
	#

	set Windows(power,win) [Info $oop win]
	set Windows(power,class) NSPower
	set Windows(power,oop) $oop
}

# NSPower::Info --
#
#	Query and modify info.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Info {oop info args} {

	global NSPower

	# Set info
	if {[llength $args]} {
		switch -- $info {
			default {
				set NSPower($oop,$info) [lindex $args 0]
			}
		}

	# Get info
	} else {
		switch -- $info {
			default {
				return $NSPower($oop,$info)
			}
		}
	}
}

# NSPower::InitWindow --
#
#	Create the window associated with this object.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitWindow oop {

	global NSCanvist
	global NSToolbar
	global Windows

	set w .power$oop
	toplevel $w
	wm title $w Powers

	wm transient $w $Windows(main,win)

	# Start out withdrawn (hidden)
	wm withdraw $w

	# Do stuff when window closes
	wm protocol $w WM_DELETE_WINDOW "NSPower::Close $oop"

	Info $oop win $w

	#
	# Toolbar
	#

	set toolId [NSObject::New NSToolbar 20 $w]
	NSToolbar::AddTool $toolId Image_ButtonOptions "DoCommandIfAllowed ="
	NSToolbar::AddTool $toolId Image_ButtonHelp "DoCommandIfAllowed ?"

	#
	# Divider
	#

	frame $w.divider2 \
		-borderwidth 1 -height 2 -relief groove

	#
	# List
	#

	frame $w.frame \
		-borderwidth 1 -relief sunken

	InitHeader $w.frame 2 {Courier 9} {Name 3 nw Level 32 ne Cost 37 ne Chance 44 ne Stat 45 nw}

	set canvistId [NSObject::New NSCanvist $w.frame 20 400 300 \
		"NSPower::NewItemCmd $oop" "NSPower::HighlightItemCmd $oop"]
	set canvas $NSCanvist($canvistId,canvas)
	ListBackgroundChanged $canvas
	$canvas configure -yscrollcommand "$w.frame.scroll set"
	scrollbar $w.frame.scroll \
		-borderwidth 0 -command "$canvas yview" -orient vert

	# This call updates the list background color whenever the
	# global list background color changes
	Info $oop clientId \
		[NSValueManager::AddClient listBG "ListBackgroundChanged $canvas"]

	Info $oop list $canvistId

	pack $w.frame.scroll -side right -fill y
	pack $w.frame.header \
		-side top -fill x
	pack $canvas -side left -expand yes -fill both

	#
	# Double-click to select spell
	#

	set NSCanvist($canvistId,invokeCmd) "NSPower::Invoke $oop"

	#
	# Statusbar
	#

	frame $w.statusBar -relief flat -borderwidth 0
	label $w.statusBar.label -anchor w -relief sunken -padx 2
	label $w.statusBar.label2 -anchor w -relief sunken -padx 2 -width 12
	pack $w.statusBar.label -side left -expand yes -fill both
	pack $w.statusBar.label2 -side right -expand no

	#
	# Geometry
	#

	grid rowconfig $w 0 -weight 0 -minsize 0
	grid rowconfig $w 1 -weight 0 -minsize 0
	grid rowconfig $w 2 -weight 1 -minsize 0
	grid rowconfig $w 3 -weight 0 -minsize 0
	grid columnconfig $w 0 -weight 1 -minsize 0
 
	pack forget $NSToolbar($toolId,frame)
	grid $NSToolbar($toolId,frame) -in $w \
		-row 0 -column 0 -rowspan 1 -columnspan 1 -sticky ew
	grid $w.divider2 -in $w \
		-row 1 -column 0 -rowspan 1 -columnspan 1 -sticky ew
	grid $w.frame -in $w \
		-row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
	grid $w.statusBar -in $w \
		-row 3 -column 0 -rowspan 1 -columnspan 1 -sticky ew

	#
	# Feed Term when keys pressed
	#

	bind $w <KeyPress> {
		angband keypress %A
	}

	#
	# Synch the scrollbars when window is shown.
	#

	bind $w.frame.scroll <Map> "NSPower::SynchScrollBars $oop"

	bind $w <FocusIn> "if !\[string compare %W $w] {focus $canvas}"
}

# NSPower::Close --
#
#	Description.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Close oop {

	angband keypress \033
}

# NSPower::Invoke --
#
#	When a power is double-clicked, "angband keypress" the char.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Invoke {oop canvistId x y} {

	global NSCanvist

	if {[lsearch -exact [angband inkey_flags] INKEY_POWER] == -1} return

	set row [NSCanvist::PointToRow $canvistId $x $y]
	if {$row == -1} return

	set char [string index "abcdefghijklmnopqrstuvwxyz" $row]
	angband keypress $char
}

# NSPower::SetList --
#
#	Fill the list with powers.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetList oop {

	set win [Info $oop win]
	set canvistId [Info $oop list]
	set canvas [NSCanvist::Info $canvistId canvas]

	NSCanvist::Delete $canvistId 0 end

	set row 0
	foreach power [angband power get] {

		angband power info $power attrib
		set attrib(char) [string index "abcdefghijklmnopqrstuvwxyz" $row]

		NSCanvist::Insert $canvistId end $attrib(char) $attrib(name) \
			$attrib(level) $attrib(cost) $attrib(chance) $attrib(stat)

		incr row
	}

	# Display number of powers
	if {$row > 1} {
		set s s
	} else {
		set s ""
	}
	$win.statusBar.label configure -text "$row power$s"
}

# NSPower::SynchScrollBars --
#
#	There is a bug (my bug or in Tk?) which prevents the scroll bars
#	from synchronizing when the window is not mapped. So I bind to
#	the <Map> event and synch the scroll bars here.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SynchScrollBars oop {

	set win [Info $oop win]
	set canvistId [Info $oop list]
	set canvas [NSCanvist::Info $canvistId canvas]

	eval $win.frame.scroll set [$canvas yview]
	$canvas yview moveto 0.0
}

# NSPower::NewItemCmd --
#
#	Called by NSCanvist::InsertItem() to create a list row.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NewItemCmd {oop canvistId y char name level cost chance stat} {

	set c [NSCanvist::Info $canvistId canvas]
	set lineHeight [NSCanvist::Info $canvistId rowHgt]
	set font {Courier 9}

	set text "$char) $name"
	set textLeft 5

	set cw [font measure $font "W"]
	set fw [font measure $font $text]
	set fh [font metrics $font -linespace]
	set diff [expr int([expr ($lineHeight - $fh) / 2])]

	# Selection rectangle inside row
	lappend itemIdList [$c create rectangle 2 [expr $y + 2] \
		[expr [winfo width $c] - 3] [expr $y + $lineHeight - 2] \
		-fill "" -outline "" -tags enabled -width 2.0]

	# Text
	lappend itemIdList [$c create text $textLeft [expr $y + $diff] \
		-text $text -anchor nw -font $font -fill White -tags enabled]

	set offset 0

	# Level
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 32]] \
		[expr $y + $diff] \
		-text $level -anchor ne -justify right -font $font -fill White]

	# Cost
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 5]] \
		[expr $y + $diff] \
		-text $cost -anchor ne -justify right -font $font -fill White]

	# Chance
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 7]] \
		[expr $y + $diff] \
		-text $chance -anchor ne -justify right -font $font -fill White]

	# Stat
	set stat [string toupper [string index $stat 0]][string range $stat 1 end]
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 1]] \
		[expr $y + $diff] \
		-text $stat -anchor nw -justify left -font $font -fill White]

	return $itemIdList
}

# NSPower::HighlightItemCmd --
#
#	Called by NSCanvist::Select() to highlight a row.
#
# Arguments:
#	oop					OOP ID. See above.
#	canvistId					OOP ID of NSCanvist object.
#	state					1 or 0 highlight state.
#	args					List of canvas item ids
#
# Results:
#	What happened.

proc HighlightItemCmd {oop canvistId state args} {

	global NSCanvist

	set canvas $NSCanvist($canvistId,canvas)
	set itemIdList $args

	set idRect [lindex $itemIdList 0]

	if $state {

		$canvas itemconfigure $idRect -outline [NSColorPreferences::Get listHilite]

	} else {

		$canvas itemconfigure $idRect -outline {}
	}
}

# NSPower::PopupSelect --
#
#	Show a pop-up menu of power choices.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc PopupSelect {menu x y} {

	global PopupResult

	set PopupResult 0

	$menu delete 0 end
	set num 0
	foreach power [angband power get] {

		angband power info $power attrib
		set attrib(char) [string index "abcdefghijklmnopqrstuvwxyz" $num]

		# Append menu entry
		$menu add command -label "$attrib(char) $attrib(name)" \
			-command "angband keypress $attrib(char) ; set PopupResult 1" \
			-underline 0

		incr num
	}
	if !$num return

	# Pressing and holding Button-3, poping up, then letting go selects 
	# an item, so wait a bit if it was a quick press-release
	after 100

	tk_popup $menu $x $y [expr $num / 2]

	# If the user unposts the menu without choosing an entry, then
	# I want to feed Escape into the Term. I tried binding to the <Unmap>
	# event but it isn't called on Windows(TM).
	after idle {
		if !$PopupResult {
			angband keypress \033
		}
	}
}

# namespace eval NSPower
}

