# icon-browser.tcl --
#
#	This mega-widget allows the user to browse through all the
#	different types of icons. It is based on a NSCanvist2, so you
#	would use the "selectionCmd" option to update your stuff when
#	an icon is selected (or unselected). An NSIconBrowser also
#	knows how to display a specific icon (ie, scroll it into view).
#

namespace eval NSIconBrowser {

variable IconTypes

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

proc InitModule {} {

	variable IconTypes

	foreach iconType [icon gettypes] {
		switch $iconType {
			alternate -
			blank -
			default -
			flavor -
			none -
			sprite {
			}
			default {
				# Hack -- Don't show ascii type icons
				if {[catch [icon ascii font $iconType]]} {
					lappend IconTypes $iconType
				}
			}
		}
	}
}

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

proc NSIconBrowser {oop parent} {

	global NSIconBrowser

	# Call this command while displaying an icon type
	Info $oop clientCmd ""

	InitDisplay $oop $parent
#	SetList_Group $oop
#	SetList_Member $oop [lindex $IconTypes 0]
}

# NSIconBrowser::~NSIconBrowser --
#
#	Object destructor called by NSObject::Delete().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc ~NSIconBrowser oop {

	NSValueManager::RemoveClient listBG [Info $oop group,clientId]
	NSValueManager::RemoveClient listBG [Info $oop member,clientId]
}

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

proc Info {oop info args} {

	global NSIconBrowser

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

	# Get info
	} else {
		switch -- $info {
			groupCanvas {
				set canvistId [Info $oop group,canvistId]
				return [NSCanvist2::Info $canvistId canvas]
			}
			memberCanvas {
				set canvistId [Info $oop member,canvistId]
				return [NSCanvist2::Info $canvistId canvas]
			}
			default {
				return $NSIconBrowser($oop,$info)
			}
		}
	}
}

# NSIconBrowser::InitDisplay --
#
#	Create our stuff.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitDisplay {oop parent} {

	global NSIconBrowser

	# This frame holds all our stuff
	set frame $parent.iconbrowser$oop
	frame $frame \
		-borderwidth 1 -relief sunken

	# So client can pack us
	Info $oop frame $frame

	#
	# Group List
	#

	set iconSize [expr [icon size] + 8]

	set frameGroup $frame.frameGroup
	frame $frameGroup \
		-borderwidth 0
	set canvistId [NSObject::New NSCanvist2 $frameGroup $iconSize $iconSize $iconSize 240]
	NSCanvist2::Info $canvistId newItemCmd \
		"NSIconBrowser::NewItemCmd $oop"
	NSCanvist2::Info $canvistId highlightCmd \
		"NSIconBrowser::HighlightItemCmd $oop"
	NSCanvist2::Info $canvistId columns 1
	set canvas [NSCanvist2::Info $canvistId canvas]
	$canvas configure -background [NSColorPreferences::Get listBG]
	$canvas configure -yscrollcommand "$frameGroup.yscroll set"
	scrollbar $frameGroup.yscroll \
		-borderwidth 0 -command "$canvas yview" -orient vertical

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

	# When a group is selected, show the artifacts/monsters in it
	NSCanvist2::Info $canvistId selectionCmd \
		"NSIconBrowser::SelectionChanged_Group $oop"

	# Grid, please
	pack $canvas -side left -expand yes -fill both -anchor nw
	pack $frameGroup.yscroll -side left -fill y

	Info $oop group,canvistId $canvistId

	#
	# Icon List
	#

	set frameIcon $frame.frameIcon
	frame $frameIcon \
		-borderwidth 0
	set canvistId [NSObject::New NSCanvist2 $frameIcon $iconSize $iconSize 240 240]
	NSCanvist2::Info $canvistId newItemCmd \
		"NSIconBrowser::NewItemCmd $oop"
	NSCanvist2::Info $canvistId highlightCmd \
		"NSIconBrowser::HighlightItemCmd $oop"
	NSCanvist2::Info $canvistId columns 6
	set canvas [NSCanvist2::Info $canvistId canvas]
	$canvas configure -background [NSColorPreferences::Get listBG]
	$canvas configure -yscrollcommand "$frameIcon.yscroll set"
	scrollbar $frameIcon.yscroll \
		-borderwidth 0 -command "$canvas yview" -orient vertical

	Info $oop member,canvistId $canvistId

	Info $oop member,clientId \
		[NSValueManager::AddClient listBG "ListBackgroundChanged $canvas"]

	pack $canvas -side left -expand yes -fill both -anchor nw
	pack $frameIcon.yscroll -side left -fill y

	#
	# Geometry
	#

	grid rowconfig $frame 0 -weight 1 -minsize 0
	grid columnconfig $frame 0 -weight 0 -minsize 0
	grid columnconfig $frame 1 -weight 1 -minsize 0
 
	grid $frameGroup \
		-row 0 -column 0 -rowspan 1 -columnspan 1 -sticky ns
	grid $frameIcon \
		-row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news

	# Destroy the object along with the widget(s)
	bind $frame <Destroy> "+
		NSObject::Delete NSIconBrowser $oop
	"
}


