Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

GUI Composer/FileOperations

From Texas Instruments Wiki
Jump to: navigation, search

File Operations in GUI Composer

Overview

GUI Composer version 6 introduces file access APIs that will enabled GUI Composer applications to have functionality similar to common desktop applications: New / Open / Save / Save as....

In this example you are a GUI Composer application developer. Following this example you will create a GUI Composer application that demonstrates how to implement such functionality. We assume that you are familiar with Code Composer Studio, GUI Composer and writing Javascript code. You will create a GUI Composer application that allows the user to open a text file and edit it in a Text Area widget. The user will be able to save the changes back in the same file or to a new file on the local file system.

The GUI Composer project can be downloaded from FileOperations.zip and imported to GUI Composer(Requires CCSv6 and higher).


Create a GUI composer app

  • From the CC App Center install GUI Composer and Javascript Development tools - Code Composer Studio Add-ons (if not already installed).
  • Open GUI Composer.
  • Create a new GUI Composer project – name it FileOperations


Add all widgets to the app

We will add a Text Area widget where the user will be able to edit the text file, all buttons, as well as the text box that displays the name of the currently edited file.

Here is the app with all the widget it in:

FileOperationsApp.png

  • Drag and drop a Text Area widget to the working area of GUI Composer.
  • Rename the Text Area widget id in the property page on the right pane to widget_data.
  • Resize the widget and increase its rows property to 12, so the user can see bigger part of the text file.
  • Drag four buttons New, Open..., Save and Save as... to the left side of the working area.
  • Set their ids to: widget_new, widget_open, widget_save and widget_save_as.
  • Select each of the buttons in the work area and then select the Events section in the property page on the right and set their onclick events to onNew(), onOpen(), onSave() and onSaveAs().
  • Drag and drop a TextBox widget and set its widget it to widget_path.
  • Drag and drop a label widget and set its text to Path.


Add the Javascript code in app.js

Now we will add all Javascript code necessary to make the example work. We will add different functions as we need them and explain their purpose. The whole Javascript file is listed at the end of the document. You can copy and paste it from there to your project.

First we will add some helper functions.

function getFileInfo() {
	return {
		localPath : dijit.byId( 'widget_path').get('value')
	};
}
 
function clearEdit( id) {
	dijit.byId( id).set('value','');
}
 
function clearAll() {
	clearEdit('widget_data');
	clearEdit('widget_path');
}
 
function updateButtons() {
	var fileInfo = getFileInfo();
	var enabled = !!fileInfo.localPath;
	dijit.byId('widget_save').set('disabled', !enabled);
}


getFileInfo() – The GUI Composer file access APIs expect as input parameter an object that has a member localPath. We keep this path in the value property of widget_path widget.

clearEdit(id) – Clears the value property if a widget.

clearAll() – clears both the Text Area widget and the path Text Box.

updateButtons() – when the path is empty the Save buttons should be disabled.


When the application is initially loaded we will subscribe to changes in widget_path. On every change of that property we will update the Save button.

require(["dojo/ready"], function(ready){
     ready(function(){
		 dijit.byId('widget_path').watch('value', function ( prop, newValue, oldValue) {
			 updateButtons();
		 });
		 updateButtons();
     });
});

The handler onNew() will clear the Text Area data and the path. That will trigger update of the buttons.

function onNew() {
	clearAll();
}

Now we will add the remaining helper functions that will be used in the rest of the event handlers.

function getOptions() {
	return {
		clientLocation : 'auto'
	}
}
 
function showError( errorInfo) {
	if( errorInfo) {
		$TI.helper.showError( "Error!", errorInfo.message);
	}
}
 
function getData() {
	return dijit.byId('widget_data').get('value');
}
 
function setData( data) {
	dijit.byId('widget_data').set('value', data);
}
 
function setFileInfo( fileInfo) {
	if( fileInfo && typeof fileInfo.localPath !== 'undefined') {
		dijit.byId( 'widget_path').set('value', fileInfo.localPath);
	};
}


