Re: Layering JavaFX onto an external rendering context

2021-03-07 Thread Mark Raynsford
On 2021-03-07T12:22:11 +
Neil C Smith  wrote:

> Hi,
> 
> A few comments from my perspective here, mainly coming from
> frustration at the number of times I've had to tell clients or users
> that JavaFX isn't a viable option for them ..
> 
> On Sat, 6 Mar 2021 at 12:22, Mark Raynsford  wrote:
> > there is a
> >  combinatorial explosion of possibilities with regards to which
> >  rendering API the _user_ might be using, and which rendering API
> >  JavaFX might be using (if any!).  
> 
> I agree that's a difficult one, but also surely not an insurmountable
> one?!  There are precedents around Java APIs that provide querying and
> access to optional support on a platform by platform basis...

I think it's insurmountable due to the complexity of the semantics of
the thing (the GPU) that's being abstracted over. The basic primitive
that would be required is "transfer this image to this other image".
You'd need to expose that operation in way that would work for every
possible pair of rendering APIs, including getting all of the
synchronization right that lower level APIs like Vulkan and DX12
require. The complexity of handling that would need to be pushed onto
each person trying to use the API. JavaFX would effectively need to
know when it was safe to use an image that was being transferred in,
without actually being able to know where the image was coming from or
who to talk to about it. The only methods it _could_ use would involve
CPU-side fences, which would then have performance implications.

To clarify a bit: Let's say we lived in an ideal world and JavaFX had a
Vulkan backend, and contained code that was willing to cooperate with
the user's Vulkan-based rendering code. The user could tell JavaFX
"here's the image to use for this node, but don't use it until this
semaphore becomes available". This is generally highly efficient as a
semaphore (in Vulkan terms) is a GPU-side primitive that just controls
parallelism across different queue instances on the GPU, with no
CPU-side interaction at all.

We have no way to get to that ideal world whilst JavaFX and the user's
code have no common API over which to communicate. Everything would
have to go via CPU-based abstractions.

> > Traditional stateful APIs like
> >  OpenGL make it far too easy for external code to screw up the
> >  rendering context anyway, so exposing JavaFX's own context would
> >  be a bad idea.  
> 
> I remain of the view that this shouldn't really be that concerning?!
> It's a bug in the library if it does so.

It's definitely concerning. Have you worked with OpenGL much? If you're
*lucky* you'll get a crash, because at least then you'll see the
exact location where the mistake occured. What you'll typically get
instead is corrupted rendering, a black screen, or just bad performance
as the driver desperately tries to make sense of what you asked it to
do, usually in completely unrelated parts of the rendering process. It's
the prime reason I jumped ship to Vulkan the second it came out. :)

> > JavaFX _does_ have a software renderer. What if we could have JavaFX
> > work with entirely software rendering into an offscreen BufferedImage?  
> 
> Why BufferedImage?  What about a reuse / extension / parallel of
> PixelBuffer? 

Yes indeed. I said BufferedImage just because I assumed that would be
more familiar. I'd not personally care where the output went as long as
I could get the raw bytes out of it in order to upload to the GPU.

-- 
Mark Raynsford | https://www.io7m.com



Re: Layering JavaFX onto an external rendering context

2021-03-06 Thread Mark Raynsford
On 2021-02-15T13:40:43 +
Mark Raynsford  wrote:

> Hello!
> 
> I'd like to use JavaFX for the UI of an application that will
> involve rendering using an existing Vulkan-based renderer. For the sake
> of example, assume that the application looks and behaves a bit like
> the Unreal Engine 4 editing tools

Apologies for the delay in responding (I've read and digested every
reply).

So... Having read everything, I'm reasonably sure that the ability to
do this in the "traditional" way - that is, having a node in the
JavaFX scene graph that displays the contents of a GPU-side
image/texture - isn't going to be happening any time soon. There are
multiple intersecting issues that make this intractably difficult to
achieve:

  1. There are software boundaries; JavaFX doesn't expose the internal
 rendering context it uses and, even if it did, there is a
 combinatorial explosion of possibilities with regards to which
 rendering API the _user_ might be using, and which rendering API
 JavaFX might be using (if any!). Traditional stateful APIs like
 OpenGL make it far too easy for external code to screw up the
 rendering context anyway, so exposing JavaFX's own context would
 be a bad idea.

  2. There are hardware and concurrency issues; Let's assume that
 JavaFX is using OpenGL or DirectX internally. Let's also assume
 that the user is using some kind of API that explicitly provides
 for managing concurrency with primitives such as fences,
 semaphores, etc. The user would have to somehow magically arrange
 for an image transfer on the GPU into an image that JavaFX knew
 about, and would have to somehow set up all of the right memory
 barriers and notify JavaFX when the transfer was completed. This
 is likely to be intensely error-prone at the very least. The
 thought of implementing this directly brings me out in a cold
 sweat.

So how about another approach entirely?

In the past, I've rendered UI elements using entirely software rendering
and then uploaded the software-rendered UI as a texture to be overlaid
on top of the 3D rendered view. I could obviously continue to do this,
but maintaining entire software-rendered UI toolkits myself is a burden,
and it would be great if I could use an existing known-good toolkit
instead like JavaFX.

JavaFX _does_ have a software renderer. What if we could have JavaFX
work with entirely software rendering into an offscreen BufferedImage?

To make this work, we'd need the following:

  1. We'd need to be able to initialize JavaFX in a manner that
 _didn't_ require JavaFX to "own" the primary stage. That is,
 right now JavaFX will invoke a user's Application subclass
 with a Stage that JavaFX created by itself. This won't work
 for most rendering engines, as typically the programmer has
 to do a fair bit of work to open a graphics context with
 the correct settings. Consider the typical code needed to
 open a window over GLFW with Vulkan...
 