# NSIconBrowser::SelectionChanged_Group --
#
#	When an icon group is selected, display icons in that group.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SelectionChanged_Group {oop canvistId select deselect} {

	variable IconTypes

	# Clear member list if no group is selected
	if {![llength $select]} {
		set canvistId [Info $oop member,canvistId]
		NSCanvist2::DeleteAll $canvistId
		return
	}

	# Get the (first) row
	set row [lindex $select 0]

	# Display icons in that group
	SetList_Member $oop [lindex $IconTypes $row]
}

# NSIconBrowser::SetList_Group --
#
#	.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetList_Group oop {

	variable IconTypes

	set canvistId [Info $oop group,canvistId]
	set canvas [NSCanvist2::Info $canvistId canvas]

	# Clear the list
	NSCanvist2::DeleteAll $canvistId

	# Add each group
	foreach iconType $IconTypes {

		# Add this group to the list
		NSCanvist2::Append $canvistId $iconType 0
	}

	# Hack -- Clear the icon list
	NSCanvist2::DeleteAll [Info $oop member,canvistId]
}

# NSIconBrowser::SetList_Member --
#
#	.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetList_Member {oop iconType} {

	set canvistId [Info $oop member,canvistId]
	set canvas [NSCanvist2::Info $canvistId canvas]
	set win [winfo toplevel $canvas]

	# Get busy
	set cursor [$win cget -cursor]
	$win configure -cursor wait
	update

	# Call this *before* clearing the list
	set command [Info $oop clientCmd]
	if {[string length $command]} {
	uplevel #0 $command open
	}

	# Clear the list
	NSCanvist2::DeleteAll $canvistId

# Is there a <Configure> event or something?
set width [winfo width $canvas]
set iconSize [expr [icon size] + 8]
set columns [expr $width / $iconSize]
if {$columns == 0} {set columns 1}
NSCanvist2::Info $canvistId columns $columns

	# Get the number of icons of the given type */
	set max [icon count $iconType]

	# Add each icon to the list
	for {set i 0} {$i < $max} {incr i} {

		# Append icon to the list
		NSCanvist2::Append $canvistId $iconType $i

if {[string length $command]} {
	uplevel #0 $command update $i $max
}
	}

	# Remember which type is currently displayed
	Info $oop iconType $iconType

if {[string length $command]} {
	uplevel #0 $command close
}

	# Display icons and restore the cursor
	update
	$win configure -cursor $cursor
}

# NSIconBrowser::SeeIcon --
#
#	.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SeeIcon {oop iconType iconIndex} {

	variable IconTypes

	set row 0
	foreach iconType2 $IconTypes {
		if {![string compare $iconType $iconType2]} break
		incr row
	}

	# Select and display the group the icon is in
	set canvistId [Info $oop group,canvistId]
	NSCanvist2::UpdateSelection $canvistId $row \
		[NSCanvist2::Selection $canvistId]
	NSCanvist2::See $canvistId $row

	# Select and display the icon itself
	set canvistId [Info $oop member,canvistId]
	NSCanvist2::UpdateSelection $canvistId $iconIndex \
		[NSCanvist2::Selection $canvistId]
	NSCanvist2::See $canvistId $iconIndex
}

# NSIconBrowser::GetIconType --
#
#	Return the type of icon currently being displayed.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc GetIconType oop {

	global NSIconBrowser

	return $NSIconBrowser($oop,iconType)
}

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

proc NewItemCmd {oop canvistId x y iconType iconIndex} {

	global NSCanvist2

	set c $NSCanvist2($canvistId,canvas)
	set columnWidth $NSCanvist2($canvistId,columnWidth)
	set rowHeight $NSCanvist2($canvistId,rowHeight)

	# Selection rectangle around everything
	lappend itemIdList [$c create rectangle [expr $x + 2] [expr $y + 2] \
		[expr $x + $columnWidth - 2] [expr $y + $rowHeight - 2] \
		-fill {} -outline {} -tags enabled -width 2.0]

	# Widget
	set iw [icon size]
	set ih [icon size]
	set xdiff [expr int([expr ($columnWidth - $iw) / 2])]
	set ydiff [expr int([expr ($rowHeight - $ih) / 2])]
	lappend itemIdList [$c create widget [expr $x + $xdiff] [expr $y + $ydiff] \
		-type $iconType -index $iconIndex -tags enabled]

	return $itemIdList
}

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

proc HighlightItemCmd {oop canvistId state args} {

	global NSCanvist2

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

	set idRect [lindex $itemIdList 0]

	if {[NSUtils::HasFocus $canvas]} {
		set fill [NSColorPreferences::Get listHilite]
	} else {
		set fill [NSColorPreferences::Get listInactive]
	}

	if $state {
		$canvas itemconfigure $idRect -outline $fill

	} else {
		$canvas itemconfigure $idRect -fill {} -outline {}
	}
}

# namespace eval NSIconBrowser
}


