This project is designed to add some basic features to JavaFXPorts and handles a lot of platform specific code just to make your life easier.
The project only makes sense to use if you use Gluon to create JavaFX apps! This implies that this project depends on Gluon.
This project is compiled with Gluon Version: 3.0.0
Any non backward compatible changes in a newer Gluon version may or may not break this project.
- platform-specific logging
- Intent support on Desktop and Android (iOS might come in future)
- ViewHandler for (automatically) switching between Views
- Orientation and Size Listener for responsive Layout
- fine touch (1px) for android
- Loading screen (right now waits for one second for demonstration purposes)
- create/open a Gluon Project
- add this project as a dependency
- change a little bit of your code to make it use this project
This should be easy :D
Add these lines to your dependencies section in your build.gradle
:
compile 'com.zeiss.quarkfx:QuarkFX-Main:1.0.0-alpha'
desktopRuntime 'com.zeiss.quarkfx:QuarkFX-Desktop:1.0.0-alpha'
androidRuntime 'com.zeiss.quarkfx:QuarkFX-Android:1.0.0-alpha'
iosRuntime 'com.zeiss.quarkfx:QuarkFX-Ios:1.0.0-alpha'
! To use Desktop Intents you need to create a runnable Jar and make sure also the desktop-specific dependencies are compiled !
Example using the javafx-gradle-plugin:
apply plugin: 'javafx-gradle-plugin'
jfx {
//minimal configuration
verbose = true
mainClass = "{package.to.gluon.class.MainClass}"
jfxAppOutputDir = "build/jfx/app"
jfxMainAppJarName = "{OutputJarName.jar}"
deployDir = "src/gluon/deploy"
}
jfxJar.doFirst {
//for now manually add (there might be a better way)
println("adding desktop dependency")
project.dependencies.add("runtime", "com.gluonhq:charm-desktop:3.0.0")
project.dependencies.add("runtime", 'com.zeiss.quarkfx:QuarkFX-Desktop:1.0.0-alpha')
}
To make this Project work you have to pipe the basic JavaFX methods through the QuarkFXApplication
//Extend QuarkFXApplication and the rest is self explanatory
public abstract class YourMainClass extends QuarkFXApplication {
//IMPORTANT change the init method to this: (you can use the viewhandler to initialize your views)
@Override
public void initApp(ViewHandler viewmanager){
//initialize your Views here (with the ViewHandler - explained below)
}
//IMPORTANT change the postInit method to this:
@Override
public void postInitApp(Scene scene){
//post init stuff here
}
//IMPORTANT change your stop method (if you have one) to this
@Override
public void stopApp(){
//javafx's stop method (called when application closes)
}
//called when this app was launched via intent
@Override
public void handleIntent(IntentP intent){
//handle this intent please (intent is not null)
}
}
To log some stuff:
Log.verbose(CurrentClass.class.getSimpleName(), "Message");
Log.debug(CurrentClass.class.getSimpleName(), "Message");
Log.info(CurrentClass.class.getSimpleName(), "Message");
Log.warning(CurrentClass.class.getSimpleName(), "Message");
Log.error(CurrentClass.class.getSimpleName(), "Message");
Log.exception(CurrentClass.class.getSimpleName(), "Message", throwable);
Log.log("myTag", "Message", LogLevel.error);
Get and set the LogLevel cap (verbose<debug<info<warning<error):
LogLevel level = Log.getMinimumLogLevel();
Log.setMinimumLogLevel(level);
Only messages with a higher priority will be logged.
The ViewHandler works a little bit different than the one implemented in Gluon. You have three steps
- register your View-Packages (a package of all views for the different orientations and sizes)
- set the HomeView (the first view to switch to after the loading screen)
- switch Views whenever you like
A View Package is defined over the IViewPackage
Interface.
A View Package defines its children depending on the Layout.
A child has to implement IView
.
Here is a code example:
public class SomeViewPackage implements IViewPackage {
//the unique ID like in Gluon (but there is no predefined HOME_VIEW any more)
public static final String ID = "SomeViewPackage";
//with this method you define when which View is shown (depending on current Screen orientation and size)
@Override
public Class<? extends FXMLView> getView(OrientationListener.Size size, OrientationListener.Orientation orientation) {
switch (orientation)
{
case LANDSCAPE:
switch (size)
{
case NORMAL: return NormalLandscapeView.class;
case XLARGE: return XLargeLandscapeView.class;
}
break;
case PORTRAIT:
switch (size)
{
case NORMAL: return NormalPortraitView.class;
case XLARGE: return XLargePortraitView.class;
}
break;
}
//this tells the viewhandler to fallback to the defaults
return null;
}
//returns the unique ID for this package
@Override
public String getID() {
return ID;
}
//The default Orientation when a View was not found
@Override
public OrientationListener.Orientation getDefaultOrientation() {
return OrientationListener.Orientation.PORTRAIT;
}
//The default Size when a View was not found
@Override
public OrientationListener.Size getDefaultSize() {
return OrientationListener.Size.NORMAL;
}
}
Example View using AfterburnerFX:
public class NormalLandscapeView extends FXMLView implements IView{
//nothing here because Afterburner :D
}
Example initApp method
@Override
public void initApp(ViewHandler viewmanager){
viewmanager.registerView(new SomeViewPackage1());
viewmanager.registerView(new SomeViewPackage2());
viewmanager.setHomeView(SomeViewPackage1.ID); //this explains the static variable in SomeViewPackage
//That's it
}
View-Switching works like this:
viewManager.switchView(SomeViewPackage2.ID, ViewStackPolicy.USE);
Currently doesn't support sending/retrieving Custom URL Schemes (Intents) on iOS.
//create a platform-independant Intent (that's where the 'P' comes from)
IntentP intent = new IntentP();
//Use it like a normal android intent
intent.setAction("ACTION_VIEW");
intent.setData("http://google.com");
//in future not necessary (fix for desktop)
intent.setMimeType("html/html");
//optional (for explicit intents only)
intent.setReceiverMainClass("package.to.Main.class.of.app.MainClass");
//send it via the native service
QuarkFXApplication.getInstance().getNativePlatform().getNativeService().sendIntent(intent);
In the class that extends QuarkFXApplication just implement the method public void handleIntent(IntentP intent){ }
and do whatever you want with it.
Next up, you have to tell Android that you want to receive an intent (Like it is done in "real Android"):
AndroidManifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest ... >
...
<application ... >
<activity ... >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<!-- specify the categories you want to listen on here -->
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
</application>
</manifest>
And finally the same for the Desktop:
DesktopManifest.json (yes its a json, because it's just easier :D)
{
"label": "{Application Name}",
"version": "{Application Version}",
"description": "{Application Description}",
"iconPath": "path/to/logo.png",
"intentfilters": [
{
"action": "MAIN",
"categories": [
"LAUNCHER"
]
},
{
"data": "*/*",
"action": "SEND",
"categories": [
"DEFAULT"
]
}
]
}
- Java / JavaFX
- GluonHQ (+ JavaFXPorts)
This software uses the 3-clause BSD license. See the accompanying LICENSE file for more details or download it here (https://opensource.org/licenses/BSD-3-Clause).
Copyright (c) 2016 Carl Zeiss Meditec AG