//=============================================================================
//
// ToolpathTableFunctions.js   
//
// Implementation of the functions used to create and manage
// the toolpath manager table in js.
//
// ----------------------------------------------------------------------------
// COPYRIGHT 2000 DELCAM PLC., BIRMINGHAM, ENGLAND. 
// ----------------------------------------------------------------------------
//
// History.
// Who When       What   
// --- -------- ---------------------------------------------------------------
// ejp 18/02/02 Written
// ejp 28/08/02 Replaced insertCell() to avid IE6 bug
// pah 24/06/04 Added 2D solid/wire options, commented out old unused functions
// pah 13/07/04 Added "virtual" toolpath colour change method:
//              OnToolpathColorChange()
//              Support conditional solid preview shading
// pah 23/02/05 Adjust for system scrollbar width in ToggleHeaderSpacingForScrollBar()
// pah 18/12/06 Fix crash in ChangeToolpathSelection when oa_toolpath is null
// sgc 06/03/07 If changing toolpaths on the Toolpath Transform page then update the 
//              toolpath position before changing
// sgc 01/06/07 Don't add uncalculated toolpaths to the list when on transform page
// sgc 11/07/07 Fixed GetSelectionAfterDeleting so it correctly works for last toolpath
//-----------------------------------------------------------------------------

//=== AddToolpathToTable ======================================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// ejp 18/02/02 Written
// sap 27/08/02 optimised
// bem 28/10/02 Add default handling for 'old' 5.1 and earlier toolpaths
// sgc 01/06/07 Don't add uncalculated toolpaths to the list when on transform page
//-----------------------------------------------------------------------------

function AddToolpathToTable(oa_toolpath)
{
   var new_table_string = "";

   var toolpath_type = '';
   
   var num_children = oa_toolpath.GetNumberOfChildren();
   
   // create heading row if toolpath has children
   if (num_children > 0)
      {     
      new_table_string = CreateToolpathTableEntry(oa_toolpath);
      //alert( new_table_string );
      return new_table_string;
      //cur_child = oa_toolpath.GetChild(0);
      }
   else
      {
      // Check if a 'template_group'
      if ( oa_toolpath.IsGroup() && (oa_toolpath.GetNumToolpathParams()>0) )
         {
         // Don't add uncalculated toolpaths to the list when on the transform page
         if(window.document.title != "Toolpath Transform")
         {
            new_table_string += AddToolpathParamToTable(oa_toolpath);
         }
         return new_table_string;
         }
      else
         {
         new_table_string = CreateToolpathTableEntry(oa_toolpath);
         }
      }
   
   return new_table_string;

}



//=== AddToolpathParamToTable =================================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// sap 27/08/02 Written
//-----------------------------------------------------------------------

function AddToolpathParamToTable(oa_toolpathgroup)
{   
   var num_children = oa_toolpathgroup.GetNumToolpathParams();
   var cur_child_index = 0;
   var toolpath_type = 'template_group';
   var cur_child = null;

   if (num_children > 0)
   {     
      cur_child = oa_toolpathgroup.GetToolpathParam(0);
      cur_child_index = 1;
   }

   var type_color = gTemplateTextColor;
   if (!oa_toolpathgroup.IsLicenced())
      type_color = gUnlicencedToolpathColor;

   var new_html = "<tr id=" + oa_toolpathgroup.Id + " toolpathtype=" 
                     + toolpath_type +" style='color:" 
                     + type_color + "'>" +
                     "<td colspan=4 onclick='OnSelectRow()' ondblclick='OnEditRow()' onselectstart='OnSelectObject()'>" +
                     "<b>[" + oa_toolpathgroup.Name + "]</b></td><td>&nbsp;</td></tr>";

   toolpath_type = 'template';
   // now create rows for actual toolpaths - always at least 1 
   while (cur_child != null)
   {
      /*if(cur_child.Has3DToolpath())
      {
         toolpath_type = 'toolpath';
      }
      else
         toolpath_type = 'uncalculated_toolpath';*/
      
      new_html += "<tr id=" + cur_child.Id +
         " toolpathtype=" + toolpath_type +
         " style='color:" + type_color + 
         "'><td ondblclick='OnEditRow()' >&nbsp;</td>" +
         "<td onclick='OnSelectTemplateRow()' ondblclick='OnEditRow()'>" + cur_child.Tool.Description + "</td>";

      new_html += "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>";
         
      // onto next child if any
      if ( cur_child_index >= num_children )
      {
         cur_child = null;
      }
      else
      {
         cur_child = oa_toolpathgroup.GetToolpathParam(cur_child_index);
         cur_child_index++
      }
   }
   
   
   return new_html;
}

//=== CreateToolpathTableHeader ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/02/02 Written
//-----------------------------------------------------------------------

function CreateToolpathTableHeader(oa_toolpath, toolpath_type)
{
   var num_toolpaths = ToolpathTable.rows.length;
   
   var new_tr = ToolpathTable.insertRow(num_toolpaths);
   if (new_tr == null)
   {
      //artcam.Alert("AddToolpath - failed to add parent row",1);
      return;
   }
   
   var row   = ToolpathTable.rows(num_toolpaths);
   if (row == null)
   {
      //artcam.Alert("AddToolpath - failed to retrieve parent row",1);
      return;
   }
   row.id = oa_toolpath.Id;    
   row.toolpathtype = toolpath_type;
   
   if( (row.toolpathtype == 'template_group') || (row.toolpathtype == 'uncalculated_group'))
      row.style.color = gTemplateTextColor;
   else
      row.style.color = gTextColor;
      
   if (!oa_toolpath.IsLicenced())  
      row.style.color = gUnlicencedToolpathColor;
   
   var cells = row.cells;
   
   // insert td spanning all 4 columns
   //var new_td = row.insertCell(cells.length);
   var new_td = document.createElement("<td></td>");
   row.appendChild(new_td);

   if (new_td == null)
   {
      //artcam.Alert("AddToolpath - failed to add parent cell",1);
      return;
   }
   // make td span 4 columns and set html
   new_td.colSpan=4;
   new_td.innerHTML="<b>[" + oa_toolpath.Name + "]</b>";
   //new_td.innerHTML="<b>[" + oa_toolpath.Name + "-" + row.toolpathtype +"]</b>";
   new_td.onclick=OnSelectRow;
   new_td.ondblclick=OnEditRow;
   new_td.onselectstart=OnSelectObject;
   
   // ### 5th TD - space
   //new_td = row.insertCell(cells.length);
   new_td = document.createElement("<td></td>");
   row.appendChild(new_td);

   if (new_td == null)
   {
      //artcam.Alert("AddToolpath - failed to add 5th cell",1);
      return;
   }
   new_td.innerHTML="&nbsp;";
}


