4.9. Define and Utilize the User Defined Reader GUI Options

The additional reader toggles, pulldowns, and fields are now defined using a struct first defined and returned by USERD_reader_open.

These options are then chosen by you in the data reader dialog are available in USERD_set_filenames, prior to reading data. Then, when the EnSight session is finished, the structured is freed in USERD_reader_close. As such, it is recommended that you define three functions in your reader, define_gui_options, handle_gui_options, and free_gui_options, each called successively by these three USERD routines during the EnSight session.

What follows is an example of each of the three routines. The test3u_advanced reader (included in your EnSight install under src/readers/test3u_advanced) contains the most up-to-date commentary in a working reader that shows in detail how and when to define these entities and how and when to get information back from the user, and how and when to free up the struct when done, in order to better control reader behavior.

The struct, defined within the Handle struct, is called UserDefinedGUI_10 *gui_options. This struct is defined in ../extern/global_extern.h.

Using this struct, you can define the toggles, pulldowns, and fields that show up in the EnSight data reader format options tab, and provide the defaults for them. This all goes in the handle. When the test3u_advanced reader is compiled and loaded by EnSight, the following dialog shows when you select FileOpen and toggles the advanced button, and chooses the test3u_advanced reader in the data reader dialog, and then clicks the Format options tab in the data reader dialog:

Clicking the Format options tab, you will see the following toggles, pulldown and fields available to control the execution of the reader.

Shown below are the three routines found in the test3u_advanced reader:

Define GUI Options


Note:  This routine should be called from within the USERD_reader_open in order to allocate and define this struct. This is called by EnSight, in order to populate your format options dialog with the appropriately labeled GUI items.


