1.1.3 Programming in Code Builder

Click on the Code Builder button Ocguide xfdialog codebuilderbutton.png to open the X-Function in Code Builder, where we can write our Origin C code.

Editor Window

There are two buttons near the top of the editor window: a Compile buttonOcguide XF Compile Button.PNG and a Return to Dialog buttonOcguide XF Returntodialog Button.PNG. The Compile button is used to compile your X-Function's Origin C code. The Return to Dialog button will close the editor window and return you to the X-Function Builder dialog.

In the editor you will notice some of the Origin C code has a gray background. These parts of the code are read-only and cannot be changed. The X-Function framework generated these parts of the code and they are in a required syntax.

Include Header Files

You can include additional header files in your X-Function's Origin C code. While not required, it is recommended that you include your additional header files near the top of the file, after the following line:

//put additional include files here

This recommendation is to help keep the file organized and to be consistent with other X-Functions.

Search Paths

When you include files using the < and > brackets, then those files are included from the Origin C System folder located in the Origin installation folder. You can still provide a relative path to move above the System folder. These brackets behave the same when compiling .c and .cpp files in Origin C.

// Include fft_utils.h located in the "OriginC\System" folder.
#include <fft_utils.h>

// Include abffiles.h located in the "OriginC\OriginLab" folder
#include <..\OriginLab\abffiles.h> // relative path

When you include files using double quotes, then those files are included from the "OriginC\X-Functions" folder in your "User Files" folder. This behavior is different than when you compile a .c or .cpp file in Origin C. This different behavior is necessary because X-Functions are installed in a location maintained by Origin.

// Include myOtherHeader.h located in the "OriginC\X-Functions"
// folder of the "User Files" folder.
#include "myOtherHeader.h"

If you specify an absolute path between double quotes, then that file will be included regardless of where the file is located.

Auto Compile Dependent Files

In X-Function Builder's Tree View there is an option named Auto Compile Dependent Files. When this option is turned on it will cause the compiler to check for a .c or .cpp file sharing a name with an included .h file. If a .c or .cpp file is found then it will be loaded and compiled too.

// Include graph_utils.h located in the "OriginC\Originlab" folder
// If Auto Compile Dependent Files is turned on
// then graph_utils.c, located in the same folder, will be loaded and compiled
#include <..\Originlab\graph_utils.h>

Define Internal Functions

In order to provide more clarity and readability, to make your code easier for future understanding and maintenance, it is recommended that you break a long function into functionally independent and well-structured short functions, which is also proposed in some other programming languages. In an X-Function, you can add these short functions in as internal functions with the keyword static after the following line.

//put your own support static functions here

For example, in many X-Functions with lots of interaction from the GUI, many codes will be needed in xfname_event1( ), and then you can add a static function, similiar to Origin's interp1 X-Function.

static void _update_method_show(TreeNode& trGetN)

As you can see, it is also recommended that you use an underscore to separate the components in a function name.

Main Function

The main function is where you put all the code that performs the primary tasks of your X-Function.

Your X-Function's main function will have the same name you gave your X-Function in X-Function Builder. For example, if you named your X-Function myXFunc then the main function will also be named myXFunc.

The arguments passed to the main function are the variables listed in the X-Function Builder dialog. All the variables set as Input are passed in as constant references while the variables set as Output or Input/Output are passed in as writable references.

Event Handling Functions

Your X-Function's source code contains functions used for handling various events. The name of each event handler function is prefixed with the X-Function's name followed by an underscore character followed by the event name. For example; if your X-Function's name is myXFunc then the before_execute event handler function will be named myXFunc_before_execute.

The following is a list of events:

  • before_execute
  • event1
  • event1_ex
  • make_tree

By default all the event handler functions are empty. You only need to add code to an event handler function when you want to change the default behavior or do some additional processing during an event.

The following sections provide more details about each of the event handler functions including their purpose, parameters passed in, and return type.

before_execute

This function will be called before execution of the main function and will be called two or three times.

Prototype

void xfname_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)

Parameters

trGetN

A TreeNode containing the variables passed to the X-Function.

nGetNDialog

An integer value indicating when the function is being called.