//=== CreateToolpathTableEntry ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// sap 27/08/02 Written
// pah 13/07/04 If no preview, still draw checkbox but disable it
// bem 20/09/04 For rotated toolpaths prefix by angle
//-----------------------------------------------------------------------

function CreateToolpathTableEntry(oa_toolpath)
{
   var num_children = oa_toolpath.GetNumberOfChildren();
   var cur_child_index = 0;
   var toolpath_type = 'group';
   var cur_child = null;

   if (num_children > 0)
   {     
      cur_child = oa_toolpath.GetChild(0);
      cur_child_index = 1;
      if(!cur_child.Has3DToolpath())
         toolpath_type = 'uncalculated_group';
   }

   var type_color = gTextColor;

   if( (toolpath_type == 'template_group') || (toolpath_type == 'uncalculated_group'))
      type_color = gTemplateTextColor;
      
   if (!oa_toolpath.IsLicenced())  
      type_color = gUnlicencedToolpathColor;      

   var new_html = "<tr id=" + oa_toolpath.Id + " toolpathtype=" + toolpath_type +" style='color:";
   
   new_html += type_color + "'><td colspan=4 onclick='OnSelectRow()' ondblclick='OnEditRow()' onselectstart='OnSelectObject()'><b>";
   // if toolpath is indexed prefix name with angle in curly brackets e.g {180}
   if (oa_toolpath.RotaryAIndex != 0.0)
      new_html += "{" + oa_toolpath.RotaryAIndex + "} ";
   new_html += "[" + oa_toolpath.Name + "]</b></td><td>&nbsp;</td></tr>";


   // now create rows for actual toolpaths - always at least 1 
   while (cur_child != null)
   {
      if(cur_child.Has3DToolpath())
      {
         toolpath_type = 'toolpath';
         type_color = gTextColor;
      }
      else
      {
         toolpath_type = 'uncalculated_toolpath';
         type_color = gTemplateTextColor;
      }
      if (!cur_child.IsLicenced())  
         type_color = gUnlicencedToolpathColor;
      
      new_html += "<tr id=" + cur_child.Id +
         " toolpathtype=" + toolpath_type +
         " style='color:" + type_color + 
         "'><td ondblclick='OnEditRow()' >&nbsp;</td>" +
         "<td onclick='OnSelectRow()' ondblclick='OnEditRow()' onselectstart='OnSelectObject()'>" + cur_child.Name + "</td>";

      //if( (toolpath_type == 'toolpath') && (cur_child.Has2DPreview()) )
      if( (toolpath_type == 'toolpath') )
      {
         var preview = cur_child.Has2DPreview();
         
         if (artcam.IsSolidDrawEnabled()) {
            // Color control
            // ID of color object is "color" + row id
            var id = "color" + cur_child.Id;
            new_html += "<td><object id='"+id+"' classid='CLSID:F63AF1A5-2FD3-11D4-A7EB-009027932721' width='17' height='13' VIEWASTEXT></object></td>";
            
            // Color click method passes toolpath Id - but only if it has a preview
            if (preview)
               new_html += "<script language='javascript' for='"+id+"' event='OnClick'>OnClickColorThumbnail('"+cur_child.Id+"')</script>";
         }               

         // 2D visibility checkbox        
         new_html += "<td><input type=checkbox style='HEIGHT: 13px; WIDTH: 13px; margin-right:5px;' onclick='OnToggle2D()'";
         
         // Set status of checkbox
         if (preview) {
            // Preview exists - set visibility of preview
            if (cur_child.Visible2D)
               new_html += " checked></td>";
            else
               new_html += "></td>";
               
         } else {
            // No preview so disable the control
            new_html += "disabled></td>";
         }
      }
      else   
      {
         if( (toolpath_type == 'template') || (toolpath_type == 'uncalculated_toolpath'))
         {
            new_html += "<td>&nbsp;</td>";
         }
         else
            new_html += "<td><input type=checkbox style='HEIGHT: 13px; WIDTH: 13px;' disabled></td>";         
      }
      
      if( (toolpath_type == 'toolpath') && (cur_child.Has3DToolpath()) )
      {
         // 3D visibility
         new_html += "<td><input type=checkbox style='HEIGHT: 13px; WIDTH: 13px' onclick='OnToggle3D()'";
         if (cur_child.Visible3D)
            new_html += " checked></td>";
         else
            new_html += "></td>";    
      }
      else
      {
         if( (toolpath_type == 'template') || (toolpath_type == 'uncalculated_toolpath'))
         {
            new_html += "<td>&nbsp;</td>";
         }
         else
            new_html += "<td><input type=checkbox style='HEIGHT: 13px; WIDTH: 13px;' disabled></td>";         
      }

      new_html += "<td>&nbsp;</td></tr>";
         
      // onto next child if any
      if ( cur_child_index >= num_children )
      {
         cur_child = null;
      }
      else
      {
         cur_child = oa_toolpath.GetChild(cur_child_index);
         cur_child_index++
      }
   }
   
   
   return new_html;
}



