Skip to content

Latest commit

 

History

History
188 lines (145 loc) · 5.73 KB

README.md

File metadata and controls

188 lines (145 loc) · 5.73 KB

UpFX

I created this tool to help in developement using JavaFX allowing CDI and other features.

How to use it:

  • Using Intellij, you can create a new JavaFX project;
  • Then you can add maven support;
  • In the resources folder, add the folder META-INF, and inside it, the beans.xml file. This will allow CDI.
  • Put the .fxml files inside resources folder. Personally I create views folder and put inside it.
  • In pom.xml you can import via dependency.

First Steps:

Creating the Main Class:

  • First extends FxMain in your Main class;
  • Import Result from com.upfx.result.Result via injection;
  • Call initiate method passing the Main class
  • With result you can call render method with the fxml location and the title
<dependency>
    <groupId>com.github.kaundev.upfx</groupId>
    <artifactId>upfx-core</artifactId>
    <version>1.0.2</version>
</dependency>
public class Main extends FxMain {

    @Inject
    private Result result;

    public static void main(String[] args) {
        initiate(Main.class, args);
    }

    @Override
    protected void firstScreen() {
        result.render("/views/sample.fxml", "My first ice screen");
    }
}

Controllers

  • Just extends Controller from com.upfx.controller.Controller;
  • There is no need to implement the initialize JavaFX method, the Controller super class already does that. Location and resouceBundle will be accessed via instance field;
  • Instead of "initialize" method, this tool offers another method: initiate (not very creative, sorry). This method can receive parameters and will be called when you use result to navigate;
public class MainController extends Controller {

    public void initiate(){
        ResourceBundle resourceBundle = this.resourceBundle;
        URL location = this.location;
    }
}

Navigation

Rendering

- result method from the example above receives a string url of .fxml file, string title of the page and others parameters that you can pass through controllers. See the example:
String path = "/views/show_message.fxml"
String title = "Show parameters"
String parameter1 = "This is a parameter being passed"
String yetAnotherParameter = "Yes, I can receive as much parameters your controller needs"

result.render(path, title, parameter1, yetAnotherParameter);
  • In the controller being called you can do
public void initiate(String parameter1, String yetAnotherParameter){
    System.out.println(parameter1);
    System.out.println(yetAnotherParameter);
}

getPane

The render method will render another screen in your project, but if you want to change a specific element of your screen you can call "getPane". getPane doesn't receives the title, but you can pass as much parameters you need. getPane also returns the controller that you are calling. Use getRoot() method to render in the element.
PaneController paneController = result.getPane("/views/lessons/studentCard.fxml", "A parameter");
this.changeblePane.getChildren().add(paneController.getRoot());

Popup

Also you can create popups, passing .fxml location, the title and other parameters you need.
public void popupNoPermission(){
    result.openPopup("/views/users/noPermission.fxml", "No permission");
}

For code organization, I recomend creating a Routes class and putting all the routes inside it.

Security

  • First create an anotation that represents the existing rules. In this example SecurityType is an Enum.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SecurityTypeRule {
    SecurityType type();
}
  • Then, create an Handler if the user doenst have permission:
public class AuthenticationSecurityHandler extends SecurityHandler{

    private Routes routes;

    @Inject
    public AuthenticationSecurityHandler(Routes routes) {
        this.routes = routes;
    }

    @Override
    public void handle(InvocationContext invocationContext) {
        routes.popupNoPermission();
    }
}
  • Then, create the Rule class implemeting SecurityRule;
  • Annotate the class with @Handler passing the handler you created
  • To perform the security create "isAllowed" method return a boolean. This method receives an AnnotatedElement that can be a class or an method. From annotatedElement you can retreive the annotation created.
@Handler(AuthenticationSecurityHandler.class)
public class DefaultRule implements SecurityRule {

    private LoggedUser loggedUser;

    @Inject
    public DefaultRule(LoggedUser loggedUser) {
        this.loggedUser = loggedUser;
    }

    public boolean isAllowed(AnnotatedElement annotatedElement) {
        SecurityTypeRule securityTypeRule = annotatedElement.getAnnotation(SecurityTypeRule.class);
        return loggedUserHasPermission(securityTypeRule.type)
    }
}
  • For Controller classes, just call Class security Annotation passing the ClassRule
@ClassSecurity(value = DefaultRule.class) @SecurityTypeRule(type =  SecurityType.list_student)
public class MySecurityController extends Controller{
    ...
}
  • For methods, call MethodSecurity annotation passing the ClassRule
@FXML @MethodSecurity(value = DefaultRule.class) @SecurityTypeRule(type = SecurityType.create_admin)
protected void addAdmin(){
    routes.newAdministrator();
}

Multi language from ResourceBundle

- The only thing to do is create a producer method passing the location of the properties file, like: "Bundle_pt_BR.properties" inside META-INF/locales/Bundle_pt_BR.properties
public class ResourceBundleProducer {

    @Produces
    public ResourceBundle produceResourceBundle() {
        return ResourceBundle.getBundle("META-INF/Bundle", new Locale("pt", "BR"));
    }
}