https://github.com/io7m/jcoronado/blob/develop/com.io7m.jcoronado.examples/src/main/java/com/io7m/jcoronado/examples/HelloVulkan.java

  2. We'd need to be able to force JavaFX to operate entirely
 using Java2D software rendering. This shouldn't be a problem
 at all.

  3. We'd need to be able to make JavaFX render to an offscreen
 BufferedImage. It would be the responsibility of the programmer
 to submit keyboard and mouse events to JavaFX manually, because
 JavaFX would no longer "own" the primary application window.
 I believe the first half of this is already doable in the sense
 that the Node class allows for taking snapshots of a scene; these
 snapshots could be uploaded to the GPU as textures. The second
 half I believe is not exposed in any sense; JavaFX opens its own
 windows, and consumes input events from those windows directly.

I wonder if it would be possible to, for example, add some kind of
WindowFactory API to JavaFX so that, when JavaFX wants to create a
Window, there's the option to delegate window creation to the
user. The created windows might not even be operating system windows
(for window-in-window UI systems)[0]. As long as the returned Window
instance acted like a Window in terms of returning dimensions,
producing the right input events... Would JavaFX even know that it
wasn't dealing with an operating system window?

[0] 
https://softcamel.com/wp-content/uploads/2019/03/Transport-Tycoon-Deluxe-2.png 

-- 
Mark Raynsford | https://www.io7m.com



Re: Layering JavaFX onto an external rendering context

2021-02-16 Thread Mark Raynsford
On 2021-02-16T16:09:04 +
Neil C Smith  wrote:
>
> I agree with you, and have certain similar requirements, like being
> able to allow GStreamer and JavaFX to share GPU contexts.  In fact,
> was bugging Johan about this in the chat around his FOSDEM talk, and
> promised to follow up here, so might as well pop my head above the
> parapet. :-)

I do think it ultimately boils down to "provide an image to JavaFX when
it asks for one, and don't allow the image to leave the GPU". I've used
GStreamer outside of Java quite a bit for aggregating feeds from
network cameras... In your case, is it that you want to consume one or
more video streams from GStreamer inside a JavaFX UI? We'd be pretty
close in terms of requirements with regards to not copying across
CPU/GPU boundaries, and requiring low latency. :)

> I certainly don't know what such an API should look like, but in some
> ways to me parallels the differences between io file and nio2 files -
> hidden by abstraction vs type-safe queryable capabilities / profiles.
> In fact, given above, also something slightly akin to GStreamer's
> context querying.
> 
> Incidentally, reading your initial post about PixelBuffer reminds me
> that I should also follow up on a point about concurrency issues with
> that from last year.  The API has (or had?) issues with accessing the
> buffer from the rendering thread after it's been removed in the event
> thread, which particularly with externally allocated buffers makes it
> hard to safely mark as invalid to allow them to be freed.

Yeah, that is a problem. It's why I said in my original email that I
was resigned to the fact that a copy was probably going to have to
happen somewhere. Without going into API specifics, I was sort of
picturing JavaFX maintaining two images on the GPU; at any given time
one is being displayed (ie. used as a texture whilst rendering a scene)
and the other is being offered to the user as a destination for a GPU
copy operation. It would be the responsibility of the user to copy an
image in the right format into the offered buffer. There would need to
be the appropriate memory barriers inserted, and I don't know how this
could/would be handled given that it might be two completely different
graphics APIs involved (there isn't a Vulkan JavaFX backend, for
example,so in my case I'm guaranteed to be talking to something that isn't
Vulkan). When an image had been copied in as required, and JavaFX had
been told that this had happened, the two images would be swapped on the
GPU.

-- 
Mark Raynsford | https://www.io7m.com



Re: Layering JavaFX onto an external rendering context

2021-02-16 Thread Mark Raynsford
On 2021-02-15T14:54:43 +0100
Hervé Girod  wrote:

> I did that with OpenGL some time ago. I should setup a GitHub project to show 
> how it can be done.
>

I appreciate the response, but there is a difference between "I did it"
and "there's actually a good, officially supported way to do this". I've
seen people do various tricks like those in DriftFX:

  https://github.com/eclipse-efx/efxclipse-drift/

But it seems to me like those projects shouldn't _have_ to exist. It
seems like a bit of a design flaw that there isn't an efficient code
path to do something (relatively) simple like this.

Has anyone given any thought as to what an API like this should look
like?

-- 
Mark Raynsford | https://www.io7m.com



Layering JavaFX onto an external rendering context

2021-02-15 Thread Mark Raynsford
Hello!

I'd like to use JavaFX for the UI of an application that will
involve rendering using an existing Vulkan-based renderer. For the sake
of example, assume that the application looks and behaves a bit like
the Unreal Engine 4 editing tools. Here's an example of those:

  https://www.youtube.com/watch?v=2UowdJetXwA

My understanding right now is that there isn't direct support in
JavaFX for building this kind of application, and the primary reason
for this is that there's a sort of conceptual wrestling match for
control of a platform-specific rendering context here. For example:

  * A JavaFX application will tell JavaFX to open a new window,
and the JavaFX implementation will do all of the
OS-windowing-system-specific things to achieve this, and will
also set up a system-specific rendering context depending on
what the underlying platform is (OpenGL, DirectX, Metal, etc).
JavaFX then translates input such as mouse and keyboard events
from OS-specific types to the platform-independent JavaFX types
so that the application can process them.

  * A typical Vulkan application will ask something analogous to
the GLFW library to open a new window, and set up a rendering
context. The GLFW library then translates input such as mouse and
keyboard events from OS-specific types to generic GLFW event
types, and the Vulkan application (probably) translates these
into its own application-specific event types for processing.

Obviously, in a given application, we're limited to having either
one of these things happen, but realistically not both.

The current approach (as of JavaFX 14) seems to be to use the
PixelBuffer API in order to provide a CPU-side bridge between
JavaFX and whatever rendering system is being used for external 3D
rendering. In other words, this is the expected setup:

  1. A JavaFX application will tell JavaFX to open a new window,
 and JavaFX will do all of the system-specific work required
 as described previously.

  2. The application will then tell a library such as GLFW to
 create an _offscreen_ rendering context, perhaps configuring
 Vulkan or OpenGL.

  3. The application, at the end of each frame, copies the contents
 of the offscreen rendering context's framebuffer into a PixelBuffer
 instance to be displayed inside a JavaFX UI.

