/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/


/*--------------------------------------------------------------------*\
Pro/TOOLKIT includes
\*--------------------------------------------------------------------*/
#include <ProToolkit.h>
#include <ProMdl.h>
#include <ProMenu.h>
#include <ProMessage.h>
#include <ProUI.h>
#include <ProUIDialog.h>
#include <ProUIPushbutton.h>
#include <ProUITable.h>
#include <ProUIInputpanel.h>
#include <ProTKRunTime.h>
#include <ProWstring.h>
#include <ProUtil.h>
/*--------------------------------------------------------------------*\
C System includes
\*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*\
Application includes
\*--------------------------------------------------------------------*/
#include "TestError.h"
#include "TestMenu.h"
#include "UtilFiles.h"
#include "UtilString.h"


#define EX_DLG_NAME (char*)"uitableexample"
#define EX_DLG_RES_FILE (char*)"uitableexample"
#define EX_DLG_TABLE (char*)"Table2"

#define EX_DLG_ADD (char*)"PushButton14"
#define EX_DLG_REMOVE (char*)"PushButton15"
#define EX_DLG_UP (char*)"PushButton16"
#define EX_DLG_DOWN (char*)"PushButton17"
#define EX_DLG_CLOSE (char*)"PushButton18"

#define EX_DLG_IP (char*)"InputPanel8"

static int row_number;
static char* ip_row;
static char* ip_col;

/**********************************************************************\
    Example which demonstrates UI Table usage. 
    The user can add and remove rows and edit cells.
\**********************************************************************/


/*====================================================================*\
FUNCTION: ProTestUITableGetLastRow 
PURPOSE:  Get the last row in the table
\*====================================================================*/
ProError ProTestUITableGetLastRow(char *dialog, char *table, 
                             char *last_row_name)
{
  ProError status;
  int count;
  char **values;

/*--------------------------------------------------------------------*\ 
    Get all the rows in the table and the return the row with the 
    greatest index.
\*--------------------------------------------------------------------*/
  status = ProUITableRownamesGet(dialog, table, &count, &values);
  TEST_CALL_REPORT("ProUITableRownamesGet()", 
                   "ProTestUITableGetLastRow()",
                   status, status != PRO_TK_NO_ERROR);
                     
  if((status != PRO_TK_NO_ERROR) || (count < 1))
  {
    last_row_name = NULL;
  }
  else
  {
    ProUtilstrcpy(last_row_name, values[count-1]);
  }

  ProStringarrayFree(values, count);

  return (PRO_TK_NO_ERROR);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditAddAction 
PURPOSE:  Add a row to the table
\*====================================================================*/
void ProTestUITableEditAddAction(char *dialog, char *component, 
                            ProAppData data)
{
  ProError status;
  char last_row_name[3] = {'\0','\0','\0'};
  char *last_row_name_ptr = &last_row_name[0];
  char new_row_name[3] = {'\0','\0','\0'};
  char *new_row_name_ptr = &new_row_name[0];
  char str_row_data[32];
  wchar_t row_data[32];
  int col_number;

/*--------------------------------------------------------------------*\ 
    Add a row after the last row 
\*--------------------------------------------------------------------*/
  ProTestUITableGetLastRow(EX_DLG_NAME, EX_DLG_TABLE, last_row_name_ptr);

  ProTKSprintf(new_row_name,"%d",(row_number+1));
  status = ProUITableRowsInsert(EX_DLG_NAME, EX_DLG_TABLE, 
                                last_row_name_ptr, 1, &new_row_name_ptr);
  TEST_CALL_REPORT("ProUITableRowsInsert()", 
                   "ProTestUITableEditAddAction()",
                   status, status != PRO_TK_NO_ERROR);
                   
/*--------------------------------------------------------------------*\ 
    Enter data in the row 
\*--------------------------------------------------------------------*/
  if(status == PRO_TK_NO_ERROR)
  { 
    row_number++;
  
    ProTKSprintf(str_row_data, "R%d; C1", row_number);
    ProStringToWstring(row_data, str_row_data);
    ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, new_row_name_ptr, 
                           (char*)"1", row_data);

    ProTKSprintf(str_row_data, "R%d; C2", row_number);
    ProStringToWstring(row_data, str_row_data);
    ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, new_row_name_ptr, 
                           (char*)"2", row_data);

    ProTKSprintf(str_row_data, "R%d; C3", row_number);
    ProStringToWstring(row_data, str_row_data);
    ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, new_row_name_ptr, 
                           (char*)"3", row_data);

    ProTKSprintf(str_row_data, "R%d; C4", row_number);
    ProStringToWstring(row_data, str_row_data);
    ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, new_row_name_ptr, 
                           (char*)"4", row_data);
  }

}

