compar.sml

  Download

More scripts: Display Toolbar

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
# View ToolScript
# This tool opens a Command Parser window that can be used to paint raster cell values.
#
# To use this tool follow these steps. 
# 1.   Add the compar.sml tool script icon to the View window, 
#      (View window / Options menu / Customize / Tool Scripts).
# 2. Create a comma separated value (CSV) file with standard color values.
#      Either create your own CSV file or, if you have an 8-bit raster that has a color map
#      you want to use universally, add the raster to the View and enter the 't' command in 
#      the Command Parser window.  (Click the Command Parser tool icon to open the Command Parser
#      window.) CSV file can be edited with a text editor or spreadsheet program.
#      Example CSV values:
#        Index    Red    Green    Transparency
#        0        0      0        50
#        1        0      100      50
#        2        75     75       50
#        .        .      .        .
#        .        .      .        .
#        .        .      .        .
#        255      0      0        100
#
#     The CSV file's index indicates a color value when used to paint (p and pr commands) 
#     or a cell value when the CSV file is copied to or from a color palette (t command).  
#     The color component values and transparency values are a percentages that determine 
#     display parameters (any value from 0 to 100 is valid).  
#     You must have an entry for all possible index values: 0 to 255.
#
# If you want to use this tool to classify an image:
# 1. Add the image you want to classify as a reference layer and set the Contrast 
#    enhancement to stretch the cell values for improved display. Add any other 
#    reference layers you want.
# 2. Add the same image again and make sure the Contrast is set to None.  This image will 
#    look like a class raster when displayed with the new color map you are creating.  
#    The raster cells retain their original values.  Make sure this image is the top 
#    layer and select it in the Layer Controls window before you enter any commands.
# 3. Click the Command Parser tool icon to open the Command Parser window.
# 4. Enter the following commands to get ready to paint:
#      lc        (make a new SMLcolor palette from a CSV file, raster must already have a color map)
#      b         (copy a CSV file into an array used to hold paint colors)
# 5. Change class raster's Color Palette to SMLcolor, Contrast to None, and enter the 
#    following command:
#      r,0,255   (cell value 0 to 255 becomes transparent - layer is now invisible)
# 6.  Look at the reference layers to find cell values belonging to a class.  Use the p and 
#     pr commands to paint cell's a specific color corresponding to the appropriate class.
#
# 
# The following symbols are predefined 
#    class VIEW View            {use to access the view the tool script is attached to} 
#    class GROUP Group          {use to access the group being viewed if the script is run from a group view} 
#    class LAYOUT Layout        {use to access the layout being viewed if the script is run from a layout view} 
#    number ToolIsActive        Will be 0 if tool is inactive or 1 if tool is active 
# 
# The following values are also predefined and are valid when the various On...() 
# functions are called which deal with pointer and keyboard events. 
#    number PointerX            Pointer X coordinate within view in pixels 
#    number PointerY            Pointer Y coordinate within view in pixels 
#    number ShiftPressed        1 if <shift> key being pressed or 0 if not 
#    number CtrlPressed         1 if <ctrl> key being pressed or 0 if not 
#    number LeftButtonPressed   1 if left pointer button pressed or 0 if not 
#    number RightButtonPressed  1 if right pointer button pressed or 0 if not 
#    number MiddleButtonPressed 1 if middle pointer button pressed or 0 if not 
# 
# The following script functions will be called (if used in the script) when 
# the appropriate action or event occurs as described in the comments before each. 
# To use a function, uncomment the lines containing the 'func' definition 
# and ending brace '}' by removing the leftmost '#' on the line and add the 
# function code between the two lines. 
#allowable width of command
numeric width;
#change this number if you want a longer/shorter command field
width = 20;
#string that seperates commands and parameters
string delim;
#change this if you want some other string to seperate them
delim = ",";
#global variables
class PromptStr Command;
class PromptStr Status;
numeric setDefaultWhenClose;
numeric i;
class RASTER rast;
class ColorMap cmap;
class Color mycolor;
class FILE myfile;
array numeric ared[256];
array numeric agreen[256];
array numeric ablue[256];
array numeric atransp[256];
numeric hascolorarray;
hascolorarray = 0;
proc OrderPizza() {
	string where;
	numeric number;
	#checks to see if the number of paramters (tokens) is correct for this function
	if (NumberTokens(Command.value,delim) != 3) {
		PopupMessage("Not enough or too many parameters for OrderPizza function");
		return;
	}
	Status.value = "OrderPizza function started";
	#gets the second parameter off of the commmad prompt string and stores it in a string
	#note the first token is the code that got you to this function from ParseCommand
	where = GetToken(Command.value,delim,2);
	#gets the third parameter off of the command string and stores it in a numeric
	number = StrToNum(GetToken(Command.value,delim,3));
	#example of how to perform parameter checking on arguments
	if (number > 10) {
		PopupMessage("You can't eat that many pizzas");
		return; # this is "fatal" so return from function
	}
	PopupString("You ordered pizzas from",where);
	PopupNum("You ordered this many",number);
	Command.value = "";  #clears command prompt letting you reenter same command twice in a row
	Status.value = "OrderPizza function complete";
}
proc OutputColorMap() {
	if (Group.ActiveLayer.Type == "Raster") {
		DispGetRasterFromLayer(rast,Group.ActiveLayer);
		cmap = ColorMapFromRastVar(rast);
		#if cmap.name is empty then we have no color map to export so exit
		if (cmap.name == "") {
			PopupMessage("No ColorMap was found in raster object Paint function aborted\n Use lc command to save a csv file as a colormap in the raster object first\n or create one yourself");
			Command.value = "";
			Status.value = "OutputColorMap aborted";
			return;
			}
		myfile = GetOutputTextFile("c:/color.csv","Select file for output:" , "csv");
		fprintf(myfile,"%s,%s,%s,%s,%s\n","Index","Red","Green","Blue","Transparency");
		Status.value = "Outputting Colormap";
		for i = 0 to 255 {
			mycolor = ColorMapGetColor(cmap,i);
			#range of RGB values is 0-100
			fprintf(myfile,"%d,%d,%d,%d,%d\n",i,round(mycolor.red),round(mycolor.green),round(mycolor.blue),round(mycolor.transp));
			}
		fclose(myfile);
		Status.value = "Colormap outputted";
		Command.value = "";
	}
	else {
		Status.value = "Active Layer must be a raster w/colormap for this function";
		Command.value = "";
	}
}
proc TranspValues() {
	if (NumberTokens(Command.value,delim) != 3) {
		Status.value = "Not enough parameters for TranspValues function";
		return;
	}
	local numeric start;
	local numeric stop;
	start = StrToNum(GetToken(Command.value,delim,2));
	stop  = StrToNum(GetToken(Command.value,delim,3));
	if (Group.ActiveLayer.Type != "Raster") {
		PopupMessage("Active Layer must be a raster object for this function");
		Command.value = "";
		Status.value = "Active layer must be a raster";
		return;
		}
	DispGetRasterFromLayer(rast,Group.ActiveLayer);
	cmap = ColorMapFromRastVar(rast);
	if (cmap.name == "") {
		PopupMessage("No ColorMap was found in raster object Paint function aborted\n Use lc command to save a csv file as a colormap in the raster object first\n or create one yourself");
		Command.value = "";
		Status.value = "TranspValues aborted";
		return;
		}
	Status.value = "Making cells transparent";
	for i = start to stop {
		mycolor = ColorMapGetColor(cmap,i);
		mycolor.transp = 100;
		ColorMapSetColor(cmap,i,mycolor);
	}
	ColorMapWriteToRastVar(rast,cmap,cmap.Name,cmap.Desc);
	#force rasterlayer to reload colormap
	View.DisableRedraw = 1;
	LayerDestroy(Group.ActiveLayer);
	GroupQuickAddRasterVar(Group,rast);
	Group.ActiveLayer.AllowDeleteLayer = 1;
	View.DisableRedraw = 0;
	ViewRedraw(View);
	Status.value = "Cells made transparent";
	Command.value = "";
}
proc Paint() {
	if (NumberTokens(Command.value,delim) != 3) {
		Status.value = "Not enough parameters for Paint function";
		return;
	}
	if (!hascolorarray) {
		PopupMessage("Use code b (SetColorArray function) to load a colormap to use first");
		Status.value = "Paint function aborted";
		Command.value = "";
		return;
	}
	local numeric cellvalue;
	local numeric colornumber;
	cellvalue = StrToNum(GetToken(Command.value,delim,2));
	colornumber = StrToNum(GetToken(Command.value,delim,3));
	if (Group.ActiveLayer.Type != "Raster") {
		PopupMessage("Active Layer must be a raster object for this function");
		Command.value = "";
		Status.value = "Active layer must be a raster";
		return;
		}
	DispGetRasterFromLayer(rast,Group.ActiveLayer);
	cmap = ColorMapFromRastVar(rast);
	if (cmap.name == "") {
		PopupMessage("No ColorMap was found in raster object Paint function aborted\n Use lc command to save a csv file as a colormap in the raster object first\n or create one yourself");
		Command.value = "";
		Status.value = "Paint function aborted aborted";
		return;
		}
	#	mycolor = ColorMapGetColor(cmap,cellvalue);
	#could read in what there already and only change what is needed
	#assumes that you reference the color numbers 0-255 the plus one is to get the
	#correct array entry since SML arrays start at 1 see SetColorArray function
	mycolor.red = ared[colornumber+1];
	mycolor.green = agreen[colornumber+1];
	mycolor.blue = ablue[colornumber+1];
	mycolor.transp = atransp[colornumber+1];
	ColorMapSetColor(cmap,cellvalue,mycolor);
	ColorMapWriteToRastVar(rast,cmap,cmap.Name,cmap.Desc);
	#force raster to reload colormap
	View.DisableRedraw = 1;
	LayerDestroy(Group.ActiveLayer);
	GroupQuickAddRasterVar(Group,rast);
	Group.ActiveLayer.AllowDeleteLayer = 1;
	View.DisableRedraw = 0;
	ViewRedraw(View);
	Status.value = "Cell Painted";
	Command.value = "";
}
proc PaintRange() {
	if (NumberTokens(Command.value,delim) != 4) {
		Status.value = "Not enough parameters for PaintRange function";
		return;
	}
	if (!hascolorarray) {
		PopupMessage("Use code b (SetColorArray function) to load a colormap to use first");
		Status.value = "PaintRange aborted";
		Command.value = "";
		return;
	}
	local numeric start;
	local numeric stop;
	local numeric colornumber;
	start = StrToNum(GetToken(Command.value,delim,2));
	stop = StrToNum(GetToken(Command.value,delim,3));
	colornumber = StrToNum(GetToken(Command.value,delim,4));
	if (Group.ActiveLayer.Type != "Raster") {
		PopupMessage("Active Layer must be a raster object for this function");
		Command.value = "";
		Status.value = "Active layer must be a raster";
		return;
		}
	DispGetRasterFromLayer(rast,Group.ActiveLayer);
	cmap = ColorMapFromRastVar(rast);
	if (cmap.name == "") {
		PopupMessage("No ColorMap was found in raster object Paint function aborted\n Use lc command to save a csv file as a colormap in the raster object first\n or create one yourself");
		Command.value = "";
		Status.value = "PaintRange function aborted";
		return;
		}
	Status.value = "Painting Range";
	for i = start to stop {
		#see Paint function for explanation of array indices
		mycolor.red = ared[colornumber+1];
		mycolor.green = agreen[colornumber+1];
		mycolor.blue = ablue[colornumber+1];
		mycolor.transp = atransp[colornumber+1];
		ColorMapSetColor(cmap,i,mycolor);
	}
	ColorMapWriteToRastVar(rast,cmap,cmap.Name,cmap.Desc);
	#force raster to reload colormap
	View.DisableRedraw = 1;
	LayerDestroy(Group.ActiveLayer);
	GroupQuickAddRasterVar(Group,rast);
	Group.ActiveLayer.AllowDeleteLayer = 1;
	View.DisableRedraw = 0;
	ViewRedraw(View);
	Status.value = "Cell Range Painted";
	Command.value = "";
}
proc LoadColorMap() {
	local string line;
	myfile = GetInputTextFile("c:/colormap.csv","Select ColorMap file","csv");
	line = fgetline$(myfile);
	#checks to see if the file we are loading is valid
	if ((NumberTokens(line,",") != 5) || ("Index" != GetToken(line, "," ,1))) {
		PopupMessage("This does not appear to be a valid colormap csv file\nThe proper format is one row of labels then 256 \nnumeric lines of the form red,green,blue,transp \nwhere red,green,blue,transp are in the range 0-100\nDisplay a raster with a colormap already and use the t command to export the colormap to a file to see how the file should look");
		Status.value = "Fatal Error ColorMap load halted";
		Command.value = "";
		return;
	}
	Status.value = "Loading Colormap";
	for i = 0 to 255 {
		line = fgetline$(myfile);
		#additional checks to see if the file we are loading is valid
		if ((i > 0) && (StrToNum(GetToken(line, ",",1)) == 0)) {
		PopupMessage("Bad Index Value Encountered while loading ColorMap file ColorMap load aborted");
		Status.value = "Fatal Error ColorMap load halted";
		Command.value = "";
		return;
		}
		mycolor.red = StrToNum(GetToken(line, "," ,2)); #first token is the index value
		mycolor.green = StrToNum(GetToken(line, "," ,3));
		mycolor.blue = StrToNum(GetToken(line, "," ,4));
		mycolor.transp = StrToNum(GetToken(line, "," ,5));
		ColorMapSetColor(cmap,i,mycolor);
	}
	if (Group.ActiveLayer.Type != "Raster") {
		PopupMessage("Active Layer must be a raster object for this function");
		Command.value = "";
		Status.value = "Active layer must be a raster";
		return;
		}
	DispGetRasterFromLayer(rast,Group.ActiveLayer);
	#writes to new colormap called SMLcolor
	#other functions assume a colormap is saved underneath the raster and manipulate the last used one
	ColorMapWriteToRastVar(rast,cmap,"SMLcolor","ColorMap created by SML script");
	#have raster layer reload now with colormap object
	View.DisableRedraw = 1;
	LayerDestroy(Group.ActiveLayer);
	GroupQuickAddRasterVar(Group,rast);
	Group.ActiveLayer.AllowDeleteLayer = 1;
	View.DisableRedraw = 0;
	ViewRedraw(View);
	Status.Value = "ColorMap saved as SMLcolor in raster object";
	PopupMessage("Colormap was saved as a SMLcolor colormap under raster object\nyou must select this colormap to see the changes\nif you were displaying the raster with a different colormap\nThis is the only function that behaves this way\nAll other function modify the most recently used colormap");
	Command.value = "";
}
proc SetColorArray() {
	local string line;
	#SML arrays indices start at 1
	myfile = GetInputTextFile("c:/colormap.csv","Select ColorMap file","csv");
	line = fgetline$(myfile);
	#check to see if the file format is valid
	if ((NumberTokens(line,",") != 5) || ("Index" != GetToken(line, "," ,1))) {
		PopupMessage("This does not appear to be a valid colormap csv file\nThe proper format is one row of labels then 256 \nnumeric lines of the form red,green,blue,transp \nwhere red,green,blue,transp are in the range 0-100\nDisplay a raster with a colormap already and use the t command to export the colormap to a file to see how the file should look");
		Status.value = "Fatal Error ColorMap load halted";
		Command.value = "";
		return;
	}
	#sml array indices start at 1 see Paint and PaintRange functions
	Status.value = "Reading Colormap";
	for i = 1 to 256 {
		line = fgetline$(myfile); 
		#additional checks to see if the file we are loading is valid
		if ((i > 1)&&(StrToNum(GetToken(line, ",",1)) == 0)) {
		PopupMessage("Bad Index Value Encountered while loading ColorMap file ColorMap load aborted");
		Status.value = "Fatal Error SetColorArray halted";
		Command.value = "";
		hascolorarray = 0;
		return;
		}
		ared[i] = StrToNum(GetToken(line, "," ,2)); #first token is the index value which we don't need
		agreen[i] = StrToNum(GetToken(line, "," ,3));
		ablue[i] = StrToNum(GetToken(line, "," ,4));
		atransp[i] = StrToNum(GetToken(line,  "," ,5));
	}
	#variable set so that Paint and PaintRange know that there is an actual colormap in the arrays
	hascolorarray = 1;
	Status.value = "Colormap read";
	Command.value = "";
}
proc ListColors() {
	if (!hascolorarray) {
		PopupMessage("Use code b (SetColorArray function) to load a colormap to use first");
		return;
	}
	string tree$;
	tree$ = "Interpret as [index] (red value, green value, blue value, transp value)\n\n";
	Status.value = "Reading Color Array";
	for i = 1 to 256 step 8 {
		tree$ = tree$ + "[" + NumToStr(i-1) + "]" + " (" + NumToStr(ared[i  ]) + "," + NumToStr(agreen[i  ]) + "," + NumToStr(ablue[i  ]) + "," + NumToStr(atransp[i  ]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i)   + "]" + " (" + NumToStr(ared[i+1]) + "," + NumToStr(agreen[i+1]) + "," + NumToStr(ablue[i+1]) + "," + NumToStr(atransp[i+1]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+1) + "]" + " (" + NumToStr(ared[i+2]) + "," + NumToStr(agreen[i+2]) + "," + NumToStr(ablue[i+2]) + "," + NumToStr(atransp[i+2]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+2) + "]" + " (" + NumToStr(ared[i+3]) + "," + NumToStr(agreen[i+3]) + "," + NumToStr(ablue[i+3]) + "," + NumToStr(atransp[i+3]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+3) + "]" + " (" + NumToStr(ared[i+4]) + "," + NumToStr(agreen[i+4]) + "," + NumToStr(ablue[i+4]) + "," + NumToStr(atransp[i+4]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+4) + "]" + " (" + NumToStr(ared[i+5]) + "," + NumToStr(agreen[i+5]) + "," + NumToStr(ablue[i+5]) + "," + NumToStr(atransp[i+5]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+5) + "]" + " (" + NumToStr(ared[i+6]) + "," + NumToStr(agreen[i+6]) + "," + NumToStr(ablue[i+6]) + "," + NumToStr(atransp[i+6]) + ") ";
		tree$ = tree$ + "[" + NumToStr(i+6) + "]" + " (" + NumToStr(ared[i+7]) + "," + NumToStr(agreen[i+7]) + "," + NumToStr(ablue[i+7]) + "," + NumToStr(atransp[i+7]) + ")\n";
	}
	Status.value = "Color Array being displayed";
	PopupMessage(tree$);
	Status.value = "Color Array message closed";
	Command.value = "";
	}
