# $Revision$ on $Date$
# The above revision line needs to be the first line for all techtk files
# Copyright (c) 2006 Ansys Inc

#----------------------------------------------------------------------------
#
# PADT---------------------------------------------------- Phoenix Analysis &
#                                                         Design Technologies
#
#----------------------------------------------------------------------------
#
#       Package: AI-Environment GUI Management
#
#
#          File: dropdown_button.tcl
#
#
#	  Developer: Matt Sutton
#
#
#   Description: This file contains the implementation of a dropdown button
#                widget. 
#        
#
#      03/25/02: Demo release 1. Implemented using a dropdown menu. Clunky, not
#                                fully functional.
#
#			
#
#-----------------------------------------------------------------------------
# For support: 1-480-813-4884 ext. 125 -or- matt.sutton@padtinc.com
#-----------------------------------------------------------------------------
#
# modified 3/30/2004 -- Matt Middleton
# Revision 2: 3/7/2005 -- for handling different arrow button sizes
#

namespace eval ::AIEnv {}
namespace eval ::AIEnv::GUIManagement {}
namespace eval ::AIEnv::GUIManagement::Widgets {} 

namespace eval ::AIEnv::GUIManagement::Widgets::DropdownButton {
	variable Dropdowns
	variable counter
	
	variable commands [list add destroy create]

	set Dropdowns(ImageArrow1) [list 2 2 5 5 9 2]
	set Dropdowns(ImageArrow2) [list 2 2 6 6 10 2]
	set Dropdowns(ImageArrow3) [list 2 2 7 7 11 2]