// --------------------------------------------------------------
// --------------------- Toolpath Removal -----------------------
// --------------------------------------------------------------

// === OnRemoveSelectedToolpath =======================================
//
// Remove selected toolpath from table
//
function OnRemoveSelectedToolpath()
{
   if (gSelectedToolpathGuid == '')
      return;
   
   RemoveToolpathAndChildren(gSelectedToolpathGuid);
   gSelectedToolpathGuid = '';
   gSelectedToolpathType = '';
}

// === RemoveToolpathAndChildren =======================================
//
// Remove passed toolpath and children from table
//
function RemoveToolpathAndChildren(toolpath_id)
{
   if (gSelectedToolpathGuid == toolpath_id)
   {
      gSelectedToolpathGuid = '';
      gSelectedToolpathType = '';
   }
   
   var toolpath_type = GetToolpathType(toolpath_id);
   var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
   
   switch(toolpath_type)
   {
   case 'group':
   case 'uncalculated_group':
      RemoveToolpath(oa_toolpath.Id);
      var num_children = oa_toolpath.GetNumberOfChildren();
      for (var i = 0; i < num_children; i++)
      {
         var cur_toolpath = oa_toolpath.GetChild(i);
         if (cur_toolpath != null)
         {
            RemoveToolpath(cur_toolpath.Id);
         }
      }
      break;
      
   case 'template_group':
      RemoveToolpath(oa_toolpath.Id);
      var num_of_params = oa_toolpath.GetNumToolpathParams();
      for(var index = 0;index<num_of_params;index++)
      {
         var oa_param = oa_toolpath.GetToolpathParam(index);
         if (oa_param != null)
         {
            //artcam.Alert("Removing Template via group",0);
            RemoveToolpath(oa_param.Id);
         } 
      }
      break;
      
   case 'toolpath':
   case 'uncalculated_toolpath':
   case 'template':
      return RemoveToolpath(toolpath_id);
      break;
   default:
      {
      //artcam.Alert("RemoveToolpathAndChildren: Unknown Toolpath Type: " + toolpath_type, 0);
      }
   }
}


// === RemoveToolpath =======================================
//
// Remove passed toolpath from table
//

function RemoveToolpath(toolpath_id)
{
   // artcam.Alert("RemoveToolpath :" + toolpath_id, 0);
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         ToolpathTable.rows(i).removeNode(true);
         //artcam.Alert("removed toolpath:" + toolpath_id + " on row:" + i, 0);
         return true;
      }
   }
   
   return false;
}

// --------------------------------------------------------------
// ---------------------- Table Searching -----------------------
// --------------------------------------------------------------

//=== FindParent ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/02/02 Written
//-----------------------------------------------------------------------

function FindParent(toolpath_id)
{
   //artcam.Alert('FindParent : id = ' + toolpath_id, 0);
   // Step through the table
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      // When we find the toolpath...
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         // Get its type
         switch(ToolpathTable.rows(i).toolpathtype)
         {
         case 'uncalculated_group':
         case 'group':
         case 'template_group':
            // If it is already a parent type then return
            return ToolpathTable.rows(i).id;
            break;
            
         case 'toolpath':
            var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
            var parent_id = oa_toolpath.ParentId;
            if(parent_id =='')
               return toolpath_id;
            else
               return parent_id;
            break;

         case 'uncalculated_toolpath':
            while(i>0)
            {
               i--;
               //artcam.Alert('FindParent : Searching - ' + ToolpathTable.rows(i).toolpathtype + " - row = " + i, 0);
               if(ToolpathTable.rows(i).toolpathtype == 'uncalculated_group')
               {
                 //artcam.Alert('FindParent : Found parent on row ' + i, 0);
                 return ToolpathTable.rows(i).id;
               }             
            }
            //artcam.Alert('FindParent : Failed to find parent', 0);
            return toolpath_id;
            break;
            

         case 'template':
            // Otherwise step back up through the table
            // until a parent is found
            while(i>0)
            {
               i--;
               //artcam.Alert('FindParent : Searching - ' + ToolpathTable.rows(i).toolpathtype + " - row = " + i, 0);
               if(ToolpathTable.rows(i).toolpathtype == 'template_group')
               {
                 //artcam.Alert('FindParent : Found parent on row ' + i, 0);
                 return ToolpathTable.rows(i).id;
               }             
            }
            //artcam.Alert('FindParent : Failed to find template parent', 0);
            return toolpath_id;
            break;
         }
      }
   }
   return toolpath_id;
}

//=== FindToolpathTableRow ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/02/02 Written
//-----------------------------------------------------------------------

function FindToolpathTableRow(toolpath_id)
{
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         return i;
      }
   }
   return -1;
}

// === GetToolpathRow ====================================
//
// Get row in table for passed toolpath
//

function GetToolpathRow(toolpath_id)
{
   for(var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
         return ToolpathTable.rows(i);
   }
   return null; // didnt find passed toolpath
}

//=== GetToolpathType ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/02/02 Written
//-----------------------------------------------------------------------

function GetToolpathType(toolpath_id)
{
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         //artcam.Alert("GetToolpathType : ToolpathType = " + ToolpathTable.rows(i).toolpathtype, 0);
         return ToolpathTable.rows(i).toolpathtype;
      }
   }
   //artcam.Alert("GetToolpathType : Failed to find toolpath: " + toolpath_id, 0);
   return '';
}


// --------------------------------------------------------------
// -------------------- Toolpath Selection ----------------------
// --------------------------------------------------------------

// === OnSelectRow =====================================================
//
// Called when user clicks on a row
//

function OnSelectRow()
{   
   var oSource = window.event.srcElement ;
   if(window.document.title == "Toolpath Transform")
   {
      if(gTransform)
      {
         gTransform.UpdateToolpath();
      }
   }
   // we want the <TR> for this element
   while ((oSource != null) && (oSource.nodeName != 'TR'))
      oSource = oSource.parentNode;
   if (oSource == null)
      return;
   if(oSource.id == '')
   {
      //artcam.Alert('OnSelectRow : ID == NULL', 0);
   }
   SelectToolpathAndChildren(oSource.id);
   EnsureSelectedToolpathVisible();
   if(window.document.title == "Toolpath Transform")
   {
      if(gTransform)
      {
         gTransform.NewToolpathSelected();  
      }
   }
}

