.NET/Link Example: PackageHelper

This example demonstrates creating and running a "modal" dialog box. It shows:
	- a modal dialog using the DoNETModal function
	- returning a result from a modal dialog
	- the use of AddEventHandler to wiire up some simple Mathematica functions for event callbacks

The program displays a dialog box showing a list of all the standard add-on packages that ship with Mathematica. The ones that are currently loaded are shown with a check mark. You can select additional packages by clicking them so that they have a check mark as well. The packages you selected are loaded if you click the Load button to dismiss the dialog. If you click Cancel, nothing happens. The function returns the current value of $Packages, unless it was cancelled, in which case it reutrns Null.

To try this example, evaluate all the initialization cells (you can do this with the menu command Kernel/Evaluation/Evaluate Initialization). Then go to the Example section.

Code

Needs["NETLink`"];
Needs["Utilities`Package`"];

PackageHelper[] :=
	NETBlock[
		Module[{packages, form, listBox, loadButton, cancelButton, getCheckedItems, selectedContexts},
		
			(* This gets the list of all contexts for the standard add-on packages. *)
			packages = FindPackages[ToFileName[{$TopDirectory, "AddOns", "StandardPackages"}]];
			
			InstallNET[];
			
			(* Load some classes from which we need to call static members. *)
			LoadNETType["System.Windows.Forms.DialogResult"];
			LoadNETType["System.Windows.Forms.FormStartPosition"];
			LoadNETType["System.Windows.Forms.FormBorderStyle"];
			
			(* Create the main form and populate it with components. *)
			form = NETNew["System.Windows.Forms.Form"];
			form@Text = "Standard Packages";
			form@Width = 300;
			form@Height = 500;
			form@StartPosition = FormStartPosition`CenterScreen;
			form@FormBorderStyle = FormBorderStyle`FixedDialog;
			form@MaximizeBox = False;
			listBox = NETNew["System.Windows.Forms.CheckedListBox"];
			listBox@Parent = form;
			listBox@Bounds = NETNew["System.Drawing.Rectangle", 6, 10, 280, 420];
			listBox@CheckOnClick = True;
			loadButton = NETNew["System.Windows.Forms.Button"];
			cancelButton = NETNew["System.Windows.Forms.Button"];
			loadButton@Parent = form;
			cancelButton@Parent = form;
			loadButton@Text = "Load";
			cancelButton@Text = "Cancel";
			
			(* These lines populate the list box with the package contexts and set their checked/unchecked state. *)
			listBox@Items@AddRange[packages];
			MapIndexed[listBox@SetItemChecked[First[#2]-1, MemberQ[$Packages, #1]]&, packages];

			(* Setting the DialogResult property of these buttons causes them to set the parent form's
			   DialogResult property to these values when they are clicked. When the dialog closes we
			   can inspect the form's DialogResult property to determine which button was clicked to
			   close the dialog.
			*)
			loadButton@DialogResult = DialogResult`OK;
			cancelButton@DialogResult = DialogResult`Cancel;
			loadButton@Location = NETNew["System.Drawing.Point", 20, listBox@Bottom + 6];
			cancelButton@Location = NETNew["System.Drawing.Point", 195, listBox@Bottom + 6];
			
			(* Setting these properties cause the buttons to respond to the Return and Esc key, respectively. *)
			form@AcceptButton = loadButton;
			form@CancelButton = cancelButton;
		
			(* We still need to wire up handlers to cause the dialog to close when the buttons are clicked.
			   That would happen automatically if we were to use the ShowDialog() method to run the modal
			   dialog, which is the standard .NET technique for modal dialogs. We don't use ShowDialog()
			   because it is not guaranteed to make the dialog visible in front of the notebook window.
			*)
			AddEventHandler[loadButton@Click, form@Close[]&];
			AddEventHandler[cancelButton@Click, form@Close[]&];
			
			(* This is the function called when the dialog box is closed to get the list of checked contexts.
			   It checks the form's DialogResult property to determine whether the form was closed by
			   clicking the Load (equivalent to OK) or Cancel button.
			*)
			getCheckedItems[f_] := If[f@DialogResult === DialogResult`OK, listBox@CheckedItems, Null];
			
			(* Run the dialog modally. The second argument to DoNETModal is code that will be called
			   just before the form is destroyed, and what it returns will be the return value of DoNETModal.
			   DoNETModal will not return until the dialog is dismissed.
			*)
			selectedContexts = DoNETModal[form, getCheckedItems[form]];
			
			If[selectedContexts =!= Null,
				(* selectedContexts is the object returned by the CheckedItems property of the list box
				   (see the getCheckedItems function defined above). This is an object that implements
				   the ICollection interface. The NETObjectToExpression converts all ICollection
				   objects to Mathematica lists.
				*)
				Needs /@ NETObjectToExpression[selectedContexts];
				$Packages,
			(* else *)
				Null
			]
		]
	]

Example

PackageHelper[]