A value greater than zero indicates the function is being called before showing its dialog. This happens when choosing Open Dialog from a menu, programmatically calling the X-Function with the -d option, or choosing Change Parameters for a manual recalculate.

Value Before Opening Dialog for...
1 Simple GetNBox
2 GetNGraphBox with Preview
3 GetNImageBox

A value of -1 indicates the dialog was closed by the user clicking the OK button.

A value of zero indicates the main function is about to be called.

nRet

This option can control the execution states of the X-Function.

XFEVT_PROCEED         = 0 // Follow with normal execution
XFEVT_ABORT           = 1 // Abort execution
XFEVT_PROCEED_NO_DLG  = 2 // Execute silently without opening dialog.

dwCntrl

This option can be used to determine how this X-Function is accessed. Possible values are enumerated as:

LTXF_FROM_GUI_MENU              // Accessed from menu
LTXF_FROM_GUI_PROMPT            // Accessed from command window
LTXF_FROM_AUTO_UPDATE           // Accessed for Auto-update
LTXF_FROM_FUNCTION              // Accessed from Origin C function
LTXF_THEME_USED                 // Theme is used
LTXF_CHANGE_PARAM               // Accessed for Change Parameters

The following example shows how to check if the X-Function is accessed from the command window and a theme is also used (type xfname -t themename in the command window).

if(!(dwCntrl & LTXF_FROM_GUI_PROMPT) && (dwCntrl & LTXF_THEME_USED))
{
    // handle this case
}

make_tree

This function is called once for each TreeNode variable passed to the X-Function. The calls occur before the before_execute function is called.

Prototype

int xfname_make_tree(TreeNode& tr, LPCSTR lpcszVarName)

Return

Return zero to update the dialog or -1 to not update the dialog. The default behavior returns -1.

Parameters

tr

The TreeNode to be created, which should have been defined as an input TreeNode type variable of the X-Function.

lpcszVarName

The name of the TreeNode variable.

event1 and event1_ex

These are the primary event handling functions. They will be called by any event, such as dialog initialization, changes to any settings in the dialog, button clicking, and more. These functions are only used in X-Functions with a simple GetN dialog. X-Functions with a graph preview or an image preview use a different set of event handler functions and are discussed in a later section.

Prototype

int xfname_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables,
    LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer,
    string& strAux, string& strErrMsg)

Return

If returning true, the dialog will be updated.

Parameters

trGetN

This is the tree node of the variables defined in the X-Function.

nRow

The index of the row of the value-changed control node in TreeNode trGetN. The value will be -1 when the event is not 'control value changed'.

nEventID

Event type ID. For example, GETNE_ON_INIT, GETNE_ON_THEME.

dwEnables

This parameter is used to enable or disable the OK, Apply or other custom button. It is true by default, and will usually be set to false when the user's settings are invalid, so as to disable the OK or Apply button.

lpcszNodeName

If the event is generated by a control change in the dialog, it will be the variable name of this control. Otherwise, it will be an empty string.

DynaCntrlContainer

X-Function dialog window container.

strAux

This parameter is the auxiliary string, which is for advanced usage. Please refer to the header file <Origin Installation Directory>\OriginC\System\GetNBox.h for more details like the following definition.

#define DLG_NEED_CHANGE_GRID "GETN_CHANGE_GRID"
#define GETN_CHANGE_GRID  set_aux_value(strAux, DLG_NEED_CHANGE_GRID);

strErrMsg

This is the string message that will be shown in the bottom of the dialog. It is usually used to notify the user of any errors that occurred during the input of variable values.

GetNGraphPreview Event Handler Functions

The event1 and event1_ex event handler functions are not used by X-Functions that have a graph preview dialog. Instead you use the GetNGraphPreview functions.

  • GetNGraphPreview_OnInitGrid
This event function is used to initialize the controls on the dialog.
  • GetNGraphPreview_OnInitGraph
This event function is used to initialize the preview graph.
  • GetNGraphPreview_OnUpdateGraph
This event function is used to update the preview graph on other events, for example, GUI changed.
  • GetNGraphPreview_OnChange
Any change will trigger this event function, and this function will decide whether to update the preview graph or update the dialog on this change.
  • GetNGraphPreview_OnDialogSetup
  • GetNGraphPreview_OnDestroy
  • GetNGraphPreview_OnCustomButton