// === OnSelectTemplateRow =====================================================
//
// Called when user clicks on a row
//

function OnSelectTemplateRow()
{   
   var oSource = window.event.srcElement ;
   // we want the <TR> for this element
   while ((oSource != null) && (oSource.nodeName != 'TR'))
      oSource = oSource.parentNode;

   if (oSource == null)
      return;
   if(oSource.id == '')
   {
      //artcam.Alert('OnSelectTemplateRow : ID == NULL', 0);
   }

   var parentid = FindParent(oSource.id);
   SelectToolpathAndChildren(parentid);
   EnsureSelectedToolpathVisible();
}
// === OnSelectToolpath ================================
//
// Called from ArtCAM to select a toolpath 
//

function OnSelectToolpath(oa_toolpath)
{
   //artcam.Alert("OnSelectToolpath : " + oa_toolpath.Name, 0);
   if (oa_toolpath == null)
      return;

   SelectToolpathAndChildren(oa_toolpath.Id);
      
   EnsureSelectedToolpathVisible();
}

// === SelectToolpathAndChildren =====================================================
//
// Select row (and any child rows) for passed toolpath
//

function SelectToolpathAndChildren(toolpath_id)
{
   if(toolpath_id=='')
   {
      //artcam.Alert("SelectToolpathAndChildren : ToolpathID == NULL", 0);
   }
  
   if(gSelectedToolpathGuid!='')
   {
      // De-select Previous Toolpath
      if(!ChangeToolpathSelection(gSelectedToolpathGuid, false))
      {
         //artcam.Alert("SelectToolpathAndChildren : Failed to DE-SELECT Toolpaths", 0);
         return false;
      }
   }
   
   // Select New Toolpath
   if(!ChangeToolpathSelection(toolpath_id, true))
   {
      //artcam.Alert("SelectToolpathAndChildren : Failed to Select Toolpaths", 0);
      return false;
   }
   
   //artcam.Alert("SelectToolpathAndChildren : Calling GetToolpathType", 0);
   var toolpath_type = GetToolpathType(toolpath_id);

   switch(toolpath_type)
   {
   case 'group':
   case 'toolpath':
      var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
      UpdateToolpathHtml(oa_toolpath);
      break;
      
   case 'uncalculated_group':
   case 'uncalculated_toolpath':
   case 'template_group':
   case 'template':  
      UpdateToolpathHtml(null);
      break;    
   default:
      //artcam.Alert("SelectToolpathAndChildren : Unknown Toolpath Type: " + toolpath_type, 0);
      break;
   }
   artcam.SelectToolpathInTree(toolpath_id);
   return true; // selected toolpath ok
}

//=== ChangeToolpathSelection =================================================
//
// Change the selected toolpath.
// For uncalculated groups and templates this requires
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// ejp 18/02/02 Written
// pah 18/12/06 Fix crash when oa_toolpath is null
// pah 12/11/07 Draw unlicenced toolpaths in different colour
//-----------------------------------------------------------------------------
function ChangeToolpathSelection(toolpath_id, select)
{
   // Find the OA_Toolpath (if any)
   var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
   
   // Decide if it is unlicenced
   var colour_as_unlicenced = false;
   
   if (oa_toolpath && !oa_toolpath.IsLicenced())
      colour_as_unlicenced = true;
   
   // Select the passed toolpath
   SelectToolpath(toolpath_id, select, colour_as_unlicenced);
   
   // Select any sub-toolpaths according to type
   if (oa_toolpath) {
   
      //artcam.Alert('ChangeToolpathSelection : ToolpathType = ' + GetToolpathType(toolpath_id), 0);
      var toolpath_type = GetToolpathType(toolpath_id);

      switch(toolpath_type)
      {
      case 'template_group':               
         var num_params = oa_toolpath.GetNumToolpathParams();        
         for (var index = 0; index < num_params; index++)
         {
            var cur_param = oa_toolpath.GetToolpathParam(index);
            if (cur_param != null)
            {
               if(!SelectToolpath(cur_param.Id, select, colour_as_unlicenced))
               {
                  //artcam.Alert("ChangeToolpathSelection : Select Sub Toolpath Parameter Failed", 0);     
                  return false;
               }
            }
         }           
         break;
      
      case 'uncalculated_group':
      case 'group':            
         var num_children = oa_toolpath.GetNumberOfChildren();
         for (var i = 0; i < num_children; i++)
         {
            var cur_toolpath = oa_toolpath.GetChild(i);
            if (cur_toolpath != null)
            {
               if(!SelectToolpath(cur_toolpath.Id, select, colour_as_unlicenced))
               {
                  //artcam.Alert("ChangeToolpathSelection : Select Sub-Toolpath Failed", 0);     
                  return false;
               }
            }
         }
         break;
      }
   
      // Update Global Current Select Variables 
      gSelectedToolpathGuid = select ? toolpath_id : '';
      gSelectedToolpathType = select ? toolpath_type : '';
   }
   
   // Change Button Availability for templates and toolpaths (ie simulation)
   UpdateButtonAvailability();
   
   return true;
}

// === SelectToolpath =========================================================
//
// Select row for passed toolpath
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 12/11/07 Added this header, draw unlicenced toolpaths in different colour
//-----------------------------------------------------------------------------
function SelectToolpath(toolpath_id, select, colour_as_unlicenced)
{  
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         var row = ToolpathTable.rows(i);
         row.bgColor = select ? gSelBGColor : gBGColor;
         switch(row.toolpathtype)
         {
         case 'toolpath':
         case 'group':
            row.style.color = select ? gSelTextColor : gTextColor;
            break;
         default:
            row.style.color = select ? gTemplateSelTextColor : gTemplateTextColor;            
         }
         // Was it unlicenced?
         if (colour_as_unlicenced)  
            row.style.color = gUnlicencedToolpathColor;
                       
         return true;
      }
   }
   //artcam.Alert("SelectToolpath : Didnt find toolpath!");
   return false;
}

