// Copyright (C) 1997-2004 Alias Systems Corp.
// 
// The information in this file is provided for the exclusive use of the
// licensees of Alias.  Such users have the right to use, modify,
// and incorporate this code into other products for purposes authorized
// by the Alias license agreement, without fee.
// 
// ALIAS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
// EVENT SHALL ALIAS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

// Description:  This procedure is called to remove a bin from the 
//      hyper shade bin list. 
//
proc removeBinFromHyperShadeBinList(string $binName)
{
    if (!isValidBinName($binName))
    {
        // Invalid input.  Do not remove. 
        //
        return;
    } 

    string $binList = `getAttr defaultRenderGlobals.hyperShadeBinList`;

    // It is assumed that the bin names are separated by ";".  For
    // example "wood;metal;outdoors".
    //
    string $newBinList;
    int $removed = false;
    if ($binName == $binList)
    {
        // The bin name is the only item in the bin list.
        //
        $newBinList = ""; 
        $removed = true;
    }

    if (!$removed)
    {
        $newBinList = `substitute ("^"+$binName+";") $binList ""`;
        if ($newBinList != $binList)
        {
            // The binName occurred at the beginning of the bin list.
            //
            $removed = true;
        } 
    }

    if (!$removed)
    {
        $newBinList = `substitute (";"+$binName+"$") $binList ""`;
        if ($newBinList != $binList)
        {
            // The binName occurred at the end of the bin list.
            //
            $removed = true;
        }
    }

    if (!$removed)
    {
        $newBinList = `substitute (";"+$binName+";") $binList ";"`;
        if ($newBinList != $binList)
        {
            $removed = true;
        }
    }
    
    if (!$removed)
    {
        // The binName does not occur in the bin list.  Do nothing.
        //
        return;
    }   

    // Store the new bin list back into the render globals' attribute.
    //
    setAttr defaultRenderGlobals.hyperShadeBinList -type "string" $newBinList;
}

// Description:  This procedure is called to empty the content
//  of the given bin.
//
proc emptyBin(string $binName)
{
    // Get all shading nodes which belong to this bin.
    //
    string $nodes[];
    hyperShadeGetNodesInBins({$binName}, $nodes);

    // Remove these nodes from this bin.
    //
    binMembership -removeFromBin $binName $nodes;
}

// Description:  This procedure is called to rename a hyper shade bin.
//
global proc hyperShadeRenameBin(
    string $binButton,
    string $gridLayout)
{
    string $newBinName = promptForNewBinName();
   
    if ($newBinName == "")
    {
        // User changed their mind, and cancelled the rename action.
        //
        return;
    } 

    // Determine the old bin name.
    //
    string $oldBinName = `iconTextButton -q -label $binButton`;

    // Rename nodes belong to this bin.
    //
    renameBinForNodes($oldBinName, $newBinName);

    // UI change related to renaming the bin.
    // 
    setParent $gridLayout;

    // Change the bin button label.
    //
    iconTextButton -edit -label $newBinName $binButton; 

    // Rename the bin in the bin list.
    //
    renameBinInHyperShadeBinList($oldBinName, $newBinName);

    // Rename the bin in the selected bin list.
    //
    global string $gHyperShadeSelectedBinList[];
    int $renamed = renameWordInList($oldBinName, $newBinName, $gHyperShadeSelectedBinList);

    if ($renamed)
    {
        if (AWNumberOfOccurrencesInStringArray("Master Bin", $gHyperShadeSelectedBinList) == 0) 
        {
            // The "Master Bin" is not selected, one of the selected
            // bins is renamed.  We need to rebuild the filter.
            //
            refreshHyperShadePaneFrontTab("", false);
        }
    }
}

// Description:  This procedure is called to duplicate the bin
//  associated with the given $binButton.
//
global proc hyperShadeDuplicateBin(
    string $binButton, string $gridLayout)
{
    // Determine the name of the original bin.
    //
    string $originalBinName = `iconTextButton -q -label $binButton`;

    // Create a new bin using the original name with an unique index
    // added at the end of the name.
    //
    string $newBinName = hyperShadeCreateNewBin($gridLayout, $originalBinName);

    // Copy the content of the original bin to the new bin.
    //
    string $nodes[];
    hyperShadeGetNodesInBins({$originalBinName}, $nodes); 
    binMembership -addToBin $newBinName $nodes;
}

