Skip navigation

OpenVista CIS

3 Posts tagged with the cis tag
0

One of the features of OpenVista CIS is that it is extensible. Without modifying the core of CIS, you can drop in additional functionality, such as new application tabs, new image format rendering support, new preferences tabs, etc.

 

In order to make OpenVista CIS extensible, it uses Mono.Addins for a plugin system. This allows developers to dynamically add more functionality to CIS without having to change its internals. Mono.Addins allows developers to specify "extension points" and then inspect and load all extensions that attach to that extension point. Here is a simple example showing one of the CIS extension points, and a simple extension that implements it.

The Extension Point

Let's look at one of the core UI extension points in CIS, the IApplicationTab. This extension point is used to provide tabs visible in the main window of CIS. Here is the relevant code from the definition of that extension point interface:

using Gtk;

[Mono.Addins.TypeExtensionPoint ("/Interface/ApplicationTab")]
public interface IApplicationTab
{
     Widget LabelWidget {
         get;
     }
     Widget Widget {
          get;
     }
     .
     .
     .
}

 

This extension node is found in the Medsphere.OpenVista.Core.UI.dll assembly, and must define an "AddinRoot" in order to let this extension point be used. The following is from the AssemblyInfo.cs file in that assembly:

using Mono.Addins;

[assembly:AddinRoot ("Medsphere.OpenVista.Core.UI", "1.0")]

A Simple Extension

 

We are going to create a new assembly that contains our application tab extension. We need to specify both our addins dependencies, as well as advertise it the addin itself, in the AssemblyInfo.cs file:

using Mono.Addins;

[assembly: Addin]
[assembly: AddinDependency ("Medsphere.OpenVista.Core.UI", "1.0")]

 

Next we will define our simple hello world extension in HelloWorldSheet.cs:

using System;
using Gtk;
using Medsphere.OpenVista.Core.UI;

[Mono.Addins.Extension ("/Interface/ApplicationTab")]
public class HelloWorldSheet : IApplicationTab
{
        public Widget LabelWidget {
                 get { return _label; }
        }

        public Widget Widget {
                 get { return _widget; }
        }
        .
        .
        .
        public HelloWorldSheet ()
        {
                 _label = new Label ("Hello\nWorld");
                 _widget = new Label ("Hello World!");
        }

        Label _label, _widget;
}

We can now compile our addin with the following command line (of course, this could just as easily be done in Visual Studio, MonoDevelop, etc):

gmcs -r:Mono.Addins.dll -r:Medsphere.OpenVista.Core.UI.dll -pkg:gtk-sharp-2.0 \
     -t:library -out:Medsphere.OpenVista.CIS.Demo.dll HelloWorldSheet.cs AssemblyInfo.cs

 

Now when we run CIS, we see that our hello world application tab has been automatically loaded:

 

openvista-cis-hello-world-plugin.png

 

Conclussion

 

For further reading on Mono.Addins, check out the Mono.Addins page on http://www.mono-project.com/. If you want to get started on extending CIS, grab the CIS source code! The full source code for the simple CIS tab plugin is attached to this document, so you can see the full details.

676 Views 0 Comments 0 References Permalink Tags: c#, cis, mono_addins, openvista_cis_internals, openvista_cis, open_source
0

P/Invoke, short term for Platform Invoke, is the mechanism provided by the .NET framework to invoke unmanaged code (methods or functions from libraries written in C or C++ programming languages) from managed code. As an example let's look at some code from the OpenVistaCIS code base.

 

Let's look at the code that brings spelling support. If you have CIS's source code available go ahead and read the file src/Medsphere.OpenVista.Spelling/AspellSpeller.cs. The basic P/Invoke suport is based on the use of the DllImport attribute. What the DllImport attribute does is to provide the information needed to call a function from unmanaged code, which is described by the method's signature (which involves the name, return type and parameters types).

 

In order to create an Aspell dictionary on OpenVistaCIS we have two external libraries definitions that take care of what's the platform we are running on, either GNU/Linux or MS Windows

[DllImport ("aspell-15.dll", EntryPoint="new_aspell_speller")]
private static extern IntPtr new_aspell_speller_win32 (IntPtr config);
 
[DllImport ("libaspell")]
private static extern IntPtr new_aspell_speller (IntPtr config);

 

