MDI is a Java framework for building scientific desktop applications with:
- Interactive plotting
- Simulation engines
- Multi-view modular architecture
- Extensible tools and layered drawing
- Distribution via Maven Central
It is built on pure Swing for long-term JVM stability and zero external runtime dependencies.
Scientific desktop applications have different needs than typical GUI apps:
- Long-running simulations
- Real-time data visualization
- Multi-document workflows
- Precise rendering control
- Stability across Java versions
MDI provides architectural infrastructure for these use cases.
It is not just a widget toolkit.
It is a foundation for building complete scientific applications.
Each window (“view”) operates independently while sharing:
- Messaging infrastructure
- Common models
- Simulation engine integration
- Extensible toolbars
- Layered drawing support
The built-in plotting module provides:
- Thread-safe curve updates
- Swing EDT-safe rendering
- Curve fitting
- Lock-free staging queues for background updates
- Coalesced repaint events
Plots can safely receive data from worker threads without repaint storms.
MDI includes:
- Step-based simulation engines
- Cancel support
- Reset hooks
- Coordinated view refresh
- Background execution integration
Ideal for:
- Physics demonstrations
- Optimization visualizations
- Network simulations
- Educational tools
Calculations that produce one result do not need to be expressed as an
artificial one-step simulation. Create a typed TaskHandle, register listeners
while it is still unstarted, and then start it:
TaskHandle<Result> handle = BackgroundTasks.create(context -> {
context.reportIndeterminateProgress("Building matrix…");
Matrix matrix = buildMatrix();
context.throwIfCancellationRequested();
context.reportProgress(0.5, "Solving…");
return solve(matrix);
});
handle.addListener(new TaskListener<>() {
@Override
public void onSucceeded(TaskHandle<Result> source, Result result) {
// Runs on the Swing EDT; it is safe to update a view here.
showResult(result);
}
@Override
public void onFailed(TaskHandle<Result> source, Throwable error) {
showFailure(error);
}
});
handle.start();The task body runs on MDI's daemon simulation thread. Progress, messages, and
listener callbacks use the simulation engine's EDT-safe, coalesced delivery.
Cancellation is cooperative: call handle.cancel() from the UI and check
context.isCancellationRequested() or
context.throwIfCancellationRequested() inside lengthy loops.
For a standard UI, embed new TaskControlPanel<>(handle). It supplies Start
and Cancel buttons, progress and status displays, and elapsed time. For concise
fire-and-observe work, BackgroundTasks.submit(task) creates and starts a
handle immediately; use create when listeners must see every lifecycle event.
Existing step-oriented simulations can use the additive
SimulationListener.onCompleted(...) callback when they need one terminal hook
covering success, explicit stop, cancellation, and failure. Existing
onDone, onFail, and onCancelRequested behavior is unchanged.
Views support:
- Items
- Layers
- Mouse interaction
- Selection tools
- Virtual desktop behavior
This makes it easy to build:
- Network graphs
- Geometric editors
- Data overlays
- Interactive teaching tools
MDI is available on Maven Central:
<dependency>
<groupId>io.github.heddle</groupId>
<artifactId>mdi</artifactId>
<version>1.2.3</version>
</dependency>The following minimal example creates an MDI application with a single DrawingView:
This example demonstrates:
- Creating an MDI application by extending
BaseMDIApplication - Configuring a
DrawingViewusing key–value properties - Adding initial content once the virtual desktop is ready
public class HelloMDI extends BaseMDIApplication {
private final DrawingView drawingView; //only view
public HelloMDI(Object... keyVals) {
super(keyVals);
// set to a fraction of screen
Dimension d = WindowPlacement.screenFraction(0.4);
// specify (bitwise) what will be on the toolbar
long toolBits = ToolBits.STATUS | ToolBits.DRAWINGTOOLS | ToolBits.ZOOMTOOLS | ToolBits.PAN;
drawingView = new DrawingView(
PropertyUtils.WORLDSYSTEM, new Rectangle2D.Double(0, 0, d.width, d.height),
PropertyUtils.WIDTH, d.width,
PropertyUtils.HEIGHT, d.height,
PropertyUtils.TOOLBARBITS, toolBits,
PropertyUtils.VISIBLE, true,
PropertyUtils.BACKGROUND, Color.white,
PropertyUtils.INFOBUTTON, true,
PropertyUtils.TITLE,"Drawing View");
}
// Runs once after the outer frame is showing and Swing layout has stabilized.
@Override
protected void onVirtualDesktopReady() {
// desktop ready, safe to apply default placements and add content.
drawingView.center();
//lets add some initial content to the drawing view
Layer layer = drawingView.getContainer().getAnnotationLayer();
CreationSupport.createRectangleItem(layer, new Rectangle(50, 50, 100, 100));
}
// Main method to launch the application.
public static void main(String[] args) {
BaseMDIApplication.launch(() ->
new HelloMDI(
PropertyUtils.TITLE, "Hello MDI",
PropertyUtils.FRACTION, 0.8
)
);
}
}The repository includes a full-featured DemoApp showcasing:
- DrawingView
- PlotView (splot integration)
- Network layout demo
- Traveling Salesperson simulation
- 2D map view
- Simulation framework examples
To run the demo from the project source:
mvn clean package
mvn exec:java -Dexec.mainClass="edu.cnu.mdi.app.DemoApp"