getOptions() – GUI Composer file access APIs expect an object that control the behavior of the API. In this version an object with clientLocation set to auto is supported.

showError() - Displays an error dialog if there is an error returned from the file access APIs.

getData() - Gets the content of the Text Area widget.

setData() – Sets the content of the Text Area widget.

setFileInfo() – transfers the fileInfo object returned from the file access APIs to the widget_path Text Box.

Now the functions onOpen(), onSave() and onSaveAs() will just use the appropriate helpers and calls the APIs: TI.File.browseAndLoad(), TI.File.save() and TI.File.browseAndSave().


function onOpen() {
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( data, fileInfo, errorInfo) {
		setFileInfo( fileInfo);
		setData( data);
		showError( errorInfo);
	};
	TI.File.browseAndLoad( fileInfo, options, callback);
}
 
function onSave() {
	var data = getData();
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( errorInfo) {
		showError( errorInfo);
	};
	TI.File.save( data, fileInfo, options, callback);
}
 
function onSaveAs() {
	var data = getData();
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( fileInfo, errorInfo) {
		setFileInfo( fileInfo);
		showError( errorInfo);
	};
	TI.File.browseAndSave( data, fileInfo, options, callback);
}

And that is all.


Here is the full content of the file app.js

/*
 * This file is provided for custom JavaScript logic that your HTML files might need.
 * GUI Composer includes this JavaScript file by default within HTML pages authored in GUI Composer.
 */
require(["dojo/ready"], function(ready){
	ready(function(){
		 dijit.byId('widget_path').watch('value', function ( prop, newValue, oldValue) {
			 updateButtons();
		 });
		 updateButtons();
	});
});
 
function getFileInfo() {
	return {
		localPath : dijit.byId( 'widget_path').get('value')
	};
}
 
function clearEdit( id) {
	dijit.byId( id).set('value','');
}
 
function clearAll() {
	clearEdit('widget_data');
	clearEdit('widget_path');
}
 
function updateButtons() {
	var fileInfo = getFileInfo();
	var enabled = !!fileInfo.localPath;
	dijit.byId('widget_save').set('disabled', !enabled);
}
 
function onNew() {
	clearAll();
}
 
function getOptions() {
	return {
		clientLocation : 'auto'
	}
}
 
function showError( errorInfo) {
	if( errorInfo) {
		$TI.helper.showError( "Error!", errorInfo.message);
	}
}
 
function getData() {
	return dijit.byId('widget_data').get('value');
}
 
function setData( data) {
	dijit.byId('widget_data').set('value', data);
}
 
function setFileInfo( fileInfo) {
	if( fileInfo && typeof fileInfo.localPath !== 'undefined') {
		dijit.byId( 'widget_path').set('value', fileInfo.localPath);
	};
}
 
function onOpen() {
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( data, fileInfo, errorInfo) {
		setFileInfo( fileInfo);
		setData( data);
		showError( errorInfo);
	};
	TI.File.browseAndLoad( fileInfo, options, callback);
}
 
function onSave() {
	var data = getData();
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( errorInfo) {
		showError( errorInfo);
	};
	TI.File.save( data, fileInfo, options, callback);
}
 
function onSaveAs() {
	var data = getData();
	var fileInfo = getFileInfo();
	var options = getOptions();
	var callback = function ( fileInfo, errorInfo) {
		setFileInfo( fileInfo);
		showError( errorInfo);
	};
	TI.File.browseAndSave( data, fileInfo, options, callback);
}


Testing the example

  • Preview the app in the GUI Composer editor.
  • Type something in the Text Area widget.
  • Select the button Save as... and browse to a location of the local file system.
  • From the File Explorer verify that a file is crated and its content is the same as the Text Area widget.
  • Select the button New.
  • The content of the Text Area widget and the Path Text Box is cleared.
  • Select the button Open... and browse the file we just saved.
  • The Text Area will display the content of the file.
  • The Path Text Box will show the path to the file.
  • Select the button Save as... and browse to another file.
  • The Path Text Box will show the new path.