This, as far as I know, works correctly. The main complaint with
this is that it pays a pretty heavy price: There's one framebuffer-sized
copy operation from the GPU to the CPU (in order to read the required
pixels), and then another framebuffer-sized copy operation back from
the CPU to the GPU (either when writing into the PixelBuffer, or when
JavaFX renders the contents of that PixelBuffer to the screen).

My understanding is that it's essentially necessary to do these two
rather expensive copying operations merely because JavaFX can't and
won't expose the underlying rendering context it uses for its own UI
rendering, and it also can't be expected to talk to whatever other
rendering system the application might be using. The problem is
essentially "we have these two systems both using the GPU, but they
don't know each other and therefore we can't write code to get
memory from one to the other without going via the CPU".

Is this an accurate picture of the situation?

As someone working exclusively with Vulkan, I can arrange to have
the GPU copy the framebuffer into host-visible (not necessarily
host-resident, but host _visible_) memory at the end of each frame.
It's a little sad to have to actually copy that memory over the PCI bus
just to immediately copy it back again, though. Is there no design we
could come up with that would allow for at worst a simple GPU → GPU
copy? I'm resigned to the fact that a copying operation is probably
going to happen _somewhere_, but it'd be nice if we could avoid a 
rather expensive and redundant GPU → CPU → GPU copy.

-- 
Mark Raynsford | https://www.io7m.com



Re: Feature Idea: Mouse Input Grab in Window

2020-12-17 Thread Mark Raynsford
On 2020-12-17T17:17:24 +
Almas Baimagambetov  wrote:
>
> *Use case:* 3D games or 3D modelling tools, where the application "grabs"
> (gets exclusive control of) the mouse and moving the mouse doesn't move the
> cursor.
> 

This is pretty much essential for mouse-based camera control in 3D
simulations, especially when combined with a "warp cursor to center of
window" feature. Typically, the cursor will be confined to the window
and warped to the center of the window at the start of every frame.
This allows for all mouse movements to be treated as delta offsets from
the center of the window, and these can typically be passed directly
into camera handling functions.

-- 
Mark Raynsford | https://www.io7m.com



MediaException with trivial javafx-media example

2020-08-31 Thread Mark Raynsford
Hello!

I thought I'd give javafx-media a shot, as I'd never tried it before
and was curious as to what it was capable of. Unfortunately, it seems 
that the most trivial possible example fails on Arch Linux. The symptom 
is that attempting to create a Media player yields the following exception(s):

Caused by: javafx.fxml.LoadException: 
/home/rm/doc/misc/2020/08/media_example/target/classes/com/io7m/media_example/mediaExample.fxml

at 
javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
at 
com.io7m.jbox/com.io7m.media_example.MainApplication.start(MainApplication.java:43)
at com.io7m.jbox/com.io7m.media_example.Main.lambda$main$0(Main.java:36)
... 8 more
Caused by: MediaException: UNKNOWN : com.sun.media.jfxmedia.MediaException: 
Could not create player! : com.sun.media.jfxmedia.MediaException: Could not 
create player!
at 
javafx.media/javafx.scene.media.MediaException.exceptionToMediaException(MediaException.java:146)
at 
javafx.media/javafx.scene.media.MediaPlayer.init(MediaPlayer.java:518)
at 
javafx.media/javafx.scene.media.MediaPlayer.(MediaPlayer.java:421)
at 
com.io7m.jbox/com.io7m.media_example.MainController.initialize(MainController.java:57)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2573)
... 12 more
Caused by: com.sun.media.jfxmedia.MediaException: Could not create player!
at 
javafx.media/com.sun.media.jfxmediaimpl.NativeMediaManager.getPlayer(NativeMediaManager.java:295)
at 
javafx.media/com.sun.media.jfxmedia.MediaManager.getPlayer(MediaManager.java:118)
at 
javafx.media/javafx.scene.media.MediaPlayer.init(MediaPlayer.java:474)
... 15 more

The example code is here, just run the com.io7m.media_example.Main program:

  https://github.com/io7m/media_example_20200831

All the program does is unpack an included royalty-free H.264 MP4 file into
a temporary directory and attempts to play it in a 128x128 window.

I've traced the execution to this line in GSTMediaPlayer.java:

int rc = gstInitPlayer(gstMedia.getNativeMediaRef());
if (0 != rc) {
dispose();
throwMediaErrorException(rc, null);
}

It appears that gstMedia.getNativeMediaRef() returns 0L, and rc == 257
after the call. This results in the given MediaException.

I don't think I'm misusing the API, so I'm guessing that this is some
kind of system incompatibility. I've seen similar reports online, but
those appeared to be down to using a raw filesystem path as the media
source rather than a URI, but that's not the case here.

$ uname -a
Linux sunflower.int.arc7.info 5.8.4-arch1-1 #1 SMP PREEMPT Wed, 26 Aug 2020 
18:35:43 + x86_64 GNU/Linux
$ java -version
openjdk version "14.0.2" 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12)
OpenJDK 64-Bit Server VM (build 14.0.2+12, mixed mode)

Any assistance would be appreciated!

--
Mark Raynsford | https://www.io7m.com



Re: Remove JavaFX JPMS enforcement

2020-04-20 Thread Mark Raynsford
Am I missing something here? What absurd arguments are required for
Maven projects?

I have multiple applications here running in full module-path mode (the
applications are modularized, and JavaFX is on the module path), using
plain Maven builds with no special arguments, and IDEA as the IDE.
This is on JDK 13, with the 13.0.2 JavaFX release from Central.

-- 
Mark Raynsford | https://www.io7m.com


Re: Gitter chat + StackOverflow [was: Concatenating transforms to scale positions but not objects]

2019-08-13 Thread Mark Raynsford
On 2019-08-12T14:25:37 +0100
Mark Raynsford  wrote:
>
> Hello!
> 
> Here's the StackOverflow question:
>  
> https://stackoverflow.com/questions/57461988/using-an-alternate-coordinate-system-inside-a-pane-or-region

And, right on cue, the question has been marked as "off-topic".