	namespace export DropdownButton
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::DropdownButton {{name ""}} {
	variable Dropdowns
	variable counter
	
	if { [llength [info level 0]] == 1 } {
		incr counter
		set name "dropdown${counter}"
	}
	
	if { ![string equal [info commands ::$name] ""] } {
		error "Command \"$name\" already exists, unable to create the Dropdown"
	}
	
	# Initialize the data structure
	
	# Create the command to manipulate the dropdown
	interp alias {} ::$name {} ::AIEnv::GUIManagement::Widgets::DropdownButton::DropdownProc $name
	return $name
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::DropdownProc {name {cmd ""} args} {
	# Check for argument consistency
	if { [llength [info level 0]] == 2 } {
		error "Wrong # args: should be \"$name option ?arg arg ...?\""	
	}
	
	if { [string equal [info commands ::AIEnv::GUIManagement::Widgets::DropdownButton::_$cmd] ""] } {
		variable commands
		set optlist [join $commands ", "]
		set optlist [linsert $optlist "end-1" "or"]
		error "Bad option \"$cmd\": must be $optlist"
	}
	return [eval [list ::AIEnv::GUIManagement::Widgets::DropdownButton::_$cmd $name] $args]
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::_add {name args} {
	variable Dropdowns
	global toolBarInfo
	
	if { [llength $args] < 3 } {
		error "Wrong # args: should be \"$name add image_normal tooltip proc\""
	}
	
	set ImageNorm [lindex $args 0]
	set ToolTip [lindex $args 1]
	set Proc [lindex $args 2]
	
	if { ![info exists Dropdowns("$name-BuildIndex")] } {
		set Dropdowns("$name-BuildIndex") 0
		set Dropdowns("$name-HolderProc") $Proc
		# Set the image of the placeholder to the first button
		$Dropdowns("$name-ButtonPlaceHolder") configure -image $ImageNorm -helptext $ToolTip
		set wi [image width $ImageNorm]
		if {$wi < 25} {set i 1} \
		elseif {$wi < 36} {set i 2} \
		else {set i 3}
		set Dropdowns("$name-Arrow") [canvas $Dropdowns("$name-Parent").arrow-$name -bd 1 \
			-relief raised -highlightthickness 0 -takefocus 0]
		$Dropdowns("$name-Arrow") create polygon $Dropdowns(ImageArrow$i) -outline black -fill black -width 1 -tags arrow
		foreach {x1 y1 x2 y2} [$Dropdowns("$name-Arrow") bbox arrow] break
		$Dropdowns("$name-Arrow") configure -width [expr {$x2 - $x1 - 1}] -height [expr {$y2 - $y1 - 1}]
		place $Dropdowns("$name-Arrow") -in $Dropdowns("$name-ButtonPlaceHolder") -relx 1 -x -1 -rely 1 -y -1 -anchor se
		bind $Dropdowns("$name-Arrow") <ButtonPress-1> \
			"::AIEnv::GUIManagement::Widgets::DropdownButton::ArrowPress $name"
	} else {
		incr Dropdowns("$name-BuildIndex")
	}
	
	set Index $Dropdowns("$name-BuildIndex")
	set Dropdowns("$name-$Index-ImageNorm") $ImageNorm
	set Dropdowns("$name-$Index-ToolTip") $ToolTip
	set Dropdowns("$name-$Index-Proc") $Proc
		
	set but [button $Dropdowns("$name-Popup").$Index -image $ImageNorm -takefocus 0 -bd 1 \
		-command "::AIEnv::GUIManagement::Widgets::DropdownButton::OnSelectButton $name $Index"]
	pack $but -anchor w -side top -padx 1 -pady 1
	# Remove the default class bindings so they are controlled by the toplevel
	bindtags $but "$but $Dropdowns(\"$name-Popup\") all"
	# set the BwHelpBalloon binding tag and register the bubble help text
	DynamicHelp::register $but balloon $ToolTip
	set toolBarInfo(dropButton,"$ToolTip") $name
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::_create {name ParentToolbar} {
	variable Dropdowns

	# This procedure basically creates our own menubutton and menu widgets	
	set Dropdowns("$name-Parent") $ParentToolbar
	set Dropdowns("$name-ButtonPlaceHolder") [$ParentToolbar add -highlightthickness 0 -takefocus 0 \
		-relief link -borderwidth 1 -padx 0 -pady 0]

	set Dropdowns("$name-Popup") [toplevel .popup-$name -bd 2 -relief raised -takefocus 0 -class popup \
		-screen [winfo screen $Dropdowns("$name-ButtonPlaceHolder")] -cursor arrow]
	wm withdraw $Dropdowns("$name-Popup")
	wm overrideredirect $Dropdowns("$name-Popup") 1
	wm transient $Dropdowns("$name-Popup")

	bind $Dropdowns("$name-ButtonPlaceHolder") <ButtonPress-1> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbPress $name %W %X %Y %b %s; break"
	bind $Dropdowns("$name-ButtonPlaceHolder") <ButtonRelease-1> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbRelease $name %X %Y %b %s; break"
	bind $Dropdowns("$name-Popup") <Enter> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbMotion $name %X %Y"
	bind $Dropdowns("$name-Popup") <Leave> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbMotion $name %X %Y"
	bind $Dropdowns("$name-Popup") <ButtonRelease> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbRelease $name %X %Y %b %s"
	bind $Dropdowns("$name-Popup") <B1-Motion> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbMotion $name %X %Y"
	bind $Dropdowns("$name-Popup") <ButtonPress> \
		"::AIEnv::GUIManagement::Widgets::DropdownButton::MbPress $name %W %X %Y %b 0"
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::_destroy {name} {
	variable Dropdowns
	
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::ButtonDown {name} {
	variable Dropdowns

	set x [winfo rootx $Dropdowns("$name-ButtonPlaceHolder")]
	set y [winfo rooty $Dropdowns("$name-ButtonPlaceHolder")]
	set h [winfo height $Dropdowns("$name-ButtonPlaceHolder")]
	set y [expr {$y + $h +1}]

	foreach w [winfo children $Dropdowns("$name-Popup")] {
		$w configure -relief flat
	}
	set Dropdowns(ActiveSelection) ""
	wm geometry $Dropdowns("$name-Popup") +$x+$y
	wm deiconify $Dropdowns("$name-Popup")
	raise $Dropdowns("$name-Popup")

	set Dropdowns(prevGrab) [grab current $Dropdowns("$name-Popup")]
	if {[string compare $Dropdowns(prevGrab) ""]} {
		set Dropdowns(prevStatus) [grab status $Dropdowns(prevGrab)]
		grab release $Dropdowns(prevGrab)
	}
	grab set -global $Dropdowns("$name-Popup")

	global use_workbench
	if {[info exists use_workbench] && $use_workbench == 1} {
		after cancel ::AIEnv::GUIManagement::AIEnvInWB_FixEvents
	}
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::ButtonUp {name {X ""} {Y ""} {event ""} {but ""} {state ""}} {
	variable Dropdowns

	if {[info exists Dropdowns(bDownID)] && ![catch {after info $Dropdowns(bDownID)}]} {
		after cancel $Dropdowns(bDownID)
		unset Dropdowns(bDownID)
		::AIEnv::GUIManagement::toolBarSelect $Dropdowns("$name-Parent") $Dropdowns("$name-ButtonPlaceHolder") 1
#		$Dropdowns("$name-ButtonPlaceHolder") configure -relief link
		eval $Dropdowns("$name-HolderProc")
		return 1
	}

	if ![winfo ismapped $Dropdowns("$name-Popup")] {return 2}

	if {[info exists Dropdowns(ArrowPressed)]} {
		$Dropdowns("$name-Arrow") configure -relief raised
	}

	if {[string compare $X ""] && [string compare $Y ""]} {
		set w [winfo containing $X $Y]
		if {[string equal $w $Dropdowns("$name-ButtonPlaceHolder")] || \
			[string equal $w $Dropdowns("$name-Arrow")]} {return 1}
		if {![catch {winfo parent $w} parent] && [string equal $parent $Dropdowns("$name-Popup")]} {return 0}
	}

	wm withdraw $Dropdowns("$name-Popup")
	if ![info exists Dropdowns(ArrowPressed)] {
		::AIEnv::GUIManagement::toolBarSelect $Dropdowns("$name-Parent") $Dropdowns("$name-ButtonPlaceHolder") 1
#		$Dropdowns("$name-ButtonPlaceHolder") configure -relief link
		event generate $Dropdowns("$name-ButtonPlaceHolder") <Leave> -when tail
	}

	set grab [grab current $Dropdowns("$name-Popup")]
	if {[string equal $grab $Dropdowns("$name-Popup")]} {
		grab release $grab
		if {[string compare $Dropdowns(prevGrab) ""]} {
			catch {
				if {[string equal $Dropdowns(prevStatus) "global"]} {
					grab set -global $Dropdowns(prevGrab)
				} else {
					grab set $Dropdowns(prevGrab)
				}
			}
		}
		set Dropdowns(prevGrab) ""
	}

	global use_workbench
	if {[info exists use_workbench] && $use_workbench == 1} {
		::AIEnv::GUIManagement::AIEnvInWB_FixEvents
	}

	if {[string compare $X ""] && [string compare $Y ""] && [string compare $event ""] && [string compare $but ""] && [string compare $state ""]} {

		# this is a work-a-round so that we can use a state of zero for ButtonPress events
		if {[string equal $event "ButtonPress"] || [string equal $event "Button"]} {
			event generate $Dropdowns("$name-Popup") <ButtonRelease> -button $but -x 0 -y 0 -state 256 -when tail
		}

		set w [winfo containing $X $Y]
		if {[string compare $w ""]} {
			set x [expr {$X - [winfo rootx $w]}]
			set y [expr {$Y - [winfo rooty $w]}]
			event generate $w <$event> -button $but -rootx $X -rooty $Y -x $x -y $y -state $state -when tail
		} else {event generate $w <$event> -button $but -rootx $X -rooty $Y -state $state -when tail}
	}

	return 2
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::OnSelectButton {name index {skip 0}} {
	variable Dropdowns

	ButtonUp $name
	$Dropdowns("$name-Arrow") configure -relief raised
	$Dropdowns("$name-ButtonPlaceHolder") configure -image $Dropdowns("$name-$index-ImageNorm") -helptext $Dropdowns("$name-$index-ToolTip")
	set Dropdowns("$name-HolderProc") $Dropdowns("$name-$index-Proc")
	# Call the user's proc
	if !$skip { eval $Dropdowns("$name-$index-Proc") }
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::MbMotion {name X Y} {
	variable Dropdowns

	set w [winfo containing $X $Y]
	set e [info exists Dropdowns(ActiveSelection)]

	if {($e && [string equal $w $Dropdowns(ActiveSelection)]) || [catch {winfo parent $w} parent]} return
	if {[string compare $parent $Dropdowns("$name-Popup")]} {
		if {$e && [string compare $Dropdowns(ActiveSelection) ""]} {
			$Dropdowns(ActiveSelection) configure -relief flat
			set Dropdowns(ActiveSelection) ""
		}
		return
	}
	if {$e && [string compare $Dropdowns(ActiveSelection) ""]} {$Dropdowns(ActiveSelection) configure -relief flat}
	$w configure -relief sunken
	set Dropdowns(ActiveSelection) $w
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::MbRelease {name X Y but state} {
	variable Dropdowns

	set w [winfo containing $X $Y]
	if {$but == 1 && [string equal $w $Dropdowns("$name-ButtonPlaceHolder")] && [info exists Dropdowns(LastWindowPress)] && \
			[string equal $Dropdowns(LastWindowPress) $Dropdowns("$name-ButtonPlaceHolder")] && \
			(![info exists Dropdowns(bDownID)] || [catch {after info $Dropdowns(bDownID)}]) && \
			![info exists Dropdowns(ArrowPressed)]} {
		ButtonUp $name
		eval $Dropdowns("$name-HolderProc")
		return
	}

	set ret [ButtonUp $name $X $Y ButtonRelease $but $state]
	if {!$ret && $but == 1} {$w invoke; set ret 2}
	if {$ret == 2} {catch {unset Dropdowns(ArrowPressed)}}
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::MbPress {name W X Y but state} {
	variable Dropdowns

	if {[string equal $W $Dropdowns("$name-ButtonPlaceHolder")]} {
		set Dropdowns(LastWindowPress) $W
		::AIEnv::GUIManagement::toolBarSelect $Dropdowns("$name-Parent") $W
#		$Dropdowns("$name-ButtonPlaceHolder") configure -relief sunken
		set Dropdowns(bDownID) [after 300 "::AIEnv::GUIManagement::Widgets::DropdownButton::ButtonDown $name"]
		return
	}
	set w [winfo containing $X $Y]
	set Dropdowns(LastWindowPress) $w

	set ret [ButtonUp $name $X $Y ButtonPress $but $state]
	if {!$ret && $but == 1} {MbMotion $name $X $Y}
	if {$ret == 2} {catch {unset Dropdowns(ArrowPressed)}}
}

proc ::AIEnv::GUIManagement::Widgets::DropdownButton::ArrowPress {name} {
	variable Dropdowns

	$Dropdowns("$name-Arrow") configure -relief sunken
	ButtonDown $name
	set Dropdowns(ArrowPressed) 1
}