See the Creating Graph Preview GetN Dialog section for an example of how to create an X-Function with a graph preview dialog.

GetNImageBox Event Handler Functions

The event1 and event1_ex event handler functions are not used by X-Functions that have an image preview dialog. Instead you use the GetNImageBox functions.

  • GetNImageBox_OnInit
The event function called when the image GetN dialog is open. The function can decide whether to update the dialog, enable/disable the OK button or show an error message on the bottom of the dialog after calling.
  • GetNImageBox_OnChange
The event function called whenever any control on the dialog is modified by the user. This function can decide whether to update the dialog, update the image preview, enable/disable the OK button, or show an error message on the bottom of the dialog.

See the Creating Image GetN Dialog section for an example of how to create an X-Function with an image preview dialog.

Error Handling

Display an Error Message in the Dialog

When a user passes a bad value to your X-Function and also passes the -d option, or enters a bad value in the X-Function's dialog, you can display an error message in the dialog by setting the strErrMsg argument passed into the event handler function.

Which event handler function is called depends on the GetN Dialog your X-Function uses.

GetN Dialog Used Event Handler Function
Simple GetNBox xfname_event1
GetNGraphBox with Preview GetNGraphPreview_OnChange
GetNImageBox GetNImageBox_OnChange

Let us assume we have an X-Function that accepts an integer variable named x1. The following code snippet, inserted into the appropriate event handler function, checks the x1 variable's value to see if it is less than zero or greater than 100. If it is then it sets the strErrMsg to an appropriate message to display in the dialog, and also disables the OK button. If the value is within the accepted range then it simply makes sure the OK button is enabled.

if( trGetN.x1.nVal < 0 || 100 < trGetN.x1.nVal )
{
    strErrMsg = "x1 is out of range.  Must be from zero to 100.";
    bOKEnable = false;
}
else
    bOKEnable = true;

Output Error Message

When an X-Function is being called programmatically and its dialog is not going to be shown, then you need another way to notify the user of any errors that may occur. Origin C has defined macros to output an error message to the Results Log, Command Window or Script Window. It is strongly recommended that you use these macros instead of out_str or printf.

The XF_WARN macros are used to output warning messages and do not terminate execution. All three macros accept a string as the first argument, containing the warning message. The two macros that accept additional arguments assume the warning message is also a format string for outputting one or two values.

  • XF_WARN(msg)
  • XF_WARN_EX(msg, arg1)
  • XF_WARN_EX2(msg, arg1, arg2)
// Assume the following:
// #define MIN_DATA_POINTS 5
// int nNumPts = 3;
// string strWksName = "Book1";
XF_WARN("Too few data points.");
XF_WARN_EX("Number of data points less than %d.", MIN_DATA_POINTS);
XF_WARN_EX("Worksheet named %s was not found.", strWksName);
XF_WARN_EX2("Only %d data points, need at least %d.", nNumPts, MIN_DATA_POINTS);

The XF_TRACE macro is similar to the XF_WARN macros in that it does not terminate execution. It also takes a message for the first argument, but it allows any number of additional arguments.

  • XF_TRACE(msg, ...)
// Assume the following:
// #define MIN_DATA_POINTS 5
// int nNumPts = 3;
// string strWksName = "Book1";
XF_TRACE("Only %d data points found in %s, need at least %d.",
    nNumPts, strWksName, MIN_DATA_POINTS);

The XF_THROW macros terminate execution, but everything else about them is the same as the XF_WARN macros. All three macros accept a string containing the warning message as the first argument. The two macros that accept additional arguments assume the warning message is also a format string for outputting one or two values.

  • XF_THROW(msg)
  • XF_THROW_EX(msg, arg1)
  • XF_THROW_EX2(msg, arg1, arg2)
// Assume the following:
// #define MIN_DATA_POINTS 5
// int nNumPts = 3;
// string strWksName = "Book1";
XF_THROW("Too few data points.");
XF_THROW_EX("Number of data points less than %d.", MIN_DATA_POINTS);
XF_THROW_EX("Worksheet named %s was not found.", strWksName);
XF_THROW_EX2("Only %d data points, need at least %d.", nNumPts, MIN_DATA_POINTS);