I don't believe that StackOverflow is suitable for general community
support. At least half of the interactions I have had with it have ended
similarly.

Thanks, Michael, for attempting to respond on StackOverflow.
Unfortunately, the somewhat rabid moderators have decided that my
question isn't worth asking and that your response isn't worth
listening to. Sadness.

-- 
Mark Raynsford | http://www.io7m.com



Re: Concatenating transforms to scale positions but not objects

2019-08-12 Thread Mark Raynsford
On 2019-08-11T07:15:41 -0500
Eric Bresie  wrote:

> Are you focused on things from a pane/layout perspective here? Maybe some 
> different layout might help.
> 
> https://openjfx.io/javadoc/11/javafx.graphics/javafx/scene/layout/package-summary.html
> 
> Or are you looking for some form of “chart” component to allow lines to be 
> graphed?
> 
> https://docs.oracle.com/javafx/2/charts/line-chart.htm
> 

Unfortunately: Both :)

Thankfully, though, the two problems are solvable separately and I only
need to focus on the first problem (the pane/layout). I need to
position objects in a pane, but I do also need to draw a scrollable
grid inside that pane. The issue with using the Chart API to draw graph
lines is that I think it assumes that graph tick lines on both axes
will always have the same spacing. Unfortunately, given the nature of
music (with changing time signatures at different points within pieces
of music), the spacing between graph tick lines can change at different
points on the timeline. Thankfully, I've already written a custom
canvas-based component to deal with this.

-- 
Mark Raynsford | http://www.io7m.com



Re: Gitter chat + StackOverflow [was: Concatenating transforms to scale positions but not objects]

2019-08-12 Thread Mark Raynsford
On 2019-08-11T09:47:22 +0100
Mark Raynsford  wrote:

> On 2019-08-11T01:41:39 +0200
> Michael Paus  wrote:
> 
> > Nir is right here but if you could ask your question on StackOverflow
> > I'd be willing to comment on it because I was facing a very similar
> > problem in my projects and I might provide some ideas.

Hello!

Here's the StackOverflow question:
 
https://stackoverflow.com/questions/57461988/using-an-alternate-coordinate-system-inside-a-pane-or-region

Out of interest: Is there any interest in setting up a Gitter.im chat
room? Given that there apparently isn't a mailing list for user
questions, and that there _is_ a GitHub presence for OpenJFX, a
Gitter.im chat room would appear to be the logical place for user
discussions.

I'd be happy to set up and run such a thing. I find Gitter strikes a
fairly nice balance in that it's accessible if you already have a
GitHub account, it stores a persistent searchable history like a mailing
list, but it's also capable of real-time communication if needed, and
is accessible without needing any kind of proprietary client. I'm not
sure if there's any other service that ticks all of those boxes. I'm
open to suggestions, though.

-- 
Mark Raynsford | http://www.io7m.com



Re: Concatenating transforms to scale positions but not objects

2019-08-11 Thread Mark Raynsford
On 2019-08-11T01:41:39 +0200
Michael Paus  wrote:

> Nir is right here but if you could ask your question on StackOverflow
> I'd be willing to comment on it because I was facing a very similar
> problem in my projects and I might provide some ideas.
> 
> Am 11.08.19 um 01:25 schrieb Nir Lisker:
> > I think that this is a better question for StackOverflow. This is a
> > development mailing list.

The Community section on https://openjfx.io points here:

"JavaFX features a vibrant and passionate developer community. This
enthusiasm can be found in the open source mailing list [link to
openjfx-dev]."

There's nothing anywhere that I can see that states what kind of
discussion is and isn't on topic.

I will consider posting on StackOverflow but I've had some bad
experiences there in the past (overly-zealous anti-spam mechanisms
preventing me linking to references, preventing me from answering my
own question, etc).

-- 
Mark Raynsford | http://www.io7m.com



Re: Concatenating transforms to scale positions but not objects

2019-08-10 Thread Mark Raynsford
On 2019-08-06T19:11:42 +0100
Mark Raynsford  wrote:

> Hello!
> 
> I realize the subject is somewhat convoluted. I'm putting together
> something that bears a passing resemblance to a DAW such as Ardour:

Given the tumbleweeds and sounds of crickets, I'm guessing that I
expressed my question rather poorly.

Here's what I'm trying to do: I'm trying to set up a pane with a
transform such that I can place objects inside that pane using
positions that don't correspond to JavaFX "scene pixels". For example,
1024 units in my coordinate system might correspond to 1 "scene pixel"
(is there a better name for the units that JavaFX uses?). However: The
objects that are *inside* the objects that I add to the pane want to
work in "scene pixels" (for example; Labels seem to want to work in
pixel positions when rendering text).

Here's a GitHub gist that gives a short example of this:

https://gist.github.com/io7m/20b071e11da2dcd96896a43fad6df644

I create one container group (actually a Pane) that adds a transform
such that 1 unit == 32 pixels. I add objects to this container. Each
object I add has an *external* pane with a size and position specified
in units, and an *internal* pane that solely exists to invert the scale
of the transform of the *external* pane. Inside this *internal* pane, I
can add Labels and so on and these all render correctly.

I set up bindings between the transforms so that I can effectively
scale and pan the scene by adjusting the transform on the group
container. However: Something about this setup seems to be confusing
something inside JavaFX; the results I'm seeing onscreen don't seem to
match what JavaFX believes the bounds of various objects are. This
causes visual issues when I try to do things like set borders on
objects, and also seems to confuse ScenicView.

Here's a shot with the container group selected (looks correct):

https://ataxia.io7m.com/2019/08/10/view0.png

Here's a shot with the *external* pane of the bottom object selected:

https://ataxia.io7m.com/2019/08/10/view1.png

Note that, although the object actually renders onscreen as the right
size (one of the pale grey boxes), ScenicView seems to believe that the
object's bounds are 1x1: They *are* 1x1, but they're 1x1 when expressed
in my custom coordinate system, not in JavaFX "scene pixels".

Here's a shot with the *internal* pane of the bottom object selected:

https://ataxia.io7m.com/2019/08/10/view2.png