/*====================================================================*\
FUNCTION: ProTestUITableEditRemoveAction 
PURPOSE:  Remove selected rows from the table
\*====================================================================*/
void ProTestUITableEditRemoveAction(char *dialog, char *component,
                               ProAppData data)
{
  ProError status;
  int count, i, sel_row, index;
  char **del_values;
  char **values;

/*--------------------------------------------------------------------*\ 
    Get all the selected rows 
\*--------------------------------------------------------------------*/  
  status = ProUITableSelectednamesGet(EX_DLG_NAME, EX_DLG_TABLE, &count, 
                                      &del_values);
  TEST_CALL_REPORT("ProUITableSelectednamesGet()", 
                   "ProTestUITableEditRemoveAction()",
                   status, status != PRO_TK_NO_ERROR);
                   
  if((status == PRO_TK_NO_ERROR) && (count > 0))
  {
/*--------------------------------------------------------------------*\ 
    Get the row with the lowest index 
\*--------------------------------------------------------------------*/ 
    sel_row = -1;
    
    for(i=0; i<count; i=i+2)
    {
      status = ProUITableRowIndexGet(EX_DLG_NAME, EX_DLG_TABLE, 
                                     del_values[i], &index);
      TEST_CALL_REPORT("ProUITableRowIndexGet()", 
                   "ProTestUITableEditRemoveAction()",
                   status, status != PRO_TK_NO_ERROR);
                   
      if((status == PRO_TK_NO_ERROR) && 
         (sel_row == -1) || (sel_row > index))
      {
        sel_row = index;
      }
    }

/*--------------------------------------------------------------------*\ 
    Delete the selected rows 
\*--------------------------------------------------------------------*/ 
    for(i=0; i<count; i=i+2)
    {
      status = ProUITableRowsDelete(EX_DLG_NAME, EX_DLG_TABLE, 1, 
                                    &(del_values[i]));
      TEST_CALL_REPORT("ProUITableRowsDelete()", 
                   "ProTestUITableEditRemoveAction()",
                   status, status != PRO_TK_NO_ERROR);
    }

/*--------------------------------------------------------------------*\ 
    Highlight the row with the lowest index 
\*--------------------------------------------------------------------*/ 
    if(sel_row > -1)
    {
      status = ProUITableRownamesGet(EX_DLG_NAME, EX_DLG_TABLE, &index, 
                                     &values);
      TEST_CALL_REPORT("ProUITableRownamesGet()", 
                   "ProTestUITableEditRemoveAction()",
                   status, status != PRO_TK_NO_ERROR);
      if((status == PRO_TK_NO_ERROR) && (index > 0))
      {
        if(sel_row >= index)
        {
          sel_row = index - 1;
        }
        status = ProUITableRowCellsSelect(EX_DLG_NAME, EX_DLG_TABLE, 1, 
                                          &(values[sel_row]));
        TEST_CALL_REPORT("ProUITableRowCellsSelect()", 
                   "ProTestUITableEditRemoveAction()",
                   status, status != PRO_TK_NO_ERROR);
      }

      ProStringarrayFree(values, index);
    }
  }

  ProStringarrayFree(del_values, count);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditSwapRows 
PURPOSE:  Swap the two rows given their index
\*====================================================================*/
ProError ProTestUITableEditSwapRows(int row1, int row2)
{
  ProError status;
  int col_count, row_count, i;
  char **row_values;
  char **col_values;
  wchar_t *label_1, *label_2;

  if(row1 == row2)
    return PRO_TK_BAD_INPUTS;

/*--------------------------------------------------------------------*\ 
    Get the rows in the table 
\*--------------------------------------------------------------------*/ 
  status = ProUITableRownamesGet(EX_DLG_NAME, EX_DLG_TABLE, &row_count, 
                                 &row_values);
  TEST_CALL_REPORT("ProUITableRownamesGet()", 
                   "ProTestUITableEditSwapRows()",
                   status, status != PRO_TK_NO_ERROR);
      
  if((status == PRO_TK_NO_ERROR) && (row_count > 1))
  {
    if((row1 >= 0) && (row1 < row_count) &&
       (row2 >= 0) && (row2 < row_count))
    {
  /*--------------------------------------------------------------------*\ 
      Get the columns in the table 
  \*--------------------------------------------------------------------*/ 
      status = ProUITableColumnnamesGet(EX_DLG_NAME, EX_DLG_TABLE,
                                        &col_count, &col_values);
      TEST_CALL_REPORT("ProUITableColumnnamesGet()", 
                   "ProTestUITableEditSwapRows()",
                   status, status != PRO_TK_NO_ERROR);
      if((status == PRO_TK_NO_ERROR) && (col_count > 0))
      {
  /*--------------------------------------------------------------------*\ 
      Swap the cell values 
  \*--------------------------------------------------------------------*/ 
        for(i=0; i<col_count; i++)
        {
          ProUITableCellLabelGet(EX_DLG_NAME, EX_DLG_TABLE, 
                                 row_values[row1], col_values[i], 
                                 &label_1);

          ProUITableCellLabelGet(EX_DLG_NAME, EX_DLG_TABLE, 
                                 row_values[row2], col_values[i], 
                                 &label_2);

          ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, 
                                 row_values[row1], col_values[i], 
                                 label_2);

          ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, 
                                 row_values[row2], col_values[i], 
                                 label_1);
        }     
      }
      ProStringarrayFree(col_values, col_count);
    }
    else
    {
      status = PRO_TK_BAD_INPUTS;
    }
  }
  ProStringarrayFree(row_values, row_count);

  return status;
}

