ClassLauncher: do not forget previous classpath additions

We want to re-use a ClassLoaderPlus if we created one previously,
not forget about it, when adding new elements to the class path.

The code used to work only because the default class loader is a
URLClassLoader and we play reflection games to access its addURL()
method.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
StderrLogService: prefix messages appropriately

This prefixes message with [INFO] and similar prefixes. It also
refactors the class a bit.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
StderrLogService: prefix exceptions appropriately, too

This prefixes the header line of stack traces with [INFO] and similar
prefixes. It also opens the door to showing the exceptions' causes,
if any, without violating the DRY principle.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
StderrLogService: log causes of exceptions, too

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ServiceHelper: fall back to stderr when there is no LogService yet

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Access ImageJ 1.x classes directly from the legacy service

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyPluginFinder: allow it to operate in its own class loader

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Code Hacker: require a class loader in which to define the classes

This opens the door to have multiple LegacyServices, each with their
own class loader, in which the ImageJ 1.x classes and the classes
using them are defined.

This is necessary because ij.IJ is basically a singleton but still has
to be connected to the appropriate ImageJ context and LegacyService. By
having a separate class loader for each LegacyService, ij.IJ can be
a singleton *in that class loader*, and things will still work out.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Failed try: load most of the LegacyService into its own class loader

This would have been so cool: by having an own class loader for each
LegacyService instance, we would have let ImageJ 1.x continue to pretend
that it is a singleton, but it would not really have been.

Alas, it is not to be. If we were to do that, nobody could instantiate an
ImagePlus *except* in classes loaded by those class loaders, which would
have been unintuitive and fragile.

So we have to undo this change, recording for history that we tried.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyImageMap: offer the list of handled images

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add the method ApplicationFrame#setVisible(boolean)

LegacyService's toggleLegacyMode() will use this method.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
SwingImageWindow: avoid pack() when hiding the window

This is needed for the upcoming Help>Legacy Mode, which would otherwise
experience an 'IllegalStateException: Cannot sync viewport from thread'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
CodeHacker: remove unused replaceMethod() method

For the legacy mode, we should avoid replacing methods in every case,
so we will not need this method anymore, ever.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
WIP: Introduce a legacy mode to the LegacyService

To fall back to original ImageJ1 (e.g. should some plugin or macro not
work in ImageJ2 as it did in ImageJ1), we'd like to be able to drive a
patched ImageJ1 in such a way that it behaves exactly like unpatched
ImageJ1 (except still synchronizing all the data with ImageJ2).

This change introduces a flag in the class LegacyService, and changes the
Javassist patches so that the legacy mode is heeded.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
WIP: Add Help>Start Legacy ImageJ 1.x Mode

Since it is very hard (or might be impossible) to achieve full 100%
backwards-compatibility with ImageJ1, we want to have one last way out for
users whose plugin/macro might not work in ImageJ2, namely to show the old
ImageJ1 GUI and lose all the ImageJ2 goodness.

This is what Help>Start Legacy ImageJ 1.x Mode does.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
WIP: Implement legacy mode's Help>Stop Legacy ImageJ 1.x Mode

When the tasks are finished in the legacy mode, we want to go back...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
WIP: make 'Ctrl+L Stop Legacy Mode' work in legacy mode

The big problem here is that we'd like to avoid introducing the
dependency on Swing, but ATM part of the code needs to be executed
on the EDT.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
HACK: WIP: Avoid showing IJ2 windows in legacy mode

We need to make this more robust before merging to 'master'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
WIP: Verify that two ImageJ contexts can have two different LegacyServices

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
to cherry-pick: DefaultLegacyService.isLegacyMode

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>