This looks correct in the sense that the bounds encompass the label and
nothing else.

Am I doing something wrong here? I can't tell if I'm basically abusing
transforms or not.

-- 
Mark Raynsford | http://www.io7m.com



Concatenating transforms to scale positions but not objects

2019-08-06 Thread Mark Raynsford
Hello!

I realize the subject is somewhat convoluted. I'm putting together
something that bears a passing resemblance to a DAW such as Ardour:

  https://rekkerd.org/img/201303/ardour3.png

Mine doesn't look like that, but the principle is basically the same: I
have regions (the blocks containing waveform images above) placed on a
timeline. The timeline is scalable on both axes independently; scaling
the timeline vertically gives you more space to work with when
adjusting automation curves (visible in the "Fader" lane above), and
scaling/translating the timeline horizontally allows you to move
forwards and backwards in time, and to focus more clearly on a
particular region of time. For the sake of simplicity, let's act as if
I have just a single timeline instead of the multiple stacked timelines
shown in that image.

My application expresses the positions of regions on the timeline in
terms of "ticks" (small units of time).  For the (obviously
JavaFX-based) GUI, I'd like to be able to specify a single
transform on the timeline view such that I can specify the coordinates
of region nodes in terms of ticks and the transform will determine
their onscreen pixel positions appropriately. This isn't too hard to
do; I can specify an x-axis scale such that 1 pixel = 128 ticks, and I
can then specify an x-axis translation in terms of ticks that will be
scaled appropriately for the screen. The problem then, however, is that
the the nodes within region nodes are also scaled up hugely; if I try
to put labels in the regions, the labels will appear 128 times larger
than they normally would. :)

I want to specify the *positions* of regions in one coordinate system,
but work in ordinary "scene pixels" inside those regions.

I can't quite work out how to express the transforms I need to JavaFX.
I feel like what I need to do is, for each region node, add *another*
node inside the node that fills the region entirely, and specify an
inverse of the transform applied to the parent region node... If that
makes any sense.

Is there a sensible way to do what I'm trying to do?

[I've developed a 3D renderer, so I'm familiar with how transforms are
concatenated using matrices. I don't have an intuitive understanding of
how transforms are applied inside JavaFX, and there doesn't appear
to be much documentation on this.]

-- 
Mark Raynsford | http://www.io7m.com



Re: Some visual issues with a test application

2018-10-14 Thread Mark Raynsford
On 2018-10-14T21:22:23 +0100
Mark Raynsford  wrote:

> Hello!
> 
> I've been developing with Swing for many years, and I'm just now giving
> JavaFX a serious look now that the distribution issues are fixed
> (packages on Maven Central and the like).

Forgot to mention:

$ uname -a
Linux almond.int.arc7.info 4.18.12-arch1-1-ARCH #1 SMP PREEMPT Thu Oct
4 01:01:27 UTC 2018 x86_64 GNU/Linux

$ java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

-- 
Mark Raynsford | http://www.io7m.com



Some visual issues with a test application

2018-10-14 Thread Mark Raynsford
Hello!

I've been developing with Swing for many years, and I'm just now giving
JavaFX a serious look now that the distribution issues are fixed
(packages on Maven Central and the like).

I've run into a couple of odd issues and I'm not sure that either of
them are my fault.

I've been putting together a little API and GUI application for
browsing OSGi repositories:

  https://github.com/io7m/osgibrowse

I've recorded the issues here:

  http://ataxia.io7m.com/2018/10/14/javafx.mp4

You may notice that things look a little odd in that all windows appear
to be fullscreen. This is because I'm using a tiling window manager
(i3). Historically, Swing had a bit of trouble with this sort of window
manager. I'm not sure if JavaFX also does.