The first parameter for the DllImport attribute is the library name, that for the Win32 version is aspell-15.dll but for the Linux version is libaspell, we have to define two external method declarations due to that fact, then for the Win32's signature comes a named argument called EntryPoint that let us map the declaration to the original name of the method in the unmanaged library, so in that case we map new_aspell_speller_win32 to new_aspell_speller. Another important thing that we must highlight is the use of the extern method's modifier to "mark" the method as being implemented externally (that allow us to just use semi-colon as the method's body. And finally, we must highlight the use of the IntPtr type to represent a pointer or handle that's coming back from the unmanaged library.

 

Now, the way we use them inside the managed code is as follows:

public AspellSpeller (AspellConfig config)
{
    if (IsWindows) {
        error = new AspellCanHaveError (new_aspell_speller_win32 (config.Handle));
    } else {
        error = new AspellCanHaveError (new_aspell_speller (config.Handle));
    }
    .
    .
    .
}

 

Where the IsWindows property is defined as:

private static bool IsWindows {
    get { return ((int)Environment.OSVersion.Platform <= 3); }
}

 


The types used in an external method declaration can go from very simple Int32, String or more complicated types that need explicit marshalling. One very detailed article about is the one found in the Mono project's Interop with Native Libraries. Check it out for more details about P/Invoke.

654 Views 0 Comments Permalink Tags: cis, linux, openvista_cis, openvista_cis_internals
0

Medsphere's open source release of OpenVista CIS allows you to download, examine, build, run, and modify the application. One of the easiest ways to manipulate the codebase is to use an integrated development environment (IDE). On Linux, the MonoDevelop project offers a fully functional open source IDE. You should be able to install MonoDevelop using your GNU/Linux distribution's package manager.

 

 

 

Next, you'll need to download the OpenVista CIS code. All of Medsphere's open source code is available from sourceforge.net. The list of available code archives can be found here. Although archives of specific subsections of the the codebase are offered, as well as a few different formats, this tutorial describes using the .zip file containing the entire codebase. You can download the current version (0.9.9) by clicking here.

 

 

 

Now, you'll extract the source tree from the file you've downloaded. There are a few ways to do this. From the command line, we can cd into the directory that contains the .zip file and run the following command:

 

 

 

$ unzip openvistacis-0.9.9.zip

 

 

 

This will create a directory called openvistacis-0.9.9 that contains the source code and configuration information of the project. You may also be able to extract the file using your desktop environment. For example, in the GNOME desktop, you can right click on the file and select ""Extract Here" from the context menu as shown:

 

 

 

MonoDevelop0.png

 

 

 

Extracting the archive creates a new directory. In the top level of this new directory you will find a file named OpenVista.mds. This is the MonoDevelop solution file. You can open this file in a few ways. You can invoke MonoDevelop from the command line:

 

 

 

$ monodevelop OpenVista.mds

 

 

 

Depending on your desktop environment, you may also be able to double click the OpenVista.mds file to start MonoDevelop. Finally, you can open the file from within MonoDevelop by choosing "Open..." from MonoDevelop's "File" menu, or by clicking "Open a Solution / File" from the MonoDevelop welcome screen.

 

 

 

MonoDevelop1.png

 

 

 

Once you've opened the solution file, you'll see the list of assemblies that comprise the OpenVista CIS codebase.

 

 

 

MonoDevelop2.png

 

 

 

There are three executables contained within the OpenVista CIS project source tree.

 

  1. OpenVista CIS, the main client GUI.

  2. OpenVista Vitals, the vital signs functionality from CIS, deployable as a standalone application.

  3. Bridge, a middleware layer that handles RPC communication with the VistA Broker and provides a Binary Remoting interface to the client.

 

The most straightforward method of running OpenVista CIS is to connect to the Bridge running on the OpenVista Public Demo server. To do this, you won't need to run your own Bridge locally, or the OpenVista Vitals app. To prevent MonoDevelop from starting these applications, right click on the first/top row of the Solution list and select "Options" from the context menu.

 

 

 

MonoDevelop3.png

 

 

 

From the list on the left of the "Solution Options" dialog, select "Startup Properties". You'll notice that the "Multiple Startup Project" radio button is active. Since you only want to start OpenVista CIS, activate the "Single Startup Project" radio button and choose "OpenVistaCIS" from the menu underneath. Click "OK" when you are finished.

 

 

 

NOTE: Due to a minor bug in MonoDevelop 1.0, when you select "Startup Properties", the correct user interface may not appear. Instead, you may see the text "label5". In this case, select any of the other option categories in the list ("Solution Information" for example, and then reselect "Startup Properties".

 

 

 

MonoDevelop4.png

 

 

 

 

 

Now we are ready to build and run OpenVista CIS from within MonoDevelop. To do this, choose "Run" from MonoDevelop's "Project" menu. You can also use the keyboard shortcut to invoke this action by pressing the F5 key. Since OpenVista CIS is a rather large program and you must build the entire tree at this time, this step may take some time. Subsequent builds only need to rebuild modified sections of the codebase, and will likely be much faster. When the build process finishes, you'll notice that two windows appear on your screen.

 

 

 

  1. An empty terminal window titled "MonoDevelop External Console". Any output from OpenVista CIS that is sent to stdout or stderr will appear in this window. It can be a useful tool to diagnose and fix errors in the program, and to allow you to see the output of print statements you've inserted into the code.

  2. The OpenVista CIS login dialog, entitled "Connect to Medsphere OpenVista Server". Note that for security purposes this window and the application will close after a period of inactivity.

 

 

 

To login to the OpenVista Public Demo Server as a physician user, enter "PU1234" into the Login ID entry, "PU1234! In future posts, we'll discuss how to make changes to the codebase using MonoDevelop.

1,158 Views 0 Comments 0 References Permalink Tags: cis, mono, monodevelop, linux, openvista_cis, tutorial, walkthrough