Wie lassen sich fremde Systembibliotheken in eine Cross-Plattform-Applikation einbinden?
Betrachten wir als Beispiel Apples MacOS X. Das Betriebssystem
stellt eine eigene Bibliothek bereit, um Java-Programme
vollständig in das System integrieren zu können.
Hierzu zählt z.B. der Aufruf des obligatorischen
Eigenschaften- oder Hilfe-Dialogs aus der oberen Desktop-Leiste
heraus. Diese Bibliothek ist auf anderen Betriebssystemen
natürlich nicht vorhanden, sodass
Cross-Plattform-Entwicklungen auf die Einbindung verzichten
müssten. Das würde zwar die Funktionalität nicht
beeinträchtigen, ließe jedoch die Homogenität
der Gesamt-Erscheinung vermissen. Um in deren Genuss zu kommen,
muss die Bibliothek beim Kompilieren natürlich im Klassenpfad
vorhanden sein.
Wie stellt man es nun an, diese Bibliothek
auf Quelltextebene einzubinden ohne zur Laufzeit auf anderen
Systemen eine Fehlermeldung zu erhalten?
Das prizipielle
Vorgehen wird im Abschnitt Strategy-Pattern
erläutert. Dem entsprechend wird eine Klasse MacImpl
deklariert, die einerseits Apples Pakete
com.apple.eawt.Application;
com.apple.eawt.ApplicationEvent;
com.apple.eawt.ApplicationListener;
einbindet, andererseits ein kleines Interface ClassSelector
implementiert. Es deklariert nur eine Methode handleOS()
.
Sie kann je nach Betriebssystem in unterschiedlichen Klassen
konkretisiert werden.
Die Methode handleOS()
erzeugt im vorliegenden Fall ein Application-Objekt, auf dem der
Reihe nach Methoden aufgerufen werden, um
- ein Dock-Icon darzustellen
- einen About-Menupunkt darzustellen
- einen Eigenschaften-Menupunkt zu erzeugen und darzustellen
- die Applikation beim Listener anzumelden
Die dann folgenden Methoden entstammen dem implementierten
Interface ApplicationListener
. Ihre Bezeichner sind
selbsterklärend und können mit beliebigen Routinen
realisiert werden.
Der "Witz" besteht jetzt
darin, dass in main()
durch die Zeile
System.getProperties().put("apple.laf.useScreenMenuBar", "true");
zunächst die Nutzung der Menuleiste angefordert wird. Das muss bereits an dieser Stelle erfolgen, um die vollständige Darstellung der Apple-Leiste zu gewährleisten. Da es sich hierbei lediglich um den Eintrag einer Systemeigenschaft handelt, wird auf anderen Betriebssystemen hierdurch kein Fehler erzeugt. In der Folge wird das Betriebssystem abgefragt und erst dann wird, je nach Ergebnis, die entsprechende Klasse aufgerufen. Das garantiert, dass nicht vorhandene Bibliotheken zur Laufzeit auch nicht benötigt werden.
import java.util.Properties;
import javax.swing.ImageIcon;
import com.apple.eawt.Application;
import com.apple.eawt.ApplicationEvent;
import com.apple.eawt.ApplicationListener;
import de.yourwebs.cent.CentGUI;
import de.yourwebs.cent.CentSplash;
import de.yourwebs.cent.Config;
import de.yourwebs.cent.dialogs.AboutDialog;
import de.yourwebs.cent.dialogs.options.OptionsDialog;
public class Cent {
public static void main(String[] args) {
System.getProperties().put("apple.laf.useScreenMenuBar", "true");
Cent cent = new Cent();
CentGUI.getCentGUI();
if (Config.getOS().equals("mac")) {
new MacImpl();
}
}
}
class MacImpl implements ClassSelector, ApplicationListener {
public MacImpl(){
handleOS();
}
@Override
public void handleOS() {
try {
final Application application = Application.getApplication();
application.setDockIconImage(new ImageIcon(ClassLoader.getSystemResource(Config.IMG_VERZ
+ Config.APP_NAME.toLowerCase() + "512.png")).getImage());
application.setEnabledAboutMenu(true);
application.addPreferencesMenuItem();
application.setEnabledPreferencesMenu(true);
application.addApplicationListener(this);
} catch (Throwable e) {
System.err.println("setupMacOSXApplicationListener failed: "
+ e.getMessage());
}
}
public void handleAbout(ApplicationEvent arg0) {
new AboutDialog(CentGUI.getCentGUI());
arg0.setHandled(true);
}
public void handleOpenApplication(ApplicationEvent arg0) {
}
public void handleOpenFile(ApplicationEvent arg0) {
}
public void handlePreferences(ApplicationEvent arg0) {
new OptionsDialog();
arg0.setHandled(true);
}
public void handlePrintFile(ApplicationEvent arg0) {
}
public void handleQuit(ApplicationEvent arg0) {
arg0.setHandled(true);
System.exit(0);
}
public void handleReOpenApplication(ApplicationEvent arg0) {
}
}
interface ClassSelector {
public void handleOS();
}
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.