// === SelectLastToolpath =======================================
//
// Select last toolpath in list
//
function SelectLastToolpath()
{
   // select last toopath
   var num_toolpaths = ToolpathTable.rows.length;
   if (num_toolpaths > 0) 
   {
      var last_toolpath_id = ToolpathTable.rows(num_toolpaths - 1).id;
      //artcam.Alert("SelectLastToolpath : ID = "+last_toolpath_id, 0);
      switch(ToolpathTable.rows(num_toolpaths - 1).toolpathtype)
      {
      
      case 'template_group':
      case 'group':
      case 'uncalculated_group':
         //artcam.Alert('SelectLastToolpath1');
         SelectToolpathAndChildren(last_toolpath_id);
         break;

      case 'template':
      case 'toolpath':
      case 'uncalculated_toolpath':
         //artcam.Alert("SelectLastToolpath : Calling FindParent...", 0);
         var parent_id = FindParent(last_toolpath_id);
         SelectToolpathAndChildren(parent_id);
         break;

      default:
         //artcam.Alert("SelectLastToolpath : Unknown Toolpath Type", 0);
      }
   }
   else
   {
      gSelectedToolpathGuid = ''; // nothing to select
      gSelectedToolpathType = ''; // nothing to select
   }
   EnsureSelectedToolpathVisible();
}

// === SelectFirstToolpath =======================================
//
// Select first toolpath in list
//
function SelectFirstToolpath()
{
   // select last toopath
   //artcam.Alert("SelectFirstToolpath", 0);
   var num_toolpaths = ToolpathTable.rows.length;
   if (num_toolpaths > 0) 
   {
      var first_toolpath_id = ToolpathTable.rows(0).id;
      SelectToolpathAndChildren(first_toolpath_id);
   }
   else
   {
      gSelectedToolpathGuid = ''; // nothing to select
      gSelectedToolpathType = ''; // nothing to select
   }
   EnsureSelectedToolpathVisible();
}


//=== GetSelectionAfterDeleting ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 18/02/02 Written
// sgc 11/07/07 Fixed bugs related to using child instead of parent in a couple of places
//-----------------------------------------------------------------------

function GetSelectionAfterDeleting(toolpath_id)
{
   if (toolpath_id == '')
      return '';
   
   // find position of passed toolpath
   var row_index = -1;
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
//         alert("deleting toolpath on row " + i);
         row_index = i;
         break;
      }
   }
   
   if (row_index == -1)
      return;
   
   var num_extra_rows = 0;
   var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
   
   var toolpath_type = GetToolpathType(toolpath_id);
   switch(toolpath_type)
   {
   case 'group':
   case 'uncalculated_group':
      num_extra_rows += oa_toolpath.GetNumberOfChildren();
      break;
      
   case 'template_group':
      num_extra_rows += oa_toolpath.GetNumToolpathParams();
      break;
      
   case 'toolpath':
   case 'uncalculated_toolpath': 
   case 'template':
      var parent_id = FindParent(toolpath_id);
      row_index = FindToolpathTableRow(parent_id);
      if (row_index == -1)
         return;

      var parent_toolpath = artcam.GetToolpathWithId(parent_id);
         
      switch(GetToolpathType(parent_id))
      {
      case 'group':
      case 'uncalculated_group':
         num_extra_rows += parent_toolpath.GetNumberOfChildren();
         break;
         
      case 'template_group':
         num_extra_rows += parent_toolpath.GetNumToolpathParams();
         break;
      }
   }
   
   // next selected toolpath will be after rows being deleted
   var selected_row = row_index + num_extra_rows + 1;
   if (selected_row >= ToolpathTable.rows.length)
   {
      // we are deleting the last toolpath - select preceeding one
      selected_row = row_index - 1;
      if (selected_row < 0)
         return ''; // no toolpaths left
      
      switch(ToolpathTable.rows(selected_row).toolpathtype)
      {        
      case 'toolpath':
      case 'uncalculated_toolpath': 
      case 'template':
         var parent_id = FindParent(ToolpathTable.rows(selected_row).id);
         if(parent_id == ToolpathTable.rows(selected_row).id)
         {
            //artcam.Alert("Failed to find parent", 0);
         }
            
          selected_row = FindToolpathTableRow(parent_id);
      }
      
   }
   
   if (selected_row < 0)
      return ''; // no toolpaths left
   
   //artcam.Alert("selecting row " + selected_row, 0 );   
   return  ToolpathTable.rows(selected_row).id
}



// === ReportSelectionPosition ======================================
//
// report position of selection
//

function ReportSelectionPosition()
{
   if (gSelectedToolpathGuid == '')
      return;
   
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == gSelectedToolpathGuid)
      {
         var row_top = ToolpathTable.rows(i).offsetTop;
         //artcam.Alert("selected toolpath pos:" + row_top + " Table.scrollTop:" + ToolpathTableDiv.scrollTop, 0);
         ToolpathTableDiv.scrollTop = row_top;
      }
   }
}

// === UpdateToolpathList =======================================
//
// Rebuild toolpath table from toolpath list in ArtCAM
//