static void
define_gui_options( EnSightRdrHandle *hdl )
{
  UserDefinedGUI_10 *opt = NULL;
  
  hdl->server.gui_options = (UserDefinedGUI_10 *) calloc(sizeof(UserDefinedGUI_10),1);  
  opt = hdl->server.gui_options;

  /* defaults */
  hdl->dataset_read_warn          = TRUE;    /* Warn when a Dataset Read occurs */
  hdl->user_verbosity             = Z_FULL;  /* Default Console output Debug */
  /* advanced features */
  hdl->coprocessing_max_timesteps = 0; /* Coprocessing disabled when 0 and enabled when > 0 */
  hdl->coprocessing_num_calls     = 0; /* incremented with each call of USERD_get_max_timesteps */
  hdl->use_metadata               = TRUE; /* part material, kind, grouping, coloration, case metadata */
  hdl->use_symmetry               = TRUE; /* symmetric parts repeated */
  hdl->use_units                  = TRUE; /* variable & query  units */
  hdl->use_rigid_body_motion      = TRUE; /* part rigid body motion */
  hdl->filter_fail_elem_val       = -1;   /* demonstrate element failure/filtering using Element_Set 
                                             variable if this value >= 0 */

  /*----------
   * Pulldowns
   *----------*/ 
  opt->iNumPullDowns              = ZTU_NUM_PULLDOWNS;
  
  if (opt->iNumPullDowns > 0) {
    opt->PullDownTitle            = (char **)  calloc(opt->iNumPullDowns,sizeof(char *)); 
    opt->PullDownNumberInList     = (int *)    calloc(opt->iNumPullDowns,sizeof(int));
    opt->PullDownDefaultSelection = (int *)    calloc(opt->iNumPullDowns,sizeof(int));
    opt->PullDownUserSelection    = (int *)    calloc(opt->iNumPullDowns,sizeof(int));
    opt->PullDownItemStrings      = (char ***) calloc(opt->iNumPullDowns,sizeof(char **));

    if (ZTU_PULL_CONSOLE_OUTPUT < ZTU_NUM_PULLDOWNS) {
      opt->PullDownTitle[ZTU_PULL_CONSOLE_OUTPUT]            = strdup("Console Output");
      int num_in_list                                        = 3;
      opt->PullDownNumberInList[ZTU_PULL_CONSOLE_OUTPUT]     = num_in_list; 
      opt->PullDownDefaultSelection[ZTU_PULL_CONSOLE_OUTPUT] = 2; /* default option debug */ 
      opt->PullDownItemStrings[ZTU_PULL_CONSOLE_OUTPUT]      = (char **) 
                                                               calloc(num_in_list, sizeof(char *)); 
      opt->PullDownItemStrings[ZTU_PULL_CONSOLE_OUTPUT][0]   = strdup("Normal");
      opt->PullDownItemStrings[ZTU_PULL_CONSOLE_OUTPUT][1]   = strdup("Verbose");
      opt->PullDownItemStrings[ZTU_PULL_CONSOLE_OUTPUT][2]   = strdup("Debug");
    }
  }

  /*----------
   * Toggles
   *----------*/ 
  opt->iNumToggles = ZTU_NUM_TOGGLES;

  if (opt->iNumToggles > 0) { 
    opt->ToggleTitle         = (char **) calloc(opt->iNumToggles,sizeof(char *));
    opt->ToggleDefaultStatus = (int *)   calloc(opt->iNumToggles,sizeof(int));
    opt->ToggleUserSelection = (int *)   calloc(opt->iNumToggles,sizeof(int));
    
    if (ZTU_TOGGLE_UNITS < ZTU_NUM_TOGGLES) {
      opt->ToggleTitle[ZTU_TOGGLE_UNITS ]         = strdup("Enable Units"); /* part metadata */
      opt->ToggleDefaultStatus[ZTU_TOGGLE_UNITS ] = hdl->use_units;
    }
    
    if (ZTU_TOGGLE_DATASET_READ < ZTU_NUM_TOGGLES) {
      opt->ToggleTitle[ZTU_TOGGLE_DATASET_READ]         = strdup("Highlight Dataset Read calls");
      opt->ToggleDefaultStatus[ZTU_TOGGLE_DATASET_READ] = hdl->dataset_read_warn;
    }
    
    if (ZTU_TOGGLE_CUSTOMIZE_PARTS < ZTU_NUM_TOGGLES) {
      opt->ToggleTitle[ZTU_TOGGLE_CUSTOMIZE_PARTS]         = strdup("Customize Parts"); /* 
                                                             part metadata */
      opt->ToggleDefaultStatus[ZTU_TOGGLE_CUSTOMIZE_PARTS] = hdl->use_metadata;
    }
    
    if (ZTU_TOGGLE_PART_SYMMETRY < ZTU_NUM_TOGGLES) {
      opt->ToggleTitle[ZTU_TOGGLE_PART_SYMMETRY ]         = strdup("Show Part Symmetry"); /* 
                                                            part metadata */
      opt->ToggleDefaultStatus[ZTU_TOGGLE_PART_SYMMETRY ] = hdl->use_symmetry;
    }
    
    if (ZTU_TOGGLE_RIGID_BODY < ZTU_NUM_TOGGLES) {
      opt->ToggleTitle[ZTU_TOGGLE_RIGID_BODY]         = strdup("Enable Rigid Body Motion"); /* 
                                                        part metadata */
      opt->ToggleDefaultStatus[ZTU_TOGGLE_RIGID_BODY] = hdl->use_rigid_body_motion;
    }
  }
  /*----------
   * Fields
   *----------*/ 
  opt->iNumFields = ZTU_NUM_FIELDS;

  if (opt->iNumFields > 0) {
    opt->FieldTitle         = (char **) calloc(opt->iNumFields,sizeof(char *));
    opt->FieldUserSelection = (char **) calloc(opt->iNumFields,sizeof(char *));
    
    /* coprocessing */
    if (ZTU_FIELD_COPROCESSING_STEPS < ZTU_NUM_FIELDS) {
      opt->FieldTitle[ZTU_FIELD_COPROCESSING_STEPS]         = strdup("Maximum number timesteps");
      opt->FieldUserSelection[ZTU_FIELD_COPROCESSING_STEPS] = (char*)calloc(1,Z_LEN_GUI_FIELD_STR);
      sprintf(opt->FieldUserSelection[ZTU_FIELD_COPROCESSING_STEPS], "%d", 
      hdl->coprocessing_max_timesteps);
    }

    if (ZTU_FIELD_FAILED_ELEMENTS < ZTU_NUM_FIELDS) {
      opt->FieldTitle[ZTU_FIELD_FAILED_ELEMENTS]               = strdup("Remove Elems in Elem Set");
      opt->FieldUserSelection[ZTU_FIELD_FAILED_ELEMENTS]       = (char*)calloc(1,Z_LEN_GUI_FIELD_STR);
      sprintf(opt->FieldUserSelection[ZTU_FIELD_FAILED_ELEMENTS], "%d", hdl->filter_fail_elem_val);
      
    }
  }

  return;
}

Handle GUI

This routine is called from USERD_set_filenames and provides the reader with the options chosen by the user. This allows you to set options in the Handle, based on user input, that influence the behavior of your reader.