proc HelpFunction() {
	string message;
	string str1$, str2$, str3$, str4$, str5$, str6$, str7$, str75$, str77$, str8$, str9$, str10$, str11$;
	str1$ = "This is a list of functions, their purpose and command line syntax";
	str2$ = "FUNCTION NAME:    PURPOSE:                                                             COMMAND LINE SYNTAX:";
	str3$ = "OrderPizza        Simple Example Function                                              pizza,string,number";
	str4$ = "OutputColorMap    Output Active Layer's colormap in csv format                         t";
	str5$ = "TranspValues      Sets cellvalue range colormap entries transparent                    r,cellvaluestart,cellvaluestop";
	str6$ = "Paint             Sets cellvalue colormap entry to index array's color value           p,cellvalue,index   See SetColorArray";
	str7$ = "PaintRange        Sets cellvalue range colormap entries to index array's color value   pr,cellvaluestart,cellvaluestop,index";
	str75$ = "Paint and PaintRange functions assume a ColorMap exists in raster object and modifies the last one used";
	str77$ = "The functions do not modify your view parameters i.e. if you are display the raster with no colormap you are still displaying the raster with no colormap";
	str8$ = "LoadColorMap      Inputs a csv file and saves it as a colormap under the raster        lc";
	str9$ = "SetColorArray     Reads in a csv file and stores it a red,green,blue transp array      b     Used by Paint and PaintRange functions";
	str10$= "ListColors        Displays the values currently set in the color array                 l";
	str11$ ="HelpFunction      Displays this message                                                help    or click help button";
	# if you add new functions and want to document them add a strx$ variable like this
 #str12$ = "my new function   Does what my new function does                                       my new function's syntax";
	#then add a \n%s to this and add the new string variable at the end
	message = sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", str1$, str2$, str3$, str4$, str5$, str6$, str7$, str75$, str77$, str8$, str9$, str10$, str11$);
	Status.value = "Help Open";
	PopupMessage(message);
	Command.value = "";
	Status.value = "Help Closed";
}
proc ParseCommand() {
	string code;
	code = GetToken(Command.value,delim,1);
	numeric valid;
	valid = 0;
	#to add new functionality to this script add an if statement of this form
	#if (code == "the new code you want") {
	#then call your func or proc here or define the function here
	#set valid to 1 if you want the script to tell you if it didn't find a function for your code
	#}
	if (code == "pizza") {
 		OrderPizza();
		valid = 1;
	}
	if (code == "t") {
		OutputColorMap();
		valid = 1;
	}
	if (code == "r") {
		TranspValues();
		valid = 1;
	}
	if (code == "p") {
		Paint();
		valid = 1;
	}
	if (code == "pr") {
		PaintRange();
		valid = 1;
	}
	if (code == "lc") {
		LoadColorMap();
		valid = 1;
	}
	if (code == "b") {
		SetColorArray();
		valid = 1;
	}
	if (code == "help") {
		HelpFunction();
		valid = 1;
	}
	if (code == "l") {
		ListColors();
		valid = 1;
	}
	if (valid == 0) {
		Status.value = "";
		Status.value ="Command not recognized";
	}
}
#callback for [x] button on dialog
#switches to default tool which makes on OnDeactivate get called
proc DoClose() {
	if (setDefaultWhenClose) {
		setDefaultWhenClose = false;
		View.SetDefaultTool();
	}
}
 