function UpdateToolpathList()
{
   // empty existing table
   //ToolpathTableDiv.innerHTML = "";
   //while (ToolpathTable.rows.length > 0) 
      //ToolpathTable.rows(0).removeNode(true);
   var table_string = "<table id='ToolpathTable' width='100%' border=0 cellspacing=0 cellpadding=0 cols=5>" +
           "<colgroup><col >" +
           "<col width='100%'>" +
           "<col WIDTH='16px'>" +
           "<col WIDTH='16px'>" +
           "<col WIDTH='9px'></colgroup>";
   
   // Get toolpaths from ArtCAM - there will be none if artcam has just opened.
   var count = artcam.ToolpathCount;
   var num_toolpaths = 0;
   for (var cur_toolpath_idx = 0; cur_toolpath_idx < count; cur_toolpath_idx++ )    
   {
      var toolpath = artcam.GetToolpath(cur_toolpath_idx);
      table_string += AddToolpathToTable(toolpath);
   }
        
   table_string += "</table>";
   ToolpathTableDiv.innerHTML = table_string;

   // Set size and color of color controls
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      // Get toolpath 
      var toolpathID = ToolpathTable.rows(i).id;

      // If it has a colour control
      if (GetColorControl(toolpathID)) {
         var oa_toolpath = artcam.GetToolpathWithId(toolpathID);
         var color = oa_toolpath.SimulationColor2D;
      
         // Set control colour
         SetThumbnailColor( toolpathID, color ); 
      }
   }
          
   // if there are no toolpaths hide the ToolpathInfoDiv
   if (count == 0)
   {
      ToolpathInfoDiv.style.display = "none";
      //ToolpathOperationsDiv.style.display = "none";
      //ToolpathSimulationDiv.style.display = "none"
      ToolpathSimulationCheckboxDiv.style.display = "none";
      gSelectedToolpathGuid = '';
      gSelectedToolpathType = '';

   }
   else
   {
      ToolpathInfoDiv.style.display = "";
      // ToolpathOperationsDiv.style.display = "";
      // ToolpathSimulationDiv.style.display = ""
      ToolpathSimulationCheckboxDiv.style.display = "";
      var previous_selection = artcam.GetSelectedToolpathFromTree();
      if(previous_selection!="none")
      {
         gSelectedToolpathGuid = previous_selection;
         GetToolpathType(gSelectedToolpathGuid);
      }
      else
      {
         gSelectedToolpathGuid = '';      
         gSelectedToolpathType = '';
      }
   }
   
 
   // try and reselect the currently selected toolpath
   if (gSelectedToolpathGuid != '')
   {
      if (!SelectToolpathAndChildren(gSelectedToolpathGuid))
      {
         // failed to load previously selected toolpath - just select last
         //artcam.Alert("UpdateToolpathList : Can't find previous selection", 0);
         SelectLastToolpath();
      }
   }
   else // there was no selected toolpath - select last in list
   {
      //artcam.Alert("UpdateToolpathList : No previous selection", 0);
      SelectLastToolpath();
   }

   // If the table length requires a scroll bar change header layout
   ToggleHeaderSpacingForScrollBar();
   EnsureSelectedToolpathVisible();

}


//=== ToggleHeaderSpacingForScrollBar =========================================
//
// Adjust for scrollbar width (if any scrollbar)
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 23/02/05 Added this header, use system scrollbar width
//-----------------------------------------------------------------------------
function ToggleHeaderSpacingForScrollBar()
{
   // Get the precise scroll bar width (user can change it to anything in Display Properties)
   var SM_CXVSCROLL = 2;
   var scrollbar_width = artcam.GetSystemMetrics( SM_CXVSCROLL );

   // Does scroll bar exist??
   if (ToolpathTable.rows.length>8) {
      // Yes 
      short1.width = 2 + scrollbar_width + 'px';
      short2.width = 2 + scrollbar_width + 'px';
   } else {
      short1.width='2px';
      short2.width='2px';
   }


/*   //ToolpathHeaderTable.deleteRow();
   //ToolpathHeaderTable.deleteRow();
   //var row  = ToolpathHeaderTable.insertRow();
   //row.style.fontWeight = "bold";
   if(ToolpathTable.rows.length>8)
   {
      //var new_td = row.insertCell();
      var new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.innerHTML="<img src='./ToolpathManagerPro/Images/ToolpathList.gif'>";
      new_td.rowSpan = 3;
      new_td.style.width = 45;
      new_td.style.valign = 'top';
      
      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.innerHTML= gShowIn ;
      new_td.style.textAlign="right";
      new_td.style.fontWeight = "bold";

      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.style.width = "18px";
      row = ToolpathHeaderTable.insertRow();

      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.innerHTML= g2D3D ;
      new_td.style.textAlign="right";
      new_td.style.fontWeight = "bold";
      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.style.width = "18px";
      short1.width='18px';
      short2.width='18px';

   }
   else
   {
      //var new_td = row.insertCell();
      /*var new_td = document.createElement("<td></td>");
      row.appendChild(new_td);
      new_td.innerHTML="<img src='./ToolpathManagerPro/Images/ToolpathList.gif'>";
      new_td.rowSpan = 3;
      new_td.style.width = 45;
      new_td.style.valign = 'top';
      
      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.innerHTML= gShowIn ;
      new_td.style.textAlign="right";
      new_td.style.fontWeight = "bold";
      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.style.width = "2px";
      
      row = ToolpathHeaderTable.insertRow();

      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.innerHTML= g2D3D ;
      new_td.style.textAlign="right";
      new_td.style.fontWeight = "bold";
      //new_td = row.insertCell();
      new_td = document.createElement("<td></td>");
      row.appendChild(new_td);

      new_td.style.width = "2px";
      short1.width='2px';
      short2.width='2px';
   }*/
}


// === OnEditRow =====================================================
//
// Called when user double clicks on a row - we edit
// the toolpath within ArtCAM
//

function OnEditRow()
{
   var oSource = window.event.srcElement ;
   // we want the <TR> for this element
   while ((oSource != null) && (oSource.nodeName != 'TR'))
      oSource = oSource.parentNode;
   
   if (oSource == null)
      return;
   
   var toolpath = artcam.GetToolpathWithId(gSelectedToolpathGuid);
   if (toolpath == null)
      return;
   
   toolpath.Edit();
}