// Description:  This procedure is called to add selected
//      object to all selected bins.
//
proc addSelectedObjectToBins(string $binList[])
{
    // Get selection.
    //
    string $selectedNodes[];
    hyperShadeGetSelectedNodes($selectedNodes);

    string $binName;
    for ($binName in $binList)
    {
        // Add the selected nodes to this bin, if it is not
        // the master bin.
        //
        if ($binName != "Master Bin")
        {
            string $node;
            for ($node in $selectedNodes)
            {
                // Put this node and all its upstream render nodes
                // in the bin.
                //
                hyperShadeAddNodeAndUpstreamNodesToBin($binName, $node);

            }
        }
    }

    binMembership -notifyChanged; 
}

// Description:
//
global proc addSelectedObjectToThisBin(string $binButton)
{
    string $originalBinName = `iconTextButton -q -label $binButton`;
	addSelectedObjectToBins({$originalBinName});
}

// Description:  This procedure is called to remove selected
//      object from the selected bins.
//
proc removeSelectedObjectFromBins(string $binList[])
{

    string $binName;
    for ($binName in $binList)
    {
        // Remove the selected nodes to from this bin, if it is not
        // the master bin.
        //
        if ($binName != "Master Bin")
        {
            // Get selection.
            //
            string $selectedNodes[];
            hyperShadeGetSelectedNodes($selectedNodes);

            if (size($selectedNodes) == 0)
            {
                // No relavent node is selected.
                //
                if (`optionVar -query hsBinsSortShadingNodesOnly`)
                {
                    warning("Remove selected from bin "+$binName+": no shading nodes are selected");
                }
                else
                {
                    warning("Remove selected from bin "+$binName+": no nodes are selected");
                }
            }
            else
            {
                string $removedNodes[] = `binMembership -removeFromBin $binName $selectedNodes`;
                

                if (size($removedNodes) == 0)
                {
                    print("// No node is removed from bin "+$binName+".\n");
                }
                else
                {
                    // Give user feedback on which nodes are removed from
                    // the bin.
                    // 
                    string $nodes = ""; 
                    string $node;
                    for ($node in $removedNodes)
                    {
                        $nodes += $node + " ";
                    }
                    print("// The nodes "+$nodes+"are removed from the bin "+$binName+"\n");
                }
            }
        }
    }
    
    binMembership -notifyChanged;
}

// Description:
//
global proc removeSelectedObjectFromThisBin(string $binButton)
{
    string $originalBinName = `iconTextButton -q -label $binButton`;
	removeSelectedObjectFromBins({$originalBinName});
}

// Description:  This procedure is called to select the content of
//  the selected bins.
//
proc selectContentOfBins (string $binList[])
{
    string $nodes[];

    // The master bin is not selected.  Get all the nodes in
    // the selected bins.
    //
    hyperShadeGetNodesInBins($binList, $nodes);

    if (size($nodes) > 0) {
        select -ne $nodes;
    } else {
        select -clear;
    }
}

// Description:
//
global proc selectContentOfThisBin(string $binButton)
{
    string $originalBinName = `iconTextButton -q -label $binButton`;
	selectContentOfBins({$originalBinName});
}

// Description:  This procedure is called when a hyper shade bin
//      button's empty bin popup menu item is pressed and we
//      need to repond to it.
//
proc hyperShadeEmptyBinsCallback(string $binList[])
{
    string $binName;
    for ($binName in $binList)
    {
        // Empty the bin if it is not the master bin.
        //
        if ($binName != "Master Bin")
        {
            emptyBin($binName);
        }
    }

    binMembership -notifyChanged; 
}

// Description:
//
global proc hyperShadeEmptyThisBins(string $binButton)
{
    string $originalBinName = `iconTextButton -q -label $binButton`;
	hyperShadeEmptyBinsCallback({$originalBinName});
}