The first issue: The menu bar I created seems to behave erratically.
Sometimes I can click on the menu to open it, other times it flashes
open and then immediately closes. In both cases, the menu seems to be
detached from the menu bar (there's a gap between the menu and the bar).

The menu is created here and added to a BorderPane:

  
https://github.com/io7m/osgibrowse/blob/develop/com.io7m.osgibrowse.gui.javafx/src/main/java/com/io7m/osgibrowse/gui/javafx/OBBrowserWindow.java#L30

The second issue: Icons set on TreeItem values seem to be corrupted
when the TreeTableView containing them is scrolled. You can see this
happen in the video. The table in question is populated from an
immutable snapshot of data returned by the underlying repository API.
Once a repository is added, the table is populated once and then does
not change until the user adds another repository.

Double clicking on a row "selects" a bundle from the repository
and this triggers a refresh of the table view. When I scroll up and
down, it seems like icon views are incorrectly reused from other rows.

The entirety of the table configuration happens here:

  
https://github.com/io7m/osgibrowse/blob/develop/com.io7m.osgibrowse.gui.javafx/src/main/java/com/io7m/osgibrowse/gui/javafx/OBTableView.java#L188

Icons are set on the tree table nodes here:

  
https://github.com/io7m/osgibrowse/blob/develop/com.io7m.osgibrowse.gui.javafx/src/main/java/com/io7m/osgibrowse/gui/javafx/OBTableView.java#L92

Any advice would be appreciated. "YOU ARE NOT USING THE API CORRECTLY"
criticism is also welcome.

-- 
Mark Raynsford | http://www.io7m.com



Re: Error: JavaFX runtime components are missing, and are required to run this application

2018-10-13 Thread Mark Raynsford
On 2018-10-13T19:46:34 +0200
Johan Vos  wrote:
>
> There are some workarounds (e.g. you can have a Main class that doesn't
> extend Application that calls your Application), but the best approach is
> go modular, as explained here:
> https://stackoverflow.com/questions/52467561/intellij-cant-recognize-javafx-11-with-openjdk-11/52470141#52470141
> 

The following appears to work: Given an unsurprising subclass of
Application:

public final class ExampleApplication extends Application
{
  private static final Logger LOG =
Logger.getLogger(ExampleApplication.class.getCanonicalName());

  public ExampleApplication()
  {

  }

  @Override
  public void start(
final Stage stage)
  {
LOG.info("started");

final Button button = new Button();
button.setText("Click");

final BorderPane pane = new BorderPane();
pane.setCenter(button);

final Scene scene = new Scene(pane, 640.0, 480.0);
stage.setScene(scene);
stage.setTitle("Example");
stage.show();
  }
}

Then a main method that passes a class reference rather than allowing
the launcher to reflectively find the application:

public final class Main
{
  private Main()
  {

  }

  public static void main(
final String[] args)
  {
/*
 * Non-modular applications must specify the application class explicitly 
rather
 * than allowing the launcher to use reflection to try to instantiate and 
start
 * an application.
 */

Application.launch(ExampleApplication.class, args);
  }
}

The application starts up and runs without issue.

-- 
Mark Raynsford | http://www.io7m.com



Re: Error: JavaFX runtime components are missing, and are required to run this application

2018-10-13 Thread Mark Raynsford
On 2018-10-13T19:46:34 +0200
Johan Vos  wrote:

> The Java launcher (in the Java 11 JDK) checks if your main class extends
> Application, and in that case it checks the module path and tries to find
> javafx.graphics module. If you have that module on the classpath, but not
> as a module, the launcher will exit with the message you see.
> 
> There are some workarounds (e.g. you can have a Main class that doesn't
> extend Application that calls your Application), but the best approach is
> go modular, as explained here:
> https://stackoverflow.com/questions/52467561/intellij-cant-recognize-javafx-11-with-openjdk-11/52470141#52470141

Ah, ok, thanks!

I'm an OSGi user and although the vast majority of the library code I
write is JPMS modularized, the application code I write almost
certainly won't ever be (because I use OSGi rather than the JPMS).

I'm fine with not extending Application - in fact I won't even have the
option to do so because OSGi applications don't have that traditional
main() method.

Is there documentation somewhere on the workaround you mentioned?

-- 
Mark Raynsford | http://www.io7m.com



Error: JavaFX runtime components are missing, and are required to run this application

2018-10-13 Thread Mark Raynsford
Hello!

Now that Java 11 is at general availability, I decided to give OpenJFX
11 a shot today. Unfortunately, I encountered the above error with an
extremely trivial example project:

Error: JavaFX runtime components are missing, and are required to run
this application

The Maven project setup I'm using is here:

  https://github.com/io7m/javafxhello

$ java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

$ mvn --version
Apache Maven 3.5.4 (NON-CANONICAL_2018-09-08T01:02:16+02:00_root;
2018-09-08T00:02:16+01:00) Maven home: /opt/maven
Java version: 11, vendor: Oracle Corporation,
runtime: /usr/lib/jvm/jdk-11 Default locale: en_GB, platform encoding:
UTF-8 OS name: "linux", version: "4.18.12-arch1-1-arch", arch: "amd64",
family: "unix"

If I try to run the program from the IDE (Intellij), the exact command
line used is:

$ /usr/lib/jvm/jdk-11/bin/java
  -javaagent:/usr/share/idea/lib/idea_rt.jar=34729:/usr/share/idea/bin \
  -Dfile.encoding=UTF-8 \
  -classpath 
/home/rm/doc/dev/2018/10/javafxhello/target/classes:/home/rm/var/maven/org/openjfx/javafx-controls/11/javafx-controls-11.jar:/home/rm/var/maven/org/openjfx/javafx-controls/11/javafx-controls-11-linux.jar:/home/rm/var/maven/org/openjfx/javafx-graphics/11/javafx-graphics-11.jar:/home/rm/var/maven/org/openjfx/javafx-graphics/11/javafx-graphics-11-linux.jar:/home/rm/var/maven/org/openjfx/javafx-base/11/javafx-base-11.jar:/home/rm/var/maven/org/openjfx/javafx-base/11/javafx-base-11-linux.jar
  com.io7m.javafxhello.Main

Am I doing something wrong? I feel like I've set things up the same way
as shown in the documentation.

-- 
Mark Raynsford | http://www.io7m.com



Re: OpenJFX 11 in OSGi

2018-08-07 Thread Mark Raynsford
On 2018-08-07T14:22:10 +0200
Tom Schindl  wrote:

> Hi,
> 
> For those not following my blog [1]. We've managed to successfully run
> OpenJFX-11 modules inside Equinox using the same approach we've already
> supplied for FXCanvas. We "simply" spin up a new Module-Layer containing
> the JavaFX-bits.
> 

Nice work. I kept an eye on the GitHub ticket you (I think it was you,
apologies if it wasn't!) filed a while back to track this. I never did
find a decent solution, so I'm glad you came up with something.

Is this applicable to Felix? It seems like it might use
Equinox-specific facilities.

-- 
Mark Raynsford | http://www.io7m.com



Re: Simple Maven example fails with unusual error

2018-07-23 Thread Mark Raynsford
On 2018-07-23T17:22:34 +0200
Johan Vos  wrote:

> Hi Mark,
> 
> So it seems these issues are not OpenJFX specific, and more projects will
> run into this?
> I'm a bit worried about the grey zone between OpenJDK and Maven/Gradle...
> @Kevin are you aware of someone from the jigsaw team who is working in this
> zone? Alan Bateman?

Depends on which of the two errors you're referring to. The one
regarding the version number is not strictly OpenJFX specific, it's
just that OpenJFX happened to pick a version number format that the JVM
doesn't like.

The issue relating to the compiler raising an
IllegalArgumentException... I have no idea who's fault that is. I've
been working with a lot of modular projects for over a year and only
saw anything similar to this error when working with old versions of
the compiler plugin (and those were fixed). Those issues were strictly
down to an embedded version of ASM (pre 6.1) that didn't support the
newer bytecode format. None of the ~70 or so modular projects I
currently compile have this problem (both projects that are themselves
modular, and have dependencies on the module path).

I'm a little mystified as to why it's shown up today at all, given that
it didn't when I initially posted to the list. I can reproduce the
issue on Travis CI:

  https://travis-ci.org/io7m/javafx-example-20180721/builds/407068017

... so it doesn't appear to be my environment that's broken (or at
least it's not *just* mine!)

-- 
Mark Raynsford | http://www.io7m.com



Re: Simple Maven example fails with unusual error

2018-07-23 Thread Mark Raynsford
On 2018-07-23T10:49:29 +0100
Paul Ray Russell  wrote:

> Mark,
> 
> I do find the following:
> https://github.com/eclipse/jetty.project/issues/2397 - and I notice in your
> POM you're using an annotation processor path.

Removed that. Same error, unfortunately.

I feel like we may be looking at two separate issues here. One appears
to be that the non-platform-specific artifacts are named such that the
JVM attempts to derive an automatic module name from them and can't due
to the structure of the version number. The other issue appears to be
some sort of compiler bug.

There's a new release of the compiler plugin due out soon that I hope
might fix the latter, but I think the former is going to require a
version number format change - it's not possible to get around the fact
that Maven is going to name the jar files a certain way on disk, and
that the JVM doesn't like what it names them.

-- 
Mark Raynsford | http://www.io7m.com



Re: Simple Maven example fails with unusual error

2018-07-23 Thread Mark Raynsford
eModuleBuilder.buildProject 
(LifecycleModuleBuilder.java:81)
at 
org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build
 (SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute 
(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:309)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:194)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:107)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:955)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke 
(NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke 
(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced 
(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch 
(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode 
(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main 
(Launcher.java:356)
Caused by: java.lang.IllegalArgumentException
at org.objectweb.asm.ClassReader. (Unknown Source)
at org.objectweb.asm.ClassReader. (Unknown Source)
at org.objectweb.asm.ClassReader. (Unknown Source)
at org.codehaus.plexus.languages.java.jpms.AsmModuleInfoParser.parse 
(AsmModuleInfoParser.java:80)
at 
org.codehaus.plexus.languages.java.jpms.AsmModuleInfoParser.getModuleDescriptor 
(AsmModuleInfoParser.java:65)
at org.codehaus.plexus.languages.java.jpms.LocationManager.resolvePaths 
(LocationManager.java:113)
at org.apache.maven.plugin.compiler.CompilerMojo.preparePaths 
(CompilerMojo.java:219)
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute 
(AbstractCompilerMojo.java:762)
at org.apache.maven.plugin.compiler.CompilerMojo.execute 
(CompilerMojo.java:168)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo 
(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute 
(MojoExecutor.java:208)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute 
(MojoExecutor.java:154)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute 
(MojoExecutor.java:146)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject 
(LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject 
(LifecycleModuleBuilder.java:81)
at 
org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build
 (SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute 
(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:309)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:194)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:107)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:955)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke 
(NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke 
(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced 
(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch 
(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode 
(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main 
(Launcher.java:356)
[ERROR] 
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please 
read the following articles:
[ERROR] [Help 1] 
http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException

The last time I saw an exception like this related to
org.objectweb.asm.ClassReader, it was due to incompatible bytecode
(when Java 9 was released, most tools weren't yet compatible with Java
9 bytecode).

-- 
Mark Raynsford | http://www.io7m.com



Re: Simple Maven example fails with unusual error

2018-07-21 Thread Mark Raynsford
On 2018-07-21T15:55:15 +0100
Mark Raynsford  wrote:
>
> Is this a known issue?

Forgot to mention:

$ java -version
openjdk version "10.0.1" 2018-04-17
OpenJDK Runtime Environment (build 10.0.1+10)
OpenJDK 64-Bit Server VM (build 10.0.1+10, mixed mode)

$ uname -a
Linux almond.int.arc7.info 4.17.5-1-ARCH #1 SMP PREEMPT Sun Jul 8
17:27:31 UTC 2018 x86_64 GNU/Linux

$ mvn --version
Apache Maven 3.5.2 (NON-CANONICAL_2017-10-25T13:09:52+03:00_root;
2017-10-25T11:09:52+01:00) Maven home: /opt/maven
Java version: 10.0.1, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-10-openjdk
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.17.5-1-arch", arch: "amd64", family:
"unix"


-- 
Mark Raynsford | http://www.io7m.com



Simple Maven example fails with unusual error

2018-07-21 Thread Mark Raynsford
Hello!

I've finally gotten around to trying out the artifacts that are
currently on Maven Central.

I put together a trivial example that does nothing but start up
OpenJFX:

  https://github.com/io7m/javafx-example-20180721

It works, but only if I take the somewhat bizarre step of excluding the
non-platform-specific artifacts from the build. Note the 
elements in the Maven dependencies.

The error I get if I don't do this:

java.lang.module.FindException: Unable to derive module descriptor
for 
/home/rm/var/maven/org/openjfx/javafx-graphics/11-ea+19/javafx-graphics-11-ea+19.jar
Caused by: java.lang.IllegalArgumentException:
javafx.graphics.11.ea.19: Invalid module name: '11' is not a Java
identifier

Is this a known issue?

-- 
Mark Raynsford | http://www.io7m.com



Re: modules versus SDK's

2018-03-26 Thread Mark Raynsford
On 2018-03-26T11:28:44 +
Mario Ivankovits <ma...@datenwort.at> wrote:

> +1 on providing JavaFX as „simple“ dependency.
> 
> Question is how to deal with the native libraries. Provide an artifact per 
> platform?

Take a look at how LWJGL handles it:

  http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.lwjgl%22

We repack those artifacts into OSGi bundles in an automated fashion too:

  https://github.com/LWJGL/lwjgl3-osgi

-- 
Mark Raynsford | http://www.io7m.com



Re: Update on enabling JavaFX to work with OpenJDK builds

2018-02-27 Thread Mark Raynsford
On 2018-02-27T13:21:56 -0800
Kevin Rushforth <kevin.rushfo...@oracle.com> wrote:
>
> In an earlier email with the subject "javafx might not be present" [1], 
> I mentioned our intention to make it easier for OpenJFX to be built, 
> tested, and run with OpenJDK builds that don't already contain javafx.* 
> modules. This will pave the way to allow a set of pre-built javafx 
> modules to be distributed that will run on top of a pre-built OpenJDK.
> 
> By way of update, this work is underway and can be tracked via the 
> following two JBS issues:

This is good to hear, thank you!

I'll keep an eye on this as it unfolds.

-- 
Mark Raynsford | http://www.io7m.com



Re: The "javafx might not be present" problem

2018-02-09 Thread Mark Raynsford
On 2018-02-09T10:28:56 -0800
John Neffenger <j...@status6.com> wrote:
>
> I reported the bug below to fix this same issue for Ubuntu:
> 
> JavaFX support is in Oracle JDK 9 but missing in Ubuntu OpenJDK 9
> https://bugs.launchpad.net/ubuntu/+source/openjdk-9/+bug/1721852
> 
> You can comment there if you're interested in seeing support for JavaFX 
> be part of the default installation of OpenJDK 9 or 10 on Ubuntu. I'm 
> hoping it can get included in time for the next Long Term Support 
> release of Ubuntu 18.04 in April.

I'll be commenting there as I would like to see it fixed. I'd like to
reiterate though that it doesn't solve the problem of:

  * Depending on OpenJFX from library code: You can't specify a
dependency on OpenJFX because it doesn't have Maven coordinates.
OpenJFX occupies a grey area where it's sort of part of the JDK
and sort of not.

  * Using OpenJFX from an application that hasn't been processed
with jlink and is using Java 9 modules: You can't check
reflectively for the existence of JavaFX without mentioning
it in the module system.

The above ticket just reduces the number of places where JavaFX might
not be present by one. I'd prefer a more general solution to this
problem. I am volunteering to help if there's any way that I can help.

-- 
Mark Raynsford | http://www.io7m.com



Re: The "javafx might not be present" problem

2018-02-09 Thread Mark Raynsford
On 2018-02-09T14:49:23 +0100
Mario Torre <neug...@redhat.com> wrote:
>
> JavaFX is not part of the Java specifications for the JDK or its
> runtime, so the presence of the library in any distribution of OpenJDK
> pretty much depends on the vendor distributing you the binaries.

Ah, my mistake then. I thought it actually was part of SE now.

I think I originally misread:

"Starting with Java SE 7 Update 6, JavaFX is part of Oracle's Java SE
implementation."

  https://www.java.com/en/javafx/

I misread that as "Starting with Java SE 7 Update 6, JavaFX is part of
Oracle's Java SE specification."

-- 
Mark Raynsford | http://www.io7m.com



Re: The "javafx might not be present" problem

2018-02-09 Thread Mark Raynsford
On 2018-02-09T13:44:55 +
Johan Vos <johan@gluonhq.com> wrote:

> Hi Mark,
> 
> Is using jlink (https://docs.oracle.com/javase/9/tools/jlink.htm) packaging
> your app with the exact set of modules you need an option for you?
> That would eliminate the need for your users to have Java installed. Not
> only there is a (small) hurdle to install Java, but it needs to be the
> "correct" version of Java as well, and you would probably expect your users
> to update their JDK with security updates etc.
> 
> I've been a long-time fan of the javapackager, and now that jlink allows
> you to create a custom runtime image, I think we have much better solutions
> than relying on the fact that an end-user installed an ok version of the
> JDK?
> 
> But maybe I'm missing something, and is jlink not an option for you?

'Ello.

Oh, it's certainly an option for applications - if you're willing to
distribute separate platform-specific downloads for each platform. To
date, I've not offered platform-specific downloads for any
applications: Why would I when I can give all users the same
platform-independent jar file?

I'm still investigating coming up with a way to use (or possibly abuse)
jlink to produce a multi-platform distribution so that I still only
offer one single download for all platforms (with some magic scripts or
wrappers that execute the correct included JRE for the platform).

For libraries, it's obviously no help. For libraries, I'd need either a
guarantee that OpenJFX is present wherever a particular version of Java
is, or I'd need Maven coordinates so that the library can specify an
accurate (and automatically resolvable) dependency on JavaFX.

Personally, if a library isn't present on Maven Central, then I don't
even consider depending on it. Being deployed to Maven Central is, for
me, a basic indicator that the project in question is competently
maintained. OpenJFX has elevated status in this regard in that it's not
on Maven Central but I would still consider depending on it if
distribution issues could be solved.

-- 
Mark Raynsford | http://www.io7m.com



The "javafx might not be present" problem

2018-02-09 Thread Mark Raynsford
Hello!

I've been using Swing for many years. One of the things I like most
about it is that it's essentially guaranteed to be present in any Java
SE installation, and although it's a little outdated aesthetically, it
works well and continues to work well.

I've been exploring the possibility of migrating to JavaFX on and off,
but the biggest showstopper for me is that JavaFX may not actually be
present in any given user's installation. If someone installs the
jre9-openjdk package on Arch Linux, for example, they don't get JavaFX.
If they install the java-openjfx package, they do (although Arch only
offers JavaFX 8 right now).

I'm migrating to Java 9 modules, and all new projects will be fully
modular projects. In the olden days (pre Java 9), it was possible to
detect if JavaFX was present with a reflection hack:

try {
  Class jfxPanel = classLoader.loadClass("javafx.embed.swing.JFXPanel");
  isJavaFxAvailable = true;
} catch (ClassNotFoundException e) {
  isJavaFxAvailable = false;
}

The idea being that you could at least display a friendly error message
to the user explaining that they need to install JavaFX if they're
using OpenJDK.

But obviously in a Java 9 project, that's not going to work: You'd need
to specify a "requires" clause on the JavaFX modules, and if they
weren't present, the VM wouldn't even start up so the above check
wouldn't get a chance to run.

For applications, I could probably try to bundle JavaFX with them
(although there may be licensing issues there). For libraries, I'm out
of luck. The only apparent option there is for me to pick a set of
Maven coordinates like "org.openjdk:javafx:8.0" and specify those in my
libary's POM file (and assume that the user is smart enough to deploy
JavaFX to a local repos to use it).

I suppose what I'm really saying is: When (if ever) can I expect JavaFX
to be present unconditionally with OpenJDK installs? I probably can't
migrate to JavaFX until that day...

-- 
Mark Raynsford | http://www.io7m.com