// === EnsureSelectedToolpathVisible ====================================
//
// Ensure the selcted toolpath is visible in page
//

function EnsureSelectedToolpathVisible()
{
   if (gSelectedToolpathGuid == '')
      return;    // no selected toolpath
   
   EnsureToolpathVisible(gSelectedToolpathGuid);
}

// === EnsureToolpathVisible =============================================
//
// Ensure that passed toolpath (and any children) are visible in page
//

function EnsureToolpathVisible(toolpath_id)
{
   // get index of first and last rows associated with toolpath
   var first_row = GetFirstRowForToolpath(toolpath_id);
   var last_row  = GetLastRowForToolpath(toolpath_id);
   if ((first_row == -1) || (last_row == -1))
   {
      //artcam.Alert("EnsureToolpathVisible - failed to find rows for toolpath", 0);
      return false; 
   }
   
   // get first and last visible table rows
   var first_vis_row = GetFirstVisibleToolpathRow();
   var last_vis_row  = GetLastVisibleToolpathRow();
   /*
   artcam.Alert("already visible - " + 
   "\nfirst_row:" + first_row + 
   "\nlast_row:" + last_row + 
   "\nfirst_vis_row:" + first_vis_row + 
   "\nlast_vis_row:" + last_vis_row 
   , 0);
   */
   // do we need to do anything ?
   if ((first_row >= first_vis_row) && (last_row <= last_vis_row))
   {
      return true; // no - already visible
   }
   // if we reach here we probably have to scroll - assuming toolpath
   // and its children will fit in viewport
   var num_rows = last_row - first_row + 1;
   var num_vis_rows = last_vis_row - first_vis_row + 1;
   
   // if we cant fit in entirely just make first row the top row in the viewport
   if (num_rows >= num_vis_rows)
   {
      PositionRowAtTop(first_row);
      return;
   }
   
   // if we reach here we have a viewport bigger than toolpath - if above
   // viewport scroll down so first row visible, if below viewport scroll
   // up so that the last row is just visible
   if (first_row < first_vis_row)
      PositionRowAtTop(first_row);
   else
      PositionRowAtBottom(last_row);
   
   
}   

// === GetFirstRowForToolpath =======================================
//
// Return index of first row for passed toolpath and its parent 
// (if any)
//
function GetFirstRowForToolpath(orig_toolpath_id)
{
   var toolpath_id = orig_toolpath_id;
   
   // check if passed toolpath has a parent - we return first row
   // for toolpath group - hence parent if it exists
   var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
   if (oa_toolpath != null)
   {
      var parent_id = oa_toolpath.ParentId;
      if (parent_id != '')
      {
         var oa_parent = artcam.GetToolpathWithId(parent_id);
         if (oa_parent != null)
            toolpath_id = parent_id; // parent will be 'above' us in table
      }
   }
   // now find row for toolpath
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         return i;
      }
   }
   // if reach here didnt find toolpath !
   //artcam.Alert("GetFirstRowForToolpath - didnt find toolpath", 0);
   return -1;
}

// === GetLastRowForToolpath =======================================
//
// Return index of last row for passed toolpath and its 
// siblings (if any)
//
function GetLastRowForToolpath(orig_toolpath_id)
{
   var toolpath_id = orig_toolpath_id;
   
   // check if passed toolpath has a parent - we return last row
   // for toolpath group - hence find parent if it exists
   var oa_toolpath = artcam.GetToolpathWithId(toolpath_id);
   if (oa_toolpath != null)
   {
      var parent_id = oa_toolpath.ParentId;
      if (parent_id != '')
      {
         var oa_parent = artcam.GetToolpathWithId(parent_id);
         if (oa_parent != null)
         {
            // get row for 'last' child
            var num_children = oa_parent.GetNumberOfChildren();
            if (num_children > 0)
            {
               var last_toolpath = oa_parent.GetChild(num_children - 1);
               if (last_toolpath != null)
                  toolpath_id = last_toolpath.Id;
            }
         }
      }
      else
      {
         // dont have a parent - if this is the parent already get
         // position of last child
         var num_children = oa_toolpath.GetNumberOfChildren();
         if (num_children > 0)
         {
            var last_toolpath = oa_toolpath.GetChild(num_children - 1);
            if (last_toolpath != null)
               toolpath_id = last_toolpath.Id;
         }
      }
   }
   
   // now find row for toolpath
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      if (ToolpathTable.rows(i).id == toolpath_id)
      {
         return i;
      }
   }
   // if reach here didnt find toolpath !
   //artcam.Alert("GetLastRowForToolpath - didnt find toolpath", 0);
   return -1;
}

// === GetFirstVisibleToolpathRow =====================================
//
// Return index of first entirely visible row
//

function GetFirstVisibleToolpathRow()
{
   var first_vis_pixel = ToolpathTableDiv.scrollTop;
   
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      var row_top = ToolpathTable.rows(i).offsetTop;
      if ( row_top >= first_vis_pixel)
         return i;
   }
   return 0;
}


// === GetLastVisibleToolpathRow =====================================
//
// Return index of last entirely visible row
//

function GetLastVisibleToolpathRow()
{
   var first_vis_pixel = ToolpathTableDiv.scrollTop;
   var last_vis_pixel  = first_vis_pixel + ToolpathTableDiv.style.pixelHeight;
   var row_height = ToolpathTableDiv.scrollHeight / ToolpathTable.rows.length;
   
   //artcam.Alert("first_vis_pixel:" + first_vis_pixel + " last_vis_pixel:" + last_vis_pixel, 0);
   var last_vis_row = 0;
   for (var i=0; i < ToolpathTable.rows.length; i++) 
   {
      var row_bottom = ToolpathTable.rows(i).offsetTop + row_height;
      //artcam.Alert("row:" + i + " row_bottom:" + row_bottom, 0)
      if (row_bottom > last_vis_pixel)
         return last_vis_row;
      last_vis_row = i;
   }
   
   return last_vis_row;
}