// Description:  This procedure is called to make the selected items
//      belong exclusively to the bin specified by the given bin UI.
//
global proc hyperShadeMakeSelectedExclusive(string $binButton)
{
    // Determine the name of the original bin.
    //
    string $binName = `iconTextButton -q -label $binButton`;

    // Get selected.
    //
    string $selectedNodes[];
    hyperShadeGetSelectedNodes($selectedNodes); 

    binMembership -makeExclusive $binName $selectedNodes;

    binMembership -notifyChanged; 
}

// Description:  This procedure is called to delete the given bins.
//
global proc hyperShadeDeleteThisBin(string $binButton)
{
    string $binName = `iconTextButton -q -label $binButton`;

    // Empty the bin.
    //
    emptyBin($binName);


    // Remove bin from the bin list.
    //
    removeBinFromHyperShadeBinList($binName);

    // Remove the bin from the selection list.
    //
    global string $gHyperShadeSelectedBinList[]; 
    int $oldLengthOfSelectedBinList = size($gHyperShadeSelectedBinList);
    $gHyperShadeSelectedBinList = AWRemoveStringsFromStringArray(
        {$binName}, $gHyperShadeSelectedBinList);
    int $newLengthOfSelectedBinList = size($gHyperShadeSelectedBinList);

    if ($oldLengthOfSelectedBinList == 1 && $newLengthOfSelectedBinList == 0)
    {
        // The deleted bin is the only one previously selected, now
        // nothing is selected, refresh the front tabs to show the
        // content of the "Master Bin".
        //
        refreshHyperShadePaneFrontTab("", true);
    } 
    else if ($oldLengthOfSelectedBinList > $newLengthOfSelectedBinList)
    {
        // The deleted bin is removed from the selected bin list.
        // If the "Master Bin" is not in the selected bin list, then
        // we need to refresh.
        //
        if (AWNumberOfOccurrencesInStringArray("Master Bin", $gHyperShadeSelectedBinList) == 0)
        {
            binMembership -notifyChanged;
        }
    }

    // Remove the bin UI using an idle event.
    //
    evalDeferred("deleteUI "+$binButton);
}

global proc hyperShadeBinPopupMenuUI(
    string $menu, string $binButton, 
    string $gridLayout)
//
//	Description:
//		This procedure is called when the popup menu on a
//      bin buttons is shown.
//
//		Create the menu items.
//
//	Arguments:
//		$menu  - The parent menu.
//
//		$binButton - The full path name to the button.
//
//      $gridLayout - The full path name to the gridLayout which 
//                    contains the button.
//
{
	//	Set the menu parent and delete all the items in the menu.
	//
	setParent -menu $menu;
	menu -edit -deleteAllItems $menu;

	//
	//	Create the menu items...
	//

	// Bin name
	//
	string $binName = `iconTextButton -q -label $binButton`;
	menuItem -label $binName;

	menuItem -divider true;
	menuItem -divider true;
	menuItem -divider true;

    //
    // Bin's Content-oriented Operations.
    //

    // Add the selected items to this bin.
    //
    menuItem -label "Add Selected"
        -command ("addSelectedObjectToThisBin "+$binButton);

    // Remove the selected items from this bin.
    //
    menuItem -label "Remove Selected"
        -command ("removeSelectedObjectFromThisBin "+$binButton);

    // Select the content of the selected bins. 
    //
    menuItem -label "Select Content"
        -command ("selectContentOfThisBin "+$binButton);

	// Make selected exclusively belonging to this bin. 
	//
	menuItem -label "Make Selected Exclusive" 
        -command ("hyperShadeMakeSelectedExclusive "+$binButton);


    menuItem -divider true;

    //
    // Bin-oriented Operations.
    //

	// Rename this bin. 
	//
	menuItem -label "Rename" 
        -command ("hyperShadeRenameBin "+$binButton+" "+$gridLayout);

	// Duplicate this bin. 
	//
	menuItem -label "Duplicate" 
        -command ("hyperShadeDuplicateBin "+$binButton+" "+$gridLayout);

    // Empty the bins.
    //
    menuItem -label "Empty"
        -command ("hyperShadeEmptyThisBins "+$binButton);

	// Delete this bin. 
	//
	menuItem -label "Delete" 
        -command ("hyperShadeDeleteThisBin "+$binButton);
}
