With the introduction of native class support in JSL, advanced users now have powerful tools to bring object-oriented design principles into their scripting workflows. Although JSL's class implementation is still evolving, the core functionality delivers significant advantages, opening new doors for building modular, scalable, and reusable applications.
This presentation focuses on using JSL classes to build dynamic, interactive GUIs in JMP. We explore practical design patterns for managing state, abstracting behavior, and reusing GUI logic across contexts. Topics also include nested class structures for window composition, leveraging replication to generate dynamic and scalable designs, and tips on how to think modularly to write highly reusable code.
Attendees should gain insight into building more maintainable and extensible JMP applications using a structured, object-oriented approach. If you've ever wished for a cleaner way to manage large GUI designs in JSL, this session offers both the conceptual patterns and hands-on examples to make it a reality.

Hi there. Thank you all for viewing this presentation. I'm going to be talking about some JMP classes and how you can work with them in JSL to implement some dynamic and extensible interface behaviors.
My name is Ben Barrett, I work for IDEXX Laboratories. I've been an engineer there for about 10 years now. I've worked with various applications, LabVIEW, MATLAB, I played around with C#. Generally in all of those languages, I've always gravitated towards using an object-oriented programming style.
For some reason that just feels intuitive to me. However, when I started working with objects in JSL, I found that those intuitions did not serve me very well. There were a few nuances that I had to overcome, but once I figured out how to use them, I found them to be very useful.
I'm going to start off by just giving a quick overview. I'm not going to give an in-depth lesson on JMP classes here. I just want to go through my discovery process as I began to work with them. Some of the things that I found were difficult, headaches that I encountered and how I overcame them, and some cool examples at the end of how I've used them.
Here's a rough agenda, we'll see how well I stick to it. I want to talk a little bit about scoping because I found that that has been a persistent issue when it comes to the way that I have implemented some of the classes, and that will lead to some of my best practices that I've found. I also want to talk about how classes in JSL are a little bit different than what you might expect from other languages like C#. Then I'm going to get into some functional demo code.
Don't expect a deep, thorough lesson on classes in JSL here, or even object-oriented design principles in general. Hopefully, this will help you avoid some headaches if you decide to dig into classes yourself.
Here's the agenda, went through all of that. Here's a quick overview of the different scopes that are available in JSL. I won't pretend to fully understand how all of these interact and how you can use all of these. I have some basic ideas on it.
There are four general scopes. There's a local scope here, global, and then your own custom namespaces. I've outlined how you can interact with each of these scopes in this document. I definitely recommend viewing the documentation online if you want to get more information. But in general, what I found is when you're trying to work with classes, my best approach that I found is to work with namespaces.
Create your own custom namespaces if you need to be referencing them in classes, and that has helped me avoid a lot of the scopes and conflict issues that have arisen. I've also found that the Here namespace is not particularly reliable when it comes to classes, so I try to avoid using names default to Here and setting that to one. Additionally, using local variables can be helpful as well, as long as you avoid the local Here command. But this is a little bit more maintenance because you have to explicitly define which variables you want to be local. But some of this will be more clear as we get into some of the demos.
I just went over what those best practices were. Avoid names default to here, use custom namespaces, and then classes as well. You can think of classes in some way as a namespace that can be copied, and you can have duplicates in memory at the same time. How are JSL classes different from a class you might be familiar with? I'm sure there are more features that some people might expect to see in classes, but I think these five here represent a fairly standard representation of what people expect from objects.
Encapsulation, inheritance, polymorphism, replication, and abstraction. Inheritance, polymorphism, and abstraction are all related to one another, and classes in JSL have pretty good support for encapsulation, inheritance, and replication, but there are some nuances around implementing polymorphic behavior and abstraction. I'm going to talk briefly about these five things.
Encapsulation is pretty well-supported. When you define a class, you define properties and methods that are associated with that class. The only nuance here is that none of these are true. You can't define a truly private member of the class. Everything is public. It's like a namespace. There's global access to the members and properties of a class.
Inheritance, this also is supported. If you create a class derived from another class, that child class will inherit the members of the parent. There are some nuances around polymorphism, which we'll get into in a little bit more detail later. In order to truly implement polymorphism, there is a specific workaround that is required in order to let a parent class appropriately dispatch to child methods from within its own methods.
Replication, this one is basically the whole point you would want to use classes. You can instantiate multiple copies of an object, and they'll each have their own encapsulated set of parameters and methods, and I haven't really encountered any problems with this.
Then abstraction, there is no explicit notion of abstraction in JSL classes, but you can define a parent class with some default methods that maybe return an error or just do some basic behavior. If you're familiar with C# or other languages, this might be closer to a virtual method than an abstract method. That's the high level overview of how classes in JSL might be different from classes you're familiar with if you're coming from other languages. With that very quick and rushed overview of classes in JSL, I am going to switch over.
We've got our JMP instance open. I've got a couple pretty simple examples. Well, one simple example that I want to start with, then a slightly more complicated one, and then a much, much more complicated one. The first one that I want to talk about is a very basic progress bar.
These demos are all with the context of making GUI development more extensible, more modular, letting you take full advantage of the capability of objects. In this progress bar, I'm just going to run it real quick, so you can see what it's doing. The basic implementation for a progress bar I found online somewhere in a some post, somebody was asking about it. I'll show you the details of how the progress bar is made, but they're not the most important for this.
This code is essentially setting up a few things to define what the progress bar looks like. It's creating a window. It's creating… You can see we're creating the objects here, and we'll go into the code for the objects in a minute. Then it's just arranging things into a window, making some random stuff that you can… To represent the task that you'd be running. Then it's just iterating as if it's doing some processing, and it is updating the progress bars by using these methods, which are part of the class definition itself.
There's not a turn in here, but this object is encapsulating all of the behavior that creates this visualization. Let me bring up that window. We're in the code now. I'm going to go to the progress bar class definition, and let's minimize these real quick. You can see that you define a class by using the define class call, give it a name, and that's how you're going to instantiate it, and then defining variables in a class is as simple as… You define them in the same way you would define another variable.
Now this value is assigned to the instance of the class, so you would access it by doing your class reference and then that name. Now methods in classes are defined in the same way that you might define a function. They are in essence functions under a different name, and these get assigned to that class object. What I mentioned before about classes being like a namespace, you can manipulate… After you've created an instance of a class, you can manipulate all of these things. You can add properties that will be assigned to the object you created. You can do all kinds of very dynamic things with JMP classes.
I'm not going to go into a lot of detail with that. I just want to focus on how this progress bar gets created. The initialize function, this will get run. Let me bring this up into a side view. This example, this initialize function will get run when you create the object. The new object call will automatically run _init.
When we initialize, we have a default config set up in here, but you can also provide it with whatever configuration you want. This just sets up all the basic stuff, and then at the end, it calls the build command. The build method is defined down here. In the build method, that's where we create all of the objects that go into making the progress bar look the way it does. We've got our container, and then there's a few spacer boxes, and the spacer boxes are what you grow and shrink in order to create the effect of progress, and again, this came from, I don't have the source on hand, but there was a JMP community post about it.
This just sets up all of the details for what that progress bar is going to look like. Then you can see we have some helper methods over here that will change the height or the width, and you can call all of that. Then there's also the, well, how do you interact with it and change the amount of progress? These are just methods. They have different functionalities, so set will provide a… It'll set the percentage explicitly to a value. Step will advance it by a certain amount, and then you can define whatever other things you want.
You could tell it exactly how many steps there are and then just advance it each time you iterate through. You could manipulate the methods here to whatever you needed to suit the particular task. Again, if we go back to the example now that we have the context here, this is pretty straightforward. We're just creating the object, and then in the… When we set up the new window in here, in order to take advantage of the object, we have to be able to get the actual display element out of it.
In the progress bar, the high level container is this H list box here. But if we get the object, all we're doing is returning that value or returning that container. In the new window definition, if we want to insert the progress bar at a particular location, we can just take the object or take the object we created and get… This could be clarified as something like get panel. That that would make more sense, but here we are.
Anyway, that would be the way that you insert it, and then here, we're still referencing the object reference here, and we're stepping through it for the primary bar, and we're setting it to an explicit value for the secondary bar. We're updating the text here. On it one more time so we can see what it's doing. Again, we're just doing some random values, updating it, and you can imagine how you could insert this into some other task.
One other thing I want to point out that I've found to be useful is you can close the progress bar, and if you do that, the next time it tries to iterate through, it'll fail because it doesn't have the reference to the windows anymore. You've closed it, and in here now when you run this update to try to update the window, it can't do that. So it returns an error.
Because this is all wrapped in a try statement, that'll fail, it'll kick it out to here, and so this is a quick and dirty way to interrupt processing if that is something that you need to do, which I have needed it on multiple occasions. That's the progress bar. Pretty basic implementation. There's many ways you could customize it. You could get information out of it, you could do whatever.
The next thing that I want to talk about is somewhat more complicated, and probably requires a little bit of setup. I want to bring up these tables here. I've taken the big class sample table and done some randomized data for it because I want to demonstrate the virtual join functionality. For anybody not familiar with virtual joins, there's the standard join where we could take… We have this class of big scores. It's got multiple entries for every student. They attempted 10 times on to do something, and they got a score. It only has their name, the attempt and the score, but we have all this other information over here. We want to get it onto here. We do a join. I'm sure anybody using JMP has done that before.
That will bring these values into this table, but there's another way to do it. All of these names are unique. We can set these to be a link ID, and then over here in this table, we can take that, and we can reference this table here. Now we have a virtual join, we can see all of that information. If we come back here, I can hide or unhide, and now we have the information from this column of this table accessible in this table without having to do a join. We could do the same thing with this table as well.
There's some pretty cool advantages to this. If we go into column info and the link reference property here, you can set it up to accept the selected or excluded state. If I apply this and I come over here, when I select there, this row, it'll select any of the related rows. You get this as well if you do a summary, and you link to the data table or the data view, same sorts of things are happening there.
This is a pretty cool feature. I'd started using it last year sometime, and I very quickly wanted to have a way to automate that in JSL scripting, and I essentially ended up writing a link manager to some extent. Let me clear these. We'll clear the link ID. We'll clear the link reference. These are now just regular unlinked tables.
What I'm going to do is bring up the example link manager here. I'm going to run some of this. We're going to set all of the tables, and we're going to initialize the link manager, and I'll get into the code behind all of this in a minute.
There we go. Don't know what that error was, but here we have the basic window for the link manager. We've got the GUI up, but nothing has been linked yet. The API that we can use, we can set a link source, which is basically going to be equivalent to what I did before over here, where I set the link ID. If I run that, we can see that the link manager has been updated.
We get this new GUI entry here. We can now link one of the tables. We get a new entry. We can link the second table. We get a second entry, and now we have means of getting in and modifying these link configurations.
If I want to have this one dispatch, so if I want the second table, I can set it up so that the select and excludes are all… Basically if I select something over here, I can have that propagate to over here. We've selected whatever. Now, all of these should be selected, and additionally, in the original, the source table as well should be selected.
Normally, if you wanted to update these things, you would have to go in, right click, Column Info, go to link reference, go to dispatch or accept, change whatever you wanted, and then apply, Okay, go to your other one and do it. I wanted something a little bit more dynamic, something where you could see what's going on. You could have another table, you could have multiple sources set up to do all of this, and all of your configurations are right here, so you can turn things off, you can remove the link, all of that.
This was a tool that I found to be particularly useful when you're dealing with bigger data sets across many tables where you might have one big summary table, and you've done some data processing on continuous data, and you want to be able to connect things, but you don't want to make a gargantuan table because that can get a little bit unwieldy. This was spawned from all of that.
Now if we want to get into the code, this is going to be a little bit more involved, and one thing I want to be very upfront about is none of this is optimized. A lot of this is still the… You could call it the first draft implementation. I got it working and haven't gone back and cleaned things up. Bear that in mind as I'm going through some of these.
You can see the initialize function here that I called, and this is just checking to see if there's an object, otherwise it's making one. One of the things that could probably be improved is I originally started by thinking I might want multiple link managers to be active at a time if I have multiple projects up and maybe that's useful, maybe not, but this class here is essentially implemented as a singleton at the moment.
You could instantiate more if you wanted, but that functionality would be a little bit sketchy for some specifics that I'll get into in a minute. But essentially, the link manager it's basically just maintaining some arrays that define how the tables are linked together and what table is linked to what and what the current state of the link is. It has methods for changing the links and doing all that fun stuff.
For the GUI, there are two classes that we have implemented here. There's this link config. This is, if I can bring up the… Let me bring up the link manager window. Where is it? Right here.
If we look at the link manager window, the link config is this box that lets you change the accept dispatch, select exclude, that would be the config, and then the tab, the link source tab is one of these. A source gets a tab, because there are some rules around what column can be linked, and what can be linked to it, and various things like that. When you create a link source, the link manager is creating one of these objects.
There's a whole bunch of other stuff happening to check things and set up some events to know when tables close and whatnot, and you can ignore all that. This is the meat of it right here. It's creating a new link source tab object and it is providing the table.
That's pretty much it. It gets appended to the GUI and I think that's somewhere down here. There's the source list in here, and so this gets appended to that, which is just a container, and you can see where we have this function to get the tab that that's the actual display object. This is basically handling a lot of that replication. Each time we create a new source, we create a new one of these and we automatically get all functionality.
If we go into the source tab, this is also going to have an initialization. It has its own display object, it's a page box, there's some lining up stuff that's happening, and then it too has a list object here. This is what contains all of the different link configs that you might have. Again, remember that this is probably a little bit unoptimized, but you can start to see how it is a little bit more… It is potentially easier to build out dynamic behavior to an interface in JMP. I've used this in multiple other places.
Some of you may have noticed I have up here this recall library, that was what I alluded to a little bit ago when I first started about there being a much more complex implementation. I don't think I have much time to really get into this. I wish I did because this was actually the very first project that I embarked upon using JMP Classes. Unfortunately, it too is still in a first draft state, you might say. There's a lot going on in here that could be consolidated very easily.
I guess at this point, I'm mostly just hoping I've got you thinking about how classes in JMP can be leveraged to provide more dynamic behavior and make the code a little bit cleaner. Because I know when I used to try to… I've seen some complicated and dynamic UI code where you build it all right into the new window function.
Right in the new window, you end up with 20 tabs in of just all of these functions and buttons doing this and that, and this and that, when there are much cleaner, much more object-based ways of implementing the same behavior. It's more maintainable, scalable, easier to read. I think there's a lot of benefits to working with classes when it comes to trying to implement UIs.
I'm not going to go into any of the recall stuff. The only thing that I will add is I'm going to be working to get all of these example code and the recall library as well cleaned up and provided in a public Git repo, where anybody who's interested can take a look, clone the repo, fork it, do whatever you want to make use of it and try to understand how you can leverage JMP classes in your own code in a way that it increases your efficiency.
I think the only thing left would be quickly pointing out some of the initial things that I talked about with scoping. We've gone through the examples, you've seen how you can begin to build up structures to implement these dynamic GUIs, but now to understand what the headaches are and how you can get around them. I think a good example would be… Let's see if we can do it in here.
If I pick one of these, the scoping issue that I talked about earlier relates to how you call methods and what scope they're inheriting. I have seen several issues around trying to work in the Here namespace. I've seen collisions between the global namespace and methods, and essentially to make it as simple as possible, the foolproof way that I have identified to get around any scoping issues that you might encounter with a class, and I'm not demonstrating here, but this is a good example to show you how you might want to do it, is to just use a local modifier. I like to format mine like this.
The only variable in here that needs to be explicitly defined would be this one. Here, this is just a variable that we're setting up to essentially parse out and create the property that will create the reference. That code is irrelevant. Just this variable could shadow a variable in another scope, simply because it wasn't defined as local, and depending on where this method gets called in your code, this variable could provide a conflict.
This is really the cleanest way that I have found to try and avoid any scoping conflicts with classes is to be very explicit about local variables. I would assume that I have to go through and do that for basically all of these methods because most of this was written before I understood what the best method was to get around some of those issues. The only other thing that helps you get around the issues is to use explicit namespace identification.
Anytime I'm writing a library, I am essentially writing it in a new custom namespace, and I try to define all of my variables and methods or variables and functions as a part of that namespace as well, and that has helped me avoid conflicts.
Then I guess, actually, the other thing to talk about too, and this is not a very good example for, would be some of the problems with polymorphism and inheritance. Let's see. A good place to talk about that might be in the recall library.
Hopefully, it's not too… We can avoid some of the details of the implementation and only focus on what the problems are. Based on what we've seen so far, the rough overview is this recall panel is essentially a container that you can set up to automatically recall the values of the fields. Now, is intended to be inherited from, so it's intended to have child classes that need to call some of the behavior. It's specifically this method her. The child class would need to implement its own version of the build method.
Now, this is where the polymorphism nuance comes into play because if you were to try and call this method from one of these other methods, so we're in the parent class, and you want to call build and there's a child that overrides the build, it will not properly dispatch build to the child method. I don't have the explanation as to why I think there's got to be some of the nuance about how the classes are implemented on the back end. But there is a way to over get around that. It is, I think, best demonstrated in a different library, but alas, I am not prepared to go into that.
I think I'm going to avoid going into the details on that and just try to say that you just close by saying that polymorphism, or the fact that you can implement a child class which will override behavior may not function as expected, which is a little bit unfortunate because I think inheritance is one of the more useful aspects of classes.
While you can inherit behaviors, it is a little bit more complicated to call those inherited behaviors in the parent class. I think that's how I will phrase it. When I put these materials online, I will try to include some more specific examples on how and why that doesn't work. Again, I'm really only trying to give an overview of how you can begin to incorporate classes into your UI designs in Junk JSL.
With that said, I'm going to I'm going to cut myself off from rambling too far. Again, my name is Ben Barrett, and I encourage you to reach out if you have questions or want to see more of these implementations. Beyond that, thank you very much.