Advanced Techniques

Click the following links to access techniques described in this topic.

Use the Visual Studio debugger

To set breakpoints and debug your plugin, set the Ansys Orbit Determination Tool Kit (ODTK) application as the startup executable.

  1. In the Solution Explorer, right-click the plugin Project and select Properties.
  2. On the Debug tab, select the Start External Program radio button and go to <Install_Dir>\bin\AgUiApplication.exe.
  3. In Command line arguments, enter: /pers ODTK.

Use the ODTK progress bar

For potentially long computations or tasks, the ODTK application displays a progress indicator in the Status bar at the very bottom of the application window. You can utilize that progress bar in your UI Plugin for the same purpose. This gives you access to the percentage progress indicator, as well as an updatable text field in the status bar. The progress indicator is ideally suited for repeated tasks occurring in a loop, where the progress indicator can be updated on each iteration.

When it calls IAgUiPluginCommandTarget.Exec, the application passes an IAgProgressTrackCancel object. An IAgProgressTrackCancel object is also returned by IAgUiPluginSite.GetProgressTracker.

To use the progress indicator for a given block of code, call BeginTracking at the start and EndTracking at the end. In between, you will need to update the progress, using the SetProgress function. In the example below , the "task" is simply a counter from 1 to 100.

[C#]
public class UiPluginExample: IAgUiPlugin, IAgUiPluginCommandTarget
{
    ...
    
    private IAgUiPluginSite m_psite;
    private IAgProgressTrackCancel m_progressBar;
    
    public void OnStartup(IAgUiPluginSite PluginSite)
    {
        m_psite = PluginSite;
        m_progressBar = m_psite.GetProgressTracker();
        ...
    }
   
    private void TestProgressBar()
    {
        m_progressBar.BeginTracking(AgEProgressTrackingOptions.eProgressTrackingOptionNone, AgEProgressTrackingType.eTrackAsProgressBar);
        for (int i = 0; i <= 100; i++)
        {
            m_progressBar.SetProgress(i, string.Format("Progress is at {0}...", i));
            System.Threading.Thread.Sleep(100);
            if (!m_progressBar.Continue)
                break;
        }
        m_progressBar.EndTracking(); 
    }
}
[Visual Basic .NET]
Public Class VBDana
    Implements IAgUiPlugin, IAgUiPluginCommandTarget, IAgUiPlugin2

    ...
    
    Dim m_pSite As IAgUiPluginSite
    Dim m_progressBar As IAgProgressTrackCancel

    Public Sub OnStartup(PluginSite As IAgUiPluginSite) Implements AGI.Ui.Plugins.IAgUiPlugin.OnStartup
        m_pSite = PluginSite
        m_progressBar = m_pSite.GetProgressTracker()
        ...

    End Sub
    Private Sub TestProgressBar()
        m_progressBar.BeginTracking(AgEProgressTrackingOptions.eProgressTrackingOptionNone, AgEProgressTrackingType.eTrackAsProgressBar)
        For i As Integer = 0 To 100
            m_progressBar.SetProgress(i, String.Format("Progress is at {0}...", i))
            System.Threading.Thread.Sleep(100)
            If Not m_progressBar.Continue Then
                Exit For
            End If
        Next
        m_progressBar.EndTracking()
    End Sub
End Class

Use the ODTK Message Viewer

The ODTK application uses the Message Viewer to provide certain kinds of feedback to the user without the interruption of a dialog box. The IAgUiPluginSite interface provides a LogMessage method for this purpose. The message type controls the icon associated with the message, and you can sort or filter messages by type.

[C#]
m_psite.LogMessage(AgEUiPluginLogMsgType.eUiPluginLogMsgInfo, "MyPluginName: This message is for your information");
m_psite.LogMessage(AgEUiPluginLogMsgType.eUiPluginLogMsgAlarm, "MyPluginName: There is an error. Something is wrong!");
[Visual Basic .NET]
m_psite.LogMessage(AgEUiPluginLogMsgType.eUiPluginLogMsgInfo, "MyPluginName: This message is for your information")
m_psite.LogMessage(AgEUiPluginLogMsgType.eUiPluginLogMsgAlarm, "MyPluginName: There is an error. Something is wrong!")

Use toolbar or menu icons

It is possible to associate an icon with a toolbar button or menu item, rather than text only. The following procedure demonstrates the use of an icon (.ico) file or image (.bmp, .gif, .jpg, .png or .tif) file.

Add icon or image file to the project

For C#:
  1. In the Solution Explorer, right-click the project and select Add and then Existing Item.
  2. Browse to the icon or image file of your choice and click Add.
  3. In the Solution Explorer, select the new icon or image file. Under Properties, set Build Action to Embedded Resource.
For VB:
  1. Open the Resources.resx file.
  2. Under Add Resource, select Add Existing File... and browse to your file.
  3. In the Solution Explorer, select the new icon or image file. Under Properties, set Build Action to Embedded Resource.

Add references

Add a reference to the Microsoft.VisualBasic.Compatibility and System.Drawing namespaces.

  1. Right-click References in the Solution Explorer and select Add Reference...
  2. From the .NET tab, select Microsoft.VisualBasic.Compatibility and System.Drawing.
  3. Add the System.Drawing and System.Reflection namespaces to the plugin class:
    [C#]
    using System.Drawing;
    using System.Reflection;
    
    [Visual Basic .NET]
    Imports System.Drawing
    Imports System.Reflection
    

Convert icon or image

The file must be read in as an Icon or Image object and then converted to an OLE IPictureDisp object. In C#, the file is identified in the resource stream by a string of the format <Plugin Namespace>.<File Name>.<File Extension>. In VB, the file is identified in the resource collection by a reference to My.Resources.<FileName>.

[C#]
// Example 1
// Use MenuIcon.ico as the menu item icon
public void OnDisplayContextMenu(IAgUiPluginMenuBuilder MenuBuilder)
{
    Assembly currentAssembly = Assembly.GetExecutingAssembly();
    Icon menuIcon = new Icon(currentAssembly.GetManifestResourceStream("MySampleUIPlugin.MenuIcon.ico"));
    stdole.IPictureDisp menuPicture = Microsoft.VisualBasic.Compatibility.VB6.Support.IconToIPicture(menuIcon) as stdole.IPictureDisp;
    MenuBuilder.AddMenuItem("MyCompany.MyPluginName.MySecondCommand", "Example Menu Item 1", "with an icon", menuPicture);
}

// Example 2
// Use ToolbarButton.jpg as the toolbar icon
public void OnInitializeToolbar(IAgUiPluginToolbarBuilder ToolbarBuilder)
{
    Assembly currentAssembly = Assembly.GetExecutingAssembly();
    Image tlbrImage = Image.FromStream(currentAssembly.GetManifestResourceStream("MySampleUIPlugin.ToolbarButton.jpg"));
    stdole.IPictureDisp tlbrPicture = Microsoft.VisualBasic.Compatibility.VB6.Support.ImageToIPictureDisp(tlbrImage) as stdole.IPictureDisp;
            
    ToolbarBuilder.AddButton("MyCompany.MyPluginName.MyFirstCommand", "Example Button 1", "with an image", AgEToolBarButtonOptions.eToolBarButtonOptionAlwaysOn, tlbrPicture);
}
[Visual Basic .NET]
' Example 1
' Use MenuIcon.ico as the menu item icon
Public Sub OnDisplayContextMenu(MenuBuilder As AGI.Ui.Plugins.IAgUiPluginMenuBuilder) Implements AGI.Ui.Plugins.IAgUiPlugin.OnDisplayContextMenu

    Dim menuPicture As stdole.IPictureDisp = Microsoft.VisualBasic.Compatibility.VB6.Support.IconToIPicture(My.Resources.MenuIcon)
    MenuBuilder.AddMenuItem("MyCompany.MyPluginName.MySecondCommand", "Example Menu Item 1", "with an icon", menuPicture)

End Sub


' Example 2
' Use ToolbarButton.jpg as the toolbar icon
Public Sub OnInitializeToolbar(ToolbarBuilder As AGI.Ui.Plugins.IAgUiPluginToolbarBuilder) Implements AGI.Ui.Plugins.IAgUiPlugin.OnInitializeToolbar

    Dim tlbrPicture As stdole.IPictureDisp = Microsoft.VisualBasic.Compatibility.VB6.Support.ImageToIPictureDisp(My.Resources.ToolbarButton)
    ToolbarBuilder.AddButton("MyCompany.MyPluginName.MyFirstCommand", "Example Button 1", "with an image", AgEToolBarButtonOptions.eToolBarButtonOptionNone, tlbrPicture)

End Sub

Make context menus context sensitive

The context menu items in your plugin may only be appropriate for certain classes of objects, such as satellite or filter. The IAgUiPluginSite.Selection property returns a collection of the objects currently selected in the object browser. The IAgUiPluginSelectedObject contains the full path of the object, which you can either parse to determine the object class. The example shown below parses the path to the object and accesses its ClassName property.

[C#]
public void OnDisplayContextMenu(IAgUiPluginMenuBuilder MenuBuilder)
	{
    	bool isValidType = true;
    	List<string> supportedObjectClasses = new List<string>(new string[] { "SATELLITE", "FILTER" });
       <string> odobjectFullPath;

       IAgUiPluginSelectedObjectCollection selectedobjects = m_psite.Selection;
            
       foreach (IAgUiPluginSelectedObject selectedobject in selectedobjects)
        {

           odobjectFullPath = selectedobject.Path; // Example path: ODTK.ExampleScenario.Satellite.Satellite1
           <string> shortenedPath = odobjectFullPath.Substring(5); // Parse out "ODTK." so the path is navigable
           dynamic objectReference = m_root(shortenedPath); // Use the remaining object path to get a reference to the object

           <string> classname = objectReference.ClassName.Value;

           if (!supportedObjectClasses.Contains(classname.ToUpperInvariant()))
           {

               isValidType = false;
           }
        }

    if (isValidType)
       {
           MenuBuilder.AddMenuItem("MyCompany.MyPluginName.SatelliteOrFilterCommand", "Example Context-sensitive Menu Item", "Sample Menu Item", null);
       }
   }
[Visual Basic .NET]
Public Sub OnDisplayContextMenu(MenuBuilder As AGI.Ui.Plugins.IAgUiPluginMenuBuilder) Implements AGI.Ui.Plugins.IAgUiPlugin.OnDisplayContextMenu

    Dim isValidType As Boolean = True
    Dim supportedObjectClasses As New List(Of String)(New String() {"SATELLITE", "FILTER"})
    Dim odobjectFullPath

    Dim selectedobjects As IAgUiPluginSelectedObjectCollection = m_pSite.Selection
    For Each selectedobject As IAgUiPluginSelectedObject In selectedobjects
         odobjectFullPath = selectedobject.Path
           Dim shortenedPath = odobjectFullPath.Substring(5)
           Dim objectReference = m_root(shortenedPath)

           Dim classname = objectReference.ClassName
        If Not (supportedObjectClasses.Contains(classname.ToUpper()) Then
            isValidType = False
        End If
    Next

    If (isValidType) Then
        MenuBuilder.AddMenuItem("MyCompany.MyPluginName.MySatelliteOrFilterCommand",
                                "Example Context-sensitive Menu Item",
                                "Sample Menu Item", Nothing)
    End If
End Sub

Create a submenu

For a plugin that will have several menu items, you may wish to group those menu items into a submenu. The following example adds a standard context menu item and then a submenu containing three menu items.

[C#]
public void OnDisplayContextMenu(IAgUiPluginMenuBuilder MenuBuilder)
{
    MenuBuilder.AddMenuItem("MyCompany.MyPluginName.MenuItemCommand1", "Some Plugin Function", "Sample Menu Item", null);
    IAgUiPluginMenuBuilder SubMenuBuilder = MenuBuilder.AddPopupMenu("Export Results");
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand1", "Export Image", "Sample SubMenu Item", null);
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand2", "Export VDF", "Sample SubMenu Item", null);
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand3", "Export CSV", "Sample SubMenu Item", null);
}
[Visual Basic .NET]
Public Sub OnDisplayContextMenu(MenuBuilder As AGI.Ui.Plugins.IAgUiPluginMenuBuilder) Implements AGI.Ui.Plugins.IAgUiPlugin.OnDisplayContextMenu
    MenuBuilder.AddMenuItem("MyCompany.MyPluginName.MenuItemCommand1", "Some Plugin Function", "Sample Menu Item", Nothing)
    Dim SubMenuBuilder As IAgUiPluginMenuBuilder = MenuBuilder.AddPopupMenu("Export Results")
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand1", "Export Image", "Sample SubMenu Item", Nothing)
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand2", "Export VDF", "Sample SubMenu Item", Nothing)
    SubMenuBuilder.AddMenuItem("MyCompany.MyPluginName.SubMenuItemCommand3", "Export CSV", "Sample SubMenu Item", Nothing)
    
End Sub

Insert menu items in other locations

The standard location for plugin menu items is in the <Object Class> Plugins submenu of an object shortcut menu, as described in the topic Add a context menu item. Menu items may also be added directly to an object shortcut menu or to the ODTK application menus (File, Edit, View, etc.).

Adding these higher-level menu items is similar in operation to the standard context menu item, with one key distinction: the OnDisplayContextMenu method is a member of the IAgUiPlugin interface, but the OnDisplayMenu method that adds higher-level menu items is a member of the IAgUiPlugin2 interface.

Furthermore, you can "add" or "insert" a higher-level menu item. Using "add" will place a new menu item at the bottom of the menu. Using "insert" will place a new menu item above an existing item (indexed beginning at 0 and including separators). Take care when inserting menu items, as the number of existing items in a menu will vary by menu and ODTK object type.

  1. Locate the UI Plugin class definition. Append the IAgUiPlugin2 interface to the class definition:
    [C#]
    public class UiPluginExample: IAgUiPlugin, IAgUiPluginCommandTarget, IAgUiPlugin2
    
    [Visual Basic .NET]
    Public Class MySampleUIPlugin
        Implements IAgUiPlugin, IAgUiPluginCommandTarget, IAgUiPlugin2
    
  2. For C#, right-click the interface (IAgUiPlugin2). Select Implement Interface and then Implement Interface again. For VB, at the end of the Implements line, press the Enter key.

    This will implement the IAgUiPlugin2 interface, exposing its members. IAgUiPlugin2 has only one public method, OnDisplayMenu.

  3. Modify the OnDisplyMenu handler to your requirements. The OnDisplayMenu handler passes a menu title and a menu type, used in these examples to add the menu items to ONLY the desired menu(s).
    [C#]
    public void OnDisplayMenu(string MenuTitle, AgEUiPluginMenuBarKind MenuBarKind, IAgUiPluginMenuBuilder2 MenuBuilder)
    {
        // Example 1
        // Add a menu item to the bottom of any ODTK Object shortcut menu
        if (MenuBarKind.Equals(AgEUiPluginMenuBarKind.eUiPluginMenuBarContextMenu))
        {
            MenuBuilder.AddMenuItem("MyCompany.MyPluginName.ObjectMenuCommand", "ODTK Object Menu Item", "Sample menu item", null);
        }
                
        // Example 2
        // Insert a menu item into the application View menu, above the 4th item (index 3),
        // then add a separator above the new item
        else if (MenuBarKind.Equals(AgEUiPluginMenuBarKind.eUiPluginMenuBarPopupMenu))
        {
            if (MenuTitle.Contains("View"))
            {
                MenuBuilder.InsertMenuItem(3, "MyCompany.MyPluginName.ApplicationMenuCommand", "View Menu Item", "Sample menu item", null);
                MenuBuilder.InsertSeparator(3);
            }
        }
    }
    
    [Visual Basic .NET]
    Public Sub OnDisplayMenu(MenuTitle As String, MenuBarKind As AGI.Ui.Plugins.AgEUiPluginMenuBarKind, MenuBuilder As AGI.Ui.Plugins.IAgUiPluginMenuBuilder2) Implements AGI.Ui.Plugins.IAgUiPlugin2.OnDisplayMenu
    
        ' Example 1
        ' Add a menu item to the bottom af any ODTK Object shortcut menu.
        If MenuBarKind.Equals(AgEUiPluginMenuBarKind.eUiPluginMenuBarContextMenu) Then
            MenuBuilder.AddMenuItem("MyCompany.MyPluginName.ObjectMenuCommand", "ODTK Object Menu Item", "Sample menu item", Nothing)
    
        ' Example 2
        ' Insert a menu item into the application View menu, above the 4th item (index 3) and
        ' then add a separator above the new item.
        ElseIf MenuBarKind.Equals(AgEUiPluginMenuBarKind.eUiPluginMenuBarPopupMenu) Then
            If MenuTitle.Contains("View") Then
                MenuBuilder.InsertMenuItem(3, "MyCompany.MyPluginName.ApplicationMenuCommand", "View Menu Item", "Sample menu item", Nothing)
                MenuBuilder.InsertSeparator(3)
            End If
        End If
    End Sub
    

To control the function and state of these new commands, populate the IAgUiPluginCommandTarget.Exec and IAgUiPluginCommandTarget.QueryState methods, as you would for any other command. See also Implement the Command Target Interface.

Related Topics: