Showing posts with label javafx. Show all posts
Showing posts with label javafx. Show all posts

Sunday, July 24, 2022

Changes to the copresheaf viewer

The basic objects of the Locus computer algebra system are copresheaves. Locus implements all my original research and ideas about copresheaves and their congruences, and these ideas in turn have influenced my ideas on the use of copresheaf theory in foundations. Once we have established sufficient motivation for wanting to work in terms of copresheaves, it would be nice as a next step to develop tools to make it easier to work with them.

The first such tool I have devised to work with them is the copresheaf viewer. This was implemented in a very small amount of lines of Clojure code using Graphviz and Swing. It consisted of two components: a view of the source category as displayed by Graphviz and a JList used for interacting with the objects and morphisms of the category. These two components are combined in a split pane as seen below. The problems with this user interface design approach are apparent from the get go. This approach is clearly not scalable.
  • You should be able to interact with the index category in place, rather then having to separately go to the JList to access an item. Imagine if we had a large index category with hundreds of objects and morphisms, then you would have to scroll through all of them to find what you are looking for. Instead you should be able to click an object or morphism in place.
  • The view of the source category should be pannable and zoomable. This will allow you to interact with increasingly large source categories, with hundreds of objects and morphisms so that you can find exactly what you are looking for.
So we need a sort of pannable, zoomable, interactive directed graph viewer. It is clear that JavaFX is the technology for this, as Swing is not suitable for designing applications with advanced graphical transformations. A scene graph, like what is provided by JavaFX, is precisely the sort of technical appartus that is needed for this type of job. Three JavaFX graph editor like programs are available and have been considered: I seriously considered each of these options, because I didn't want to create a JavaFX graph editor myself. Unfortunately, none of theme seems to have the idea of displaying categories in mind. In order to display a category we need to support multiple labeled directed edges. Many of these graph editors don't support labeled edges or perhaps even multiple edges, especially the last two. The first one seems to be specifically concerned with the Eclipse modeling foundation technologies, which is a whole different concern entirely.

Another issue is that these graph editors might not have support for adding event listeners on their vertices and edges. Even if they do, they might have the documentation to describe it. Basically, I have a very specific use case: creating interactive displays of categories. This explains why I created my own JavaFX copresheaf viewer, although I didn't set out to do so. At least with this, you can directly click on an object or a morphism to get its corresponding output, without having to go through a JList. It also supports zooming and panning, so you can get a much better handle on some copresheaves. I want everything in general, but in Locus especially, to go through some kind of copresheaf so this viewer is really the key to everything in our whole algebra system.

The copresheaf viewer is programmed in Java. In order to call it from Clojure, we reify a GraphActionListener with vertex and edge actions that apply the copresheaf to its corresponding objects and morphisms and this works fine for now. This gives us an interactive handle on copresheaves, which works pretty good for now.

The only limitation of this approach is that it has limited capabilities for handling graph layouts. I support a simple mechanism for layouting directed acyclic graphs from their partial orders using a ranking like a Hasse diagram. This is good for a number of simple categories, but for anything else you may have to hand hold the copresheaf viewer so that it lays out the objects of the category appropriately.

One thing that is nice is that if you are viewing an MSet in the JavaFX copresheaf viewer, the loops of the source category of the MSet do not overlap so you can more easily access them. I implemented this with a simple algorithm that goes around the node and places the loops separately so they don't overlap. This didn't even always occur in the Graphviz viewer, which despite working great for almost everything also wasn't built with displaying categories in mind. An option I have considered is using JNI or some other solution to access Graphviz layout mechanisms.

It is clear that no graphical user interface program is perfect, and both my copresheaf viewer and to a much lesser extent Graphviz could use some improvements. I look forward to even being able to replace this JavaFX copresheaf viewer with something else, as long as it works better. The most important thing is achieving the vision of a computing environment based upon presheaf theory, however, that happens.

All I have is a grand vision of presheaf theory involving mathematical means of reasoning about presheaves, data structures and algorithms for running computations involving copresheaves, ideas for how to graphically and interactively display copresheaves, new presheaf theoretic mechanisms for creating ontologies, etc. The Locus project is nothing more then the embodiment of this mathematical vision.

The transference of attention to presheaf topos theory is just the first step in building the future of computing. Once you work in presheaf theory, it is possible to create new topos theoretic ontologies and a geometry of computation. Foundations are important, and so it is only by using topos theoretic foundations that these great avenues of exploration can be made available.

Friday, May 20, 2022

Java desktop applications

I have posted a number of times about the various Java-based desktop application frameworks like Swing and JavaFX, and how you can create various applications with them in either Java or Clojure. It occurs to me that I should write an overview of the different desktop libraries that you can use in your JVM applications.

AWT

The AWT (abstract window toolkit) was introduced with Java 1.0. A major purpose of AWT and the first versions of Java was to provide support for Java applets. An applet is an AWT component and container, so applets were fully integrated into the AWT widget system. They basically allowed you to add AWT components into webpages. There weren't many options to add interactivity into websites at the time.

The AWT toolkit came with a peer system provided by the java.awt.peer package. Each AWT component came with a peer, which is that component defined in the native environment. This means that AWT components were heavy weight, already in the next version of Java was updated to address this.

The old peer system meant that each new Component class had its own opaque native window. Java 1.1 was updated with the lightweight UI framework which allowed you to directly extend java.awt.Component and java.awt.Container to create your own components that do not have native windows associated to them. In a way, this layed the foundation for Swing which builds upon these classes. It goes without saying that classical AWT is not used anymore.

Swing

The Swing library was released as part of Java 1.2. It was based upon the Java 1.1 lightweight UI framework. In particular, all Swing components extend java.awt.Component and java.awt.Container. They are lightweight, so they don't have native counterparts.

In place of native widgets, Swing came with a pluggable look and feel (PLAF). Swing widgets don't inherit from native widgets, but in theory you can at least make them look like them. Or you can modify the existing look and feel to create your own.

The fact that Swing was constructed on the AWT means that it has a lot of historical legacy. For example, all Swing widgets start with the letter "J" so that they don't interfer with their AWT counterparts. So you use JFrame instead of Frame, and JButton instead of Button, and so on. This makes Swing appear like a legacy framework with a great deal of baggage.

The fact that Swing was introduced early on meant that applets were still widely used. Swing extended the Applet class with the Swing based JApplet class, and after that many applets were created with Swing. Applets were phased out in the 2010s, for various reasons that we could go into depth on later. Probably the most basic one is that JavaScript gained a kind of maturity that led browser vendors to consider it sufficient.

Swing is basically where we are at now. Although it doesn't run in browsers and it is full of historical legacy, it is still a part of every Java SE distribution and some of the best desktop applications are developed with it. IntelliJ IDEA, for example, was created with Swing. So we are stuck with Swing as part of the Java desktop application stack for the forseeable future.

JavaFX

The fact that Java Swing comes with so much legacy means that it is necessary to have a fresh start. That fresh start came with JavaFX. The components in JavaFX do not extend from their AWT counterparts. JavaFX was intended to replace Swing in Java SE, but that project was abandoned and it was moved out of the JDK to be maintained elsewhere.

JavaFX also comes with a number of more modern features, like an updated scene graph library. Scene graphs are a fundamental part of any advanced structured graphical applications like zooming user interfaces or interactive 3D components. JavaFX was also equipped with an XML based file format and support for CSS styling of components. Its API is more modern and clean then Swing.

Alternatives

The Java platform comes with the Java native interface (JNI) which allows Java programs to interoperate with C/C++ programs. In theory, this should allow you to create any number of different types of user interfaces using native components. The only really successful example is SWT. It uses the JNI to create Java based extensions of native widgets, to provide users with a native look and feel that fits in with the platform.

As is the case with AWT, this means that it is hard or impossible to extend SWT components because they rely on native peers. Additionally, the fact that SWT requires the JNI means that you have to package your program to deal with different desktop environments and toolkits. SWT is not part of Java SE, but unlike other alternative desktop toolkits it has strong support because of its use in the Eclipse IDE.

Remarks

The Java platform is widely used in scientific and mathematical applications. These applications of course need to have data visualisation functionality associated with them. I am looking in to JavaFX for scientific visualisations, it already has its own charting library built in for example. But I can't make any promises, all I know is I will continue to use the JVM which I have already dedicated so much time to.

External references:
Java desktop module

JavaFX overview

Saturday, April 30, 2022

Visualising prime distributions with JavaFX

Let $n \in \mathbb{N}$ be a natural number greater then zero $n > 0$. Then by the fundamental theorem of arithmetic $n$ is associated to a multiset of prime factors. By the relative multiplicities of this multiset, this number is always associated to a prime distribution. We can display these prime distributions using JavaFX.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.chart.*;
import org.apache.commons.collections4.multiset.HashMultiSet;
import org.apache.commons.math3.primes.Primes;
import java.util.ArrayList;
import java.util.HashMap;

public class PrimeDistributionChart extends  Application {
    public HashMap primeDistribution(int n) {
        var factors = new HashMultiSet(Primes.primeFactors(n));
        double bigomega = (double) factors.size();
        var rval = new HashMap();

        for(var i : factors.entrySet()) {
            rval.put(i.getElement(), ((double) i.getCount()) / bigomega);
        }

        return rval;
    }

    public void start(Stage primaryStage) throws Exception {
        // this is the number to be factorised
        var initialNumber = 360;
       
        // create the prime distribution 
        var dist = primeDistribution(initialNumber);
        var dataCollection = new ArrayList();
        for(var i : dist.entrySet()) {
            var keyString = i.getKey().toString();
            var data = new PieChart.Data(keyString, i.getValue());
            dataCollection.add(data);
        }

        // make the prime distribution into a pie chart
        ObservableList pieChartData =
                FXCollections.observableArrayList(dataCollection);
        var chart = new PieChart(pieChartData);

        // put the pie chart in a stackpane
        var group = new StackPane();
        group.getChildren().add(chart);

        // set up the scene
        var scene = new Scene(group, 500,450);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Prime distribution");
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

Here is an example of the prime distribution of three hundred and sixty: You can easily change this program to display the prime distribution of any non zero natural number.

Friday, April 29, 2022

Opening JavaFX hyperlinks in the browser

Suppose you have a hyperlink in your JavaFX application. Then you can make it clickable using the HostServices provided by JavaFX.
package application;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HyperLinkExample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        var linkLocation = "http://www.multi-ai.blogspot.com";
        Hyperlink hp = new Hyperlink(linkLocation);
        var root = new StackPane();
        HostServices services = this.getHostServices();

        hp.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent actionEvent) {
                services.showDocument(linkLocation);
            }
        });

        root.getChildren().add(hp);
        Scene scene=new Scene(root,400,300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Clickable hyperlinks");
        primaryStage.show();

    }

}

The idea of opening up a separate browser window for a hyperlink provides an alternative to using the JavaFX webview.