// === PositionRowAtTop ======================================
//
// Position passed row of table at top of scroll window
//

function PositionRowAtTop(first_row_index)
{
   var row_top = ToolpathTable.rows(first_row_index).offsetTop;
   ToolpathTableDiv.scrollTop = row_top;
}

// === PositionRowAtBottom ======================================
//
// Position bottom of passed row of table at bottom of scroll window
//

function PositionRowAtBottom(last_row_index)
{
   var row = ToolpathTable.rows(last_row_index);
   var row_top    = row.offsetTop;
   
   var row_height = ToolpathTableDiv.scrollHeight / ToolpathTable.rows.length;
   
   var row_bottom = row_top + row_height;
   /*
   artcam.Alert("PositionRowAtBottom:" + 
   "\nindex: " + last_row_index + 
   "\nrow_bottom:" + row_bottom + 
   "\nrow_top:" + row_top + 
   "\nrow_height:" + row_height + 
   "\nTable.scrollTop:" + ToolpathTableDiv.scrollTop
   , 0);
   */
   var viewport_height = ToolpathTableDiv.style.pixelHeight;
   
   ToolpathTableDiv.scrollTop = row_bottom - viewport_height;
   
}


//=== OnDeleteSelectedToolpath ==============================================
//
// User has pressed delete button on page - delete current toolpath
//

//
// History
// Who When       What
// --- ---------- ---------------------------------------------------------
// bem 23/02/01 Written
// bem 31/07/01 Check commands are OK before deleting toolpath as 
//                may be drawing / simulating etc.
// ejp 12/02/02 Largely re-written to work with templates
// ejp 27/02/02 NB: Called directly by ArtCAM tree ctrl
// ----------------------------------------------------------------------

function OnDeleteSelectedToolpath()
{
   
   if (!artcam.CommandsOK())
      return;
   
   if (gSelectedToolpathGuid == '')
      return;
   
   var toolpath = artcam.GetToolpathWithId(gSelectedToolpathGuid);
   
   if (toolpath != null)
   {
      var next_selection = GetSelectionAfterDeleting(gSelectedToolpathGuid);
      // select next toolpath
      if (next_selection != '')
      {
         SelectToolpathAndChildren(next_selection);
         EnsureSelectedToolpathVisible();
      }
      else
      {
         SelectLastToolpath();
      }
      RemoveToolpathAndChildren(toolpath.id);
      // and delete within ArtCAM
      toolpath.Delete()
   }

   
   // was this the last toolpath ?
   if (artcam.ToolpathCount == 0)
   {
      // Yes - hide our table data
      
	  ToolpathInfoDiv.style.display = "none";
      // ToolpathOperationsDiv.style.display = "none";
      // ToolpathSimulationDiv.style.display = "none";
      ToolpathSimulationCheckboxDiv.style.display = "none";
   }
}


// === DeleteToolpath ==================================
//
// Delete passed toolpath from list.
//
// This function does NOT delete the toolpath within ArtCAM
//

function DeleteToolpath(oa_toolpath)
{
   // Delete this from our table
   RemoveToolpathAndChildren(oa_toopath);
   
   // if there are no toolpaths hide the ToolpathInfoDiv
   if (ToolpathTable.rows.length == 0)
   {
       ToolpathInfoDiv.style.display = "none";
      // ToolpathOperationsDiv.style.display = "none";
      // ToolpathSimulationDiv.style.display = "none"
      ToolpathSimulationCheckboxDiv.style.display = "none";
   }
}

//=== OnToggle2D  ==============================================
//
// Called when user clicks on a 2D checkbox to toggle visibility
// of toolpath 2d preview
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// bem 08/08/01  Written
//-----------------------------------------------------------------------

function OnToggle2D()
{
   var oSource = window.event.srcElement ;
   if (oSource.nodeName != 'INPUT')
      return;
  
   var checked = oSource.checked;

   // we want the <TR> for this element
   while ((oSource != null) && (oSource.nodeName != 'TR'))
      oSource = oSource.parentNode;
   if (oSource == null)
      return;
   var toolpath = artcam.GetToolpathWithId(oSource.id);
   if (toolpath == null)
      return;
  
   toolpath.Visible2D = checked;
}


function GetColorControl( toolpathID )
{
   var colorID = "color" + toolpathID;
   var control = document.getElementById( colorID );
   return control;
}

function OnClickColorThumbnail( toolpathID )
{
   var control = GetColorControl( toolpathID );

   // Extract colours from whichever colour control user clicked
   var red   = control.Red;
   var green = control.Green;
   var blue  = control.Blue;
   
   var original = red + green<<8 + blue<<16;
   
   // Call ArtCAM to pop up the colour dialog
   var col = artcam.GetColor(red, green, blue);
   
   if (original != col) {           
      SetToolpathColor(toolpathID, col);               // Set toolpath colour  
      artcam.Refresh2dView();
      OnToolpathColorChange();               // Call virtual method on page
   }
}

// "Virtual" function for toolpath color change 
// You can override it by declaring one on the html page
function OnToolpathColorChange()
{
}


function SetToolpathColor( toolpathID, color )
{
   // Get toolpath and set colour      
   var oa_toolpath = artcam.GetToolpathWithId(toolpathID);
   if (oa_toolpath)
      oa_toolpath.SimulationColor2D = color;
   
   SetThumbnailColor( toolpathID, color )
}

function SetThumbnailColor( toolpathID, color )
{
   // Set colour of thumbnail
   var control = GetColorControl( toolpathID );

   if (control) {
      red   =  color & 0xff;
      green = (color & 0xff00)>>8;
      blue  = (color & 0xff0000)>>16;
      
      control.SetColor(red, green, blue);
      control.Red = red;
      control.Green = green;
      control.Blue = blue; 
      
      // Set size also
      control.size = 100;
      control.smoothness = 30;         
   }
}   