static void
handle_gui_options( EnSightRdrHandle *hdl )
{
  UserDefinedGUI_10 *opt = hdl->server.gui_options;

  // Execute GUI Option
  // .. Pulldown related variables

  if (ZTU_PULL_CONSOLE_OUTPUT < ZTU_NUM_PULLDOWNS) {
    // Console output pulldown: Normal, Verbose, Debug
    switch( opt->PullDownUserSelection[ZTU_PULL_CONSOLE_OUTPUT] ) {
    case 0:
      hdl->user_verbosity = Z_QUIET;
      break;
    case 1:
      hdl->user_verbosity = Z_ROUTINE_ONLY;
      break;
    case 2:
      hdl->user_verbosity = Z_FULL;
      break;
    default:
      hdl->user_verbosity = Z_ROUTINE_ONLY;
      break;
    };
  }

  
  if( print_flag(hdl) >= Z_FULL) {
    USERD_info("----------------------\n");
    USERD_info("  handle_gui_options()");
    if (hdl->dataset_read_warn) {
      USERD_warn("    All simulated Dataset reads will be output as highlighted warnings\n");
    } else {
      USERD_info("    All simulated Dataset reads will be output simply as informational messages\n");
    }
    USERD_info("    Console output is Debug\n");
  }
  
  // .. Field related variables
  //  Get Float Value
  if (ZTU_FIELD_COPROCESSING_STEPS < ZTU_NUM_FIELDS) {
    if( opt->FieldUserSelection &&  strlen(opt->FieldUserSelection[ZTU_FIELD_COPROCESSING_STEPS ]) ) {
      int max_timesteps = hdl->coprocessing_max_timesteps;
      if( sscanf(opt->FieldUserSelection[ ZTU_FIELD_COPROCESSING_STEPS ],"%d",&max_timesteps)) {
        hdl->coprocessing_max_timesteps = max_timesteps;
        if( print_flag(hdl) >= Z_FULL) {
          if (hdl->coprocessing_max_timesteps > 0) {
            USERD_info("    Coprocessing max number of timesteps  = %d\n",
            hdl->coprocessing_max_timesteps);
          } else {
            USERD_info("    Coprocessing is turned off (max timesteps  = %d)\n",
            hdl->coprocessing_max_timesteps);
          }
        }
      }
    }
  }

  if (ZTU_FIELD_FAILED_ELEMENTS < ZTU_NUM_FIELDS) {
    if( opt->FieldUserSelection &&  strlen(opt->FieldUserSelection[ZTU_FIELD_FAILED_ELEMENTS ]) ) {
      int elem_var_val;
      if ( sscanf(opt->FieldUserSelection[ZTU_FIELD_FAILED_ELEMENTS ] , "%d", &elem_var_val)) {
        hdl->filter_fail_elem_val = elem_var_val;    
        if( print_flag(hdl) >= Z_FULL) {
          if (hdl->filter_fail_elem_val >= 0) {
            USERD_info("    Element filtering of Element_Set  = %d\n",
            hdl->filter_fail_elem_val);
          } else {
            USERD_info("    Element filtering of Element_Set is turned off  = 
            %d)\n",hdl->filter_fail_elem_val);
          }
        }
      }
    }
  }

  if (opt->ToggleUserSelection ) {
    if (ZTU_TOGGLE_DATASET_READ < ZTU_NUM_TOGGLES) {
      hdl->dataset_read_warn = opt->ToggleUserSelection[ZTU_TOGGLE_DATASET_READ];
    }
    
    if (ZTU_TOGGLE_CUSTOMIZE_PARTS < ZTU_NUM_TOGGLES) {
      hdl->use_metadata = opt->ToggleUserSelection[ZTU_TOGGLE_CUSTOMIZE_PARTS];
    }
    if (ZTU_TOGGLE_PART_SYMMETRY < ZTU_NUM_TOGGLES) {
      hdl->use_symmetry = opt->ToggleUserSelection[ZTU_TOGGLE_PART_SYMMETRY];
    }
    if (ZTU_TOGGLE_UNITS < ZTU_NUM_TOGGLES) {
      hdl->use_units = opt->ToggleUserSelection[ZTU_TOGGLE_UNITS];
    }
    if (ZTU_TOGGLE_RIGID_BODY < ZTU_NUM_TOGGLES) {
      hdl->use_rigid_body_motion = opt->ToggleUserSelection[ZTU_TOGGLE_RIGID_BODY];
    }
  }
  
  if( print_flag(hdl) >= Z_FULL) {
    if (hdl->dataset_read_warn) {
      USERD_warn("    All simulated dataset reads will be output as highlighted warnings\n");
    } else {
      USERD_info("    All simulated dataset reads will be output simply as informational messages\n");
    }
    if ( hdl->use_metadata  ) {
      USERD_info("    Parts will be customized: Grouping, color, material, kind\n");
    } else {
      USERD_info("    Parts will NOT be customized: Grouping, color, material, kind\n");
    }
    if ( hdl->use_symmetry ) {
      USERD_info("    Symmetric Parts will be able to use informed Visual symmetry\n");
    } else {
      USERD_info("    Symmetric Parts will NOT use informed Visual symmetry\n");
    }
    if ( hdl->use_units  ) {
      USERD_info("    If available in datataset, Variables will have units\n");
    } else {
      USERD_info("    Variables will NOT have units\n");
    }
    if ( hdl->use_rigid_body_motion ) {
      USERD_info("    Parts will have rigid body motion\n");
    } else {
      USERD_info("    Parts will NOT have rigid body motion\\n");
    }
    USERD_info("-------------\n");
  }

}