/*====================================================================*\
FUNCTION: ProTestUITableEditMoveRows 
PURPOSE:  Move selected row
\*====================================================================*/
ProError ProTestUITableEditMoveRows(int direction)
{
  ProError status;
  int count, i, sel_row, new_row, index;
  char **values;

/*--------------------------------------------------------------------*\ 
    Get all the selected rows 
\*--------------------------------------------------------------------*/  
  status = ProUITableSelectednamesGet(EX_DLG_NAME, EX_DLG_TABLE, &count, 
                                      &values);
  TEST_CALL_REPORT("ProUITableSelectednamesGet()", 
                   "ProTestUITableEditMoveRows()",
                   status, status != PRO_TK_NO_ERROR);
  if((status == PRO_TK_NO_ERROR) && (count > 0))
  {
/*--------------------------------------------------------------------*\ 
    Get the row with the lowest index 
\*--------------------------------------------------------------------*/ 
    sel_row = -1;
    
    for(i=0; i<count; i=i+2)
    {
      status = ProUITableRowIndexGet(EX_DLG_NAME, EX_DLG_TABLE, 
                                     values[i], &index);
      TEST_CALL_REPORT("ProUITableRowIndexGet()", 
                   "ProTestUITableEditMoveRows()",
                   status, status != PRO_TK_NO_ERROR);

      if((status == PRO_TK_NO_ERROR) && 
         (sel_row == -1) || (sel_row > index))
      {
        sel_row = index;
      }
    }

/*--------------------------------------------------------------------*\ 
    Swap the values of the selected row
\*--------------------------------------------------------------------*/     
    new_row = sel_row + direction;
    status = ProTestUITableEditSwapRows(new_row, sel_row);
    
    if(status == PRO_TK_NO_ERROR)
    {
/*--------------------------------------------------------------------*\ 
    Deselect all the rows
\*--------------------------------------------------------------------*/ 
      for(i=0; i<count; i=i+2)
      {
        status = ProUITableRowCellsDeselect(EX_DLG_NAME, EX_DLG_TABLE, 
                                            1, &(values[i]));
        TEST_CALL_REPORT("ProUITableRowCellsDeselect()", 
                   "ProTestUITableEditMoveRows()",
                   status, status != PRO_TK_NO_ERROR);
      }

      ProStringarrayFree(values, count);    
/*--------------------------------------------------------------------*\ 
    Highlight the new row 
\*--------------------------------------------------------------------*/     
      status = ProUITableRownamesGet(EX_DLG_NAME, EX_DLG_TABLE, &count, 
                                     &values);
      TEST_CALL_REPORT("ProUITableRownamesGet()", 
                   "ProTestUITableEditMoveRows()",
                   status, status != PRO_TK_NO_ERROR);
                   
      if((status == PRO_TK_NO_ERROR) && (count > 0))
      {     
        status = ProUITableRowCellsSelect(EX_DLG_NAME, EX_DLG_TABLE, 1, 
                                          &(values[new_row]));
        TEST_CALL_REPORT("ProUITableRowCellsSelect()", 
                   "ProTestUITableEditMoveRows()",
                   status, status != PRO_TK_NO_ERROR);
      }
    }
  }
  
  ProStringarrayFree(values, count);
  return (status);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditUpAction 
PURPOSE:  Move selected row up
\*====================================================================*/
void ProTestUITableEditUpAction(char *dialog, char *component,
                           ProAppData data)
{
  ProTestUITableEditMoveRows(-1);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditDownAction 
PURPOSE:  Move selected row down
\*====================================================================*/
void ProTestUITableEditDownAction(char *dialog, char *component,
                             ProAppData data)
{
  ProTestUITableEditMoveRows(1);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditCloseAction 
PURPOSE:  Close the dialog
\*====================================================================*/
void ProTestUITableEditCloseAction(char *dialog, char *component, 
                              ProAppData data)
{
  ProError status;

  status = ProUIDialogExit(dialog, PRO_TK_NO_ERROR);
  TEST_CALL_REPORT("ProUIDialogExit()", 
                   "ProTestUITableEditCloseAction()",
                   status, status != PRO_TK_NO_ERROR);
}


/*====================================================================*\
FUNCTION: ProTestUITableEditLoseIPfocus 
PURPOSE:  Action function for input panel at table cell
\*====================================================================*/
void ProTestUITableEditLoseIPfocus(char *dialog, char *component,
                              ProAppData data)
{
  ProError status;
  wchar_t* label;
  char input_panel[8];
    
  ProTKSprintf(input_panel, "%s_%s", ip_row, ip_col);
  
/*--------------------------------------------------------------------*\
    Copy the input panel label to the cell
\*--------------------------------------------------------------------*/
  status = ProUIInputpanelValueGet(EX_DLG_NAME, input_panel, &label);  
  TEST_CALL_REPORT("ProUIInputpanelValueGet()", 
                   "ProTestUITableEditLoseIPfocus()",
                   status, status != PRO_TK_NO_ERROR);
                   
  if((status == PRO_TK_NO_ERROR) && (label != NULL))
  {
    status = ProUITableCellLabelSet(EX_DLG_NAME, EX_DLG_TABLE, ip_row, 
                                    ip_col, label);
    TEST_CALL_REPORT("ProUITableCellLabelSet()", 
                   "ProTestUITableEditLoseIPfocus()",
                   status, status != PRO_TK_NO_ERROR);

  }

/*--------------------------------------------------------------------*\
    Delete the input panel label from the cell
\*--------------------------------------------------------------------*/  
  status = ProUITableCellComponentDelete(EX_DLG_NAME, EX_DLG_TABLE, 
                                         ip_row, ip_col);
  TEST_CALL_REPORT("ProUITableCellComponentDelete()", 
                   "ProTestUITableEditLoseIPfocus()",
                   status, status != PRO_TK_NO_ERROR);

  ProWstringFree(label);
  ProStringFree(ip_row);
  ProStringFree(ip_col);
}

/*====================================================================*\
FUNCTION: ProTestUITableEditActivateCell 
PURPOSE:  Edit action when user selects a cell
\*====================================================================*/
void ProTestUITableEditActivateCell(char *dialog, char *component, 
                               ProAppData data)
{
  ProError status;
  int count, i, width;
  char **values;
  char *row;
  wchar_t* label;
  char input_panel[8];

/*--------------------------------------------------------------------*\ 
    Get all the selected rows. If more thatn one row is selected, do 
    nothing
\*--------------------------------------------------------------------*/  
  status = ProUITableSelectednamesGet(EX_DLG_NAME, EX_DLG_TABLE, &count, 
                                      &values);
  TEST_CALL_REPORT("ProUITableSelectednamesGet()", 
                   "ProTestUITableEditActivateCell()",
                   status, status != PRO_TK_NO_ERROR);

  if((status == PRO_TK_NO_ERROR) && (count > 0))
  {
    row = values[0];
    for(i=2; i<count; i++)
    {
      if(strcmp(row, values[i]) != 0)
      {
        ProStringarrayFree(values, count);
        return;
      }
    }
  }
  ProStringarrayFree(values, count);

/*--------------------------------------------------------------------*\ 
    Get the focus cell
\*--------------------------------------------------------------------*/   
  status = ProUITableFocusCellGet(EX_DLG_NAME, EX_DLG_TABLE, 
                                  &ip_row, &ip_col);
  TEST_CALL_REPORT("ProUITableFocusCellGet()", 
                   "ProTestUITableEditActivateCell()",
                   status, status != PRO_TK_NO_ERROR);

  if(status == PRO_TK_NO_ERROR)
  {
    status = ProUITableCellLabelGet(EX_DLG_NAME, EX_DLG_TABLE, ip_row, 
                                    ip_col, &label);
    TEST_CALL_REPORT("ProUITableCellLabelGet()", 
                   "ProTestUITableEditActivateCell()",
                   status, status != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\ 
    Create an input panel at the focus cell
\*--------------------------------------------------------------------*/     
    ProTKSprintf(input_panel, "%s_%s", ip_row, ip_col);

    status = ProUITableCellComponentCopy(EX_DLG_NAME, EX_DLG_TABLE, 
                                         ip_row, ip_col, EX_DLG_NAME, 
                                         EX_DLG_IP, input_panel);
    TEST_CALL_REPORT("ProUITableCellComponentCopy()", 
                   "ProTestUITableEditActivateCell()",
                   status, status != PRO_TK_NO_ERROR);
                   
    if(status == PRO_TK_NO_ERROR)
    {
/*--------------------------------------------------------------------*\
    Setup the properties of the input panel
\*--------------------------------------------------------------------*/
      ProUITableColumnWidthGet(EX_DLG_NAME, EX_DLG_TABLE, ip_col, 
                               &width);

      ProUIInputpanelColumnsSet(EX_DLG_NAME, input_panel, width);

      ProUIInputpanelEnable(EX_DLG_NAME, input_panel);            

      ProUIInputpanelShow(EX_DLG_NAME, input_panel);

      ProUIInputpanelValueSet(EX_DLG_NAME, input_panel, label);

      ProUIInputpanelFocusoutActionSet(EX_DLG_NAME, input_panel, 
                                      (ProUIAction)ProTestUITableEditLoseIPfocus, 
                                       NULL);
      ProUIInputpanelActivateActionSet(EX_DLG_NAME, input_panel, 
                                       (ProUIAction)ProTestUITableEditLoseIPfocus, 
                                       NULL);
      ProUIDialogFocusSet(EX_DLG_NAME, input_panel);
    }
    else
    {
      ProStringFree(ip_row);
      ProStringFree(ip_col);
    }
    ProWstringFree(label);
  }
}

/*====================================================================*\
FUNCTION: UserUITableEditExample 
PURPOSE:  Example which demonstrates UI Table usage. 
          The user can add and remove rows and edit cells.
\*====================================================================*/
int ProTestUITableEditExample()
{
  ProError status;

/*--------------------------------------------------------------------*\ 
    Load the dialog from the resource file 
\*--------------------------------------------------------------------*/ 
  status = ProUIDialogCreate(EX_DLG_NAME, EX_DLG_RES_FILE);  
  TEST_CALL_REPORT("ProUIDialogCreate()", "ProTestUITableEditExample()",
                    status, status != PRO_TK_NO_ERROR);  
  if(status != PRO_TK_NO_ERROR)
    return (status);

  row_number = 0;

/*--------------------------------------------------------------------*\ 
    Set action function for buttons 
\*--------------------------------------------------------------------*/ 
  status = ProUIPushbuttonActivateActionSet(EX_DLG_NAME, EX_DLG_ADD, 
                                         (ProUIAction)ProTestUITableEditAddAction, 
                                         NULL);
  TEST_CALL_REPORT("ProUIPushbuttonActivateActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);  
                    
  status = ProUIPushbuttonActivateActionSet(EX_DLG_NAME, EX_DLG_REMOVE, 
                                        (ProUIAction)ProTestUITableEditRemoveAction, 
                                        NULL);
  TEST_CALL_REPORT("ProUIPushbuttonActivateActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
  status = ProUIPushbuttonActivateActionSet(EX_DLG_NAME, EX_DLG_UP, 
                                          (ProUIAction)ProTestUITableEditUpAction, 
                                          NULL);
  TEST_CALL_REPORT("ProUIPushbuttonActivateActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
  status = ProUIPushbuttonActivateActionSet(EX_DLG_NAME, EX_DLG_DOWN, 
                                        (ProUIAction)ProTestUITableEditDownAction, 
                                        NULL);
  TEST_CALL_REPORT("ProUIPushbuttonActivateActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
  status = ProUIPushbuttonActivateActionSet(EX_DLG_NAME, EX_DLG_CLOSE, 
                                       (ProUIAction)ProTestUITableEditCloseAction, 
                                       NULL);
  TEST_CALL_REPORT("ProUIPushbuttonActivateActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
  status = ProUIDialogCloseActionSet(EX_DLG_NAME, 
                                       (ProUIAction)ProTestUITableEditCloseAction, 
                                       NULL);
  TEST_CALL_REPORT("ProUIDialogCloseActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
/*--------------------------------------------------------------------*\ 
    Set action function for editing cells 
\*--------------------------------------------------------------------*/ 
  status = ProUITableSelectActionSet(EX_DLG_NAME, EX_DLG_TABLE, 
                                     (ProUIAction)ProTestUITableEditActivateCell, NULL);
  TEST_CALL_REPORT("ProUITableSelectActionSet()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);
                   
/*--------------------------------------------------------------------*\ 
    Display and activate the dialog 
\*--------------------------------------------------------------------*/ 
  status = ProUIDialogActivate(EX_DLG_NAME, NULL);
  TEST_CALL_REPORT("ProUIDialogActivate()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);

/*--------------------------------------------------------------------*\ 
    Remove the dialog from memory 
\*--------------------------------------------------------------------*/ 
  status = ProUIDialogDestroy(EX_DLG_NAME);
  TEST_CALL_REPORT("ProUIDialogDestroy()", 
                   "ProTestUITableEditExample()",
                   status, status != PRO_TK_NO_ERROR);

  return(1);
}