Build a JavaScript dialog and Call Origin C in the Upcoming Origin 2017

Building an Origin C based dialog is challenging in two aspects:

  1. The complexity of C++ based coding and Origin C specific implementations
  2. The need to build a resource DLL using Visual Studio

In Origin2017, we have a new mechanism to create a dialog without a resource DLL. Such a dialog will be built by html & JavaScript, like a web page. By this way developers will have more flexibility of dialog design and style.

Documentation on this feature is available online.

In this post, we will show you how to build a simple calculator using this new Origin feature. This example will focus on showing JavaScript code calling Origin C functions. The reverse call, Origin C calling JavaScript, is also supported in Origin 2017, but will not be covered in this simple example.

Before we started, we need to build a calculator interface by HTML. For example:

<!DOCTYPE html>
<html>
	<head>
		<title>Origin Calculator</title>
		<meta name="viewport" content="initial-scale=1.0">
    	        <meta charset="utf-8">
    	<script>
    	</script>

	</head>

	<body>
		<div id="Equation" style="border:solid;height:20px;"></div>
		<div id="Ops">
        	<input type="button" id="btnPlus" value="+" onclick="" />
        	<input type="button" id="btnMinus" value="-" onclick="" />
        	<input type="button" id="btnMultiply" value="X" onclick="" />
        	<input type="button" id="btnDiv" value="/" onclick="" />
        </div>
        </br>
        <div id="Num789">
        	<input type="button" id="btn7" value="7" onclick="" />
        	<input type="button" id="btn8" value="8" onclick="" />
        	<input type="button" id="btn9" value="9" onclick="" />
        </div>
        <div id="Num456">
        	<input type="button" id="btn4" value="4" onclick="" />
        	<input type="button" id="btn5" value="5" onclick="" />
        	<input type="button" id="btn6" value="6" onclick="" />
        </div>
        <div id="Num123">
        	<input type="button" id="btn1" value="1" onclick="" />
        	<input type="button" id="btn2" value="2" onclick="" />
        	<input type="button" id="btn3" value="3" onclick="" />
        </div>
        </br>
        <div>
        	<input type="button" id="btnCalculate" value="Calculate" onclick="" />
        	<input type="button" id="btnClear" value="Clear" onclick="" />
        </div>
    </div>
	</body>
</html>

From the interface design, we will need three types of functions: Add a char to the end of the equation, calculate the equation and clear the box.

Let’s go back to Origin and create a blank cpp file. First, we need to include two extra header files, the one called HTMLDlg.h is new in Origin2017 and that’s the one that hooks Origin and your HTML dialog together.

#include <Origin.h>
#include <..\OriginLab\DialogEx.h>
#include <..\OriginLab\HTMLDlg.h>

Now let’s create the dialog class

class OriginCalculatorDlg: public HTMLDlg {
public:
	string GetInitURL();
	string GetDialogTitle();
protected:
	string AddOp(string str, string strOp);
        string AddNum(string str, int NewNum);
        double Calculate(string str);
        string Clear();
};

The first public method is the key to link the dialog to this source code, in this example, we used a special char (__FILE__) represents the same folder location where the current cpp file is.

string OriginCalculatorDlg::GetInitURL() {
	string strPath = GetFilePath(__FILE__);
	strPath += "SimpleCalc.html";    //html file in same folder as this cpp file
	return strPath;
}

Then provide the title of the dialog by:

string OriginCalculatorDlg::GetDialogTitle() {
	string strTitle("Simple Calculator");
	return strTitle;
}

We separated the adding char to the end function to two cases, string for operations and numeric for numbers, just for showing how to pass different variable type form html dialog to OriginC:

string OriginCalculatorDlg::AddOp(string str, string strOp) {
	return str + " " + strOp + " ";
}

string OriginCalculatorDlg::AddNum(string str, int NewNum) {
	return str + ftoa(NewNum);
}

Then, define the calculation and clear function:

double OriginCalculatorDlg::Calculate(string str) {
	double dd;
	LT_evaluate(str ,&dd); 
	return dd;
}

string OriginCalculatorDlg::Clear(void) {
	return "";
}

Finally, add the following special macro so that the JavaScript in the HTML can locate where those functions are.

public:
	DECLARE_DISPATCH_MAP

After the class declaration, list the detailed function list.

BEGIN_DISPATCH_MAP(OriginCalculatorDlg, HTMLDlg)
	DISP_FUNCTION(OriginCalculatorDlg, AddOp, VTS_STR, VTS_STR VTS_STR)    // DISP_FUNCTION(ClassName, MethodName, OutputType, InputType1 InputType2 ...)
	DISP_FUNCTION(OriginCalculatorDlg, AddNum, VTS_STR, VTS_STR VTS_I4)
	DISP_FUNCTION(OriginCalculatorDlg, Calculate, VTS_R8, VTS_STR)
	DISP_FUNCTION(OriginCalculatorDlg, Clear, VTS_STR, VTS_VOID)
END_DISPATCH_MAP

In the html JavaScript, use window.external.ExtCall(FunctionName, Input1, Input2, …) to call the Origin C functions in the header.

<script>
    	var PlusOp = "+";
    	var MinusOp = "-";
    	var MultiplyOp = "*";
    	var DivOp = "/";

    	function Invoke_AddOp(strOp) {
    		var OriginStr = document.getElementById('Equation').innerHTML;
    		var NewStr = window.external.ExtCall("AddOp", OriginStr, strOp);
   		document.getElementById('Equation').innerHTML = NewStr;
    	}

    	function Invoke_AddNum(NewNum) {
    		var OriginStr = document.getElementById('Equation').innerHTML;
    		var NewStr = window.external.ExtCall("AddNum", OriginStr, NewNum);
    		document.getElementById('Equation').innerHTML = NewStr;
    	}

    	function Invoke_Cal() {
    		var Str = document.getElementById('Equation').innerHTML;
    		var Result = window.external.ExtCall("Calculate", Str);
    		document.getElementById('Equation').innerHTML = Result;
    	}

    	function Invoke_Clear() {
    		document.getElementById('Equation').innerHTML = window.external.ExtCall("Clear");
    	}

</script>

Then you can call those functions by the buttons you created. For example:

<input type="button" id="btnPlus" value="+" onclick="Invoke_AddOp(PlusOp)" />
...
<input type="button" id="btn7" value="7" onclick="Invoke_AddNum(7)" />
...
<input type="button" id="btnCalculate" value="Calculate" onclick="Invoke_Cal()" />

Now we have hooked the html and Origin C together. Create a main function at the end of the cpp file to launch the dialog.

void calc() {
	OriginCalculatorDlg dlg;
	dlg.DoModalEx(GetWindow());
}

You can download this zip to see the code, or download more examples here.

About S Z

Male, single, alive.

View all posts by S Z →

Leave a Reply

Your email address will not be published. Required fields are marked *