Free GUI Items

This routine should be called from USERD_reader_close, which is the last routine called when the EnSight session is quit (for example, the EnSight server is closed). This will allow you to free up your structs and avoid memory leaks (for example, unfreed, allocated memory).

static int
free_gui_options( EnSightRdrHandle *hdl )
{
  if (print_flag(hdl) >= Z_FULL) USERD_info("free_gui_options\n");
  
  /* Free any pulldowns
   *-------------------*/
  if( hdl->server.gui_options->iNumPullDowns ) {
    if( print_flag(hdl) >= Z_FULL ) {
      USERD_info(" Freeing %d Pulldowns\n", hdl->server.gui_options->iNumPullDowns);
    }
    for(int i=0; i<hdl->server.gui_options->iNumPullDowns; ++i) {
      safe_free(hdl->server.gui_options->PullDownTitle[i]);
      for(int j=0; j<hdl->server.gui_options->PullDownNumberInList[i]; ++j) {
        safe_free(hdl->server.gui_options->PullDownItemStrings[i][j]);
      }
      safe_free(hdl->server.gui_options->PullDownItemStrings[i]);
    }
    safe_free(hdl->server.gui_options->PullDownTitle);  
         hdl->server.gui_options->PullDownTitle = NULL;
    safe_free(hdl->server.gui_options->PullDownNumberInList);
         hdl->server.gui_options->PullDownNumberInList = NULL;
    safe_free(hdl->server.gui_options->PullDownDefaultSelection);
         hdl->server.gui_options->PullDownDefaultSelection = NULL;
    safe_free(hdl->server.gui_options->PullDownUserSelection);
         hdl->server.gui_options->PullDownUserSelection = NULL;
    safe_free(hdl->server.gui_options->PullDownItemStrings);
         hdl->server.gui_options->PullDownItemStrings = NULL;
    hdl->server.gui_options->iNumPullDowns = 0;
  }

  /* Free any toggles
   *-----------------*/
  if( hdl->server.gui_options->iNumToggles ) {
    if( print_flag(hdl) >=Z_FULL ) {
      USERD_info(" Freeing %d Toggles\n", hdl->server.gui_options->iNumToggles);
    }
    for(int i=0; i<hdl->server.gui_options->iNumToggles; ++i) {
      safe_free(hdl->server.gui_options->ToggleTitle[i]);
    }
    safe_free(hdl->server.gui_options->ToggleTitle);
         hdl->server.gui_options->ToggleTitle = NULL;
    safe_free(hdl->server.gui_options->ToggleDefaultStatus);
         hdl->server.gui_options->ToggleDefaultStatus = NULL;
    safe_free(hdl->server.gui_options->ToggleUserSelection);
         hdl->server.gui_options->ToggleUserSelection = NULL;
    hdl->server.gui_options->iNumToggles = 0;
  }

  /* Free any fields
   *----------------*/
  if( hdl->server.gui_options->iNumFields ) {
    if( print_flag(hdl) >= Z_FULL ) {
      USERD_info(" Freeing %d Fields\n", hdl->server.gui_options->iNumFields);
    }
    for(int i=0; i<hdl->server.gui_options->iNumFields; ++i) {
      safe_free(hdl->server.gui_options->FieldTitle[i]);
      safe_free(hdl->server.gui_options->FieldUserSelection[i]);
    }
    safe_free(hdl->server.gui_options->FieldTitle);
         hdl->server.gui_options->FieldTitle = NULL;
    safe_free(hdl->server.gui_options->FieldUserSelection);
         hdl->server.gui_options->FieldUserSelection = NULL;
    hdl->server.gui_options->iNumFields = 0;
  }

  /* Free the gui options pointer
   *-----------------------------*/
  if( hdl->server.gui_options ) {
    if( print_flag(hdl) >= Z_FULL) {
        USERD_info(" Freeing server.gui_options\n");
    }
    safe_free(hdl->server.gui_options);
         hdl->server.gui_options = (UserDefinedGUI_10 *)NULL;
  }

  return(Z_OK);
}

Note:  See the test3u_advanced reader, included with your EnSight install, for better and more current details.