# Called the first time the tool is activated. 
# If the tool implements a dialog it should be created (but not displayed) here. 
func OnInitialize () { 
	class XmForm dlgform;
	class PushButtonItem btnItemHelp;
	dlgform = CreateFormDialog("Command Parser",View.Form);
	WidgetAddCallback(dlgform.Shell.PopdownCallback,DoClose);
	Command = CreatePromptStr(dlgform,"Enter Command:",width,"Type help for help");
	Status = CreatePromptStr(dlgform,"Status:",width+13,"Waiting");
	btnItemHelp = CreatePushButtonItem("Click Here for Help",HelpFunction);
	btnItemHelp.IconName = "help";
	class XmRowColumn btnrowaction;
	btnrowaction = CreateIconButtonRow(dlgform,btnItemHelp);
	btnrowaction.TopWidget = dlgform;
	btnrowaction.RightWidget = Command;
	btnrowaction.LeftWidget = dlgform;
	btnrowaction.BottomWidget = Status;
	Command.TopWidget = dlgform;
	Command.RightWidget = dlgform;
	Status.LeftWidget = dlgform;
	Status.BottomWidget = dlgform;
	Status.TopWidget = Command;
	#setup so when value in the PromptString Command changes ParseCommand will be called
	WidgetAddCallback(Command.ValueChangedCallback,ParseCommand);
	#global variables
	numeric setDefaultWhenClose;
	numeric i;
	class RASTER rast;
	class ColorMap cmap;
	class Color mycolor;
	class FILE myfile;
	array ared[256];
	array agreen[256];
	array ablue[256];
	array atransp[256];
	numeric hascolorarray;
	hascolorarray = 0;
}  # end of OnInitialize 
 
# Called when tool is to be destroyed, will not be called if tool was never activated. 
# If the tool implements a dialog it should be destroyed here. 
func OnDestroy () { 
	DestroyWidget(dlgform);
}  # end of OnDestroy 
 
# Called when tool is activated. 
# If the tool implements a dialog it should be "managed" (displayed) here. 
func OnActivate () { 
	dlgform.managed = 1;
	setDefaultWhenClose = true;
}  # end of OnActivate 
 
# Called when tool is deactivated (usually when switching to another tool). 
# If the tool implements a dialog it should be "unmanaged" (hidden) here. 
func OnDeactivate () { 
	setDefaultWhenClose = false;
	dlgform.managed = 0;
}  # end of OnDeactivate 
 
# Called when tool is to be 'suspended' during a redraw operation. 
# func OnSuspend () { 
# }  # end of OnSuspend 
 
# Called when tool is to be 'resumed' after a redraw operation. 
# If the tool displays any graphics they should be updated by this function. 
# func OnResume () { 
# }  # end of OnResume 
 
# Called when user presses 'left' pointer/mouse button. 
# func OnLeftButtonPress () { 
# }  # end of OnLeftButtonPress 
 
# Called when user presses 'right' pointer/mouse button. 
# func OnRightButtonPress () { 
# }  # end of OnRightButtonPress 
 
# Called when user presses 'middle' pointer/mouse button. 
# func OnMiddleButtonPress () { 
# }  # end of OnMiddleButtonPress 
 
# Called when user releases 'left' pointer/mouse button. 
# func OnLeftButtonRelease () { 
# }  # end of OnLeftButtonRelease 
 
# Called when user releases 'right' pointer/mouse button. 
# func OnRightButtonRelease () { 
# }  # end of OnRightButtonRelease 
 
# Called when user releases 'middle' pointer/mouse button. 
# func OnMiddleButtonRelease () { 
# }  # end of OnMiddleButtonRelease 
 
# Called when user moves cursor if no button being pressed 
# func OnPointerMoveNoButton () { 
# }  # end of OnPointerMoveNoButton 
 
# Called when user moves cursor while holding down button 
# func OnPointerMoveWithButton () { 
# }  # end of OnPointerMoveWithButton 
 
# Called when cursor enters window associated with view. 
# func OnEnterWindow () { 
# }  # end of OnEnterWindow 
 
# Called when cursor leaves window associated with view. 
# func OnLeaveWindow () { 
# }  # end of OnLeaveWindow 
 
# Called when user presses 'key' on keyboard. 
#func OnKeyPress (key) { 
#}  # end of OnKeyPress