e(fx)clipse 1.0 – New Features – Integration of JavaFX source and property JavaDoc

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

Integration of JavaFX source and property JavaDoc

JDT in Luna added an extension point e(fx)clipse makes use of to contribute the location of the JavaFX source code when the JRE System Library is initialized. The nice effect this has for developers is that they e.g. can debug through JavaFX source code without any manual configuration.

debug

Unfortunately adding the source produces a problem one does not notice when only the HTML-JavaDoc is attached to the JRE. The JavaFX team is lazy and does not JavaDoc all of the 3 Property-Methods (get*/set*/*Property) but does it only once and the JavaDoc-Tool has an UNDOCUMENTED switch to procude HTML-JavaDoc for all 2 of them.

Now that Eclipse has the source it would not have shown JavaDoc for the methods because it didn’t know about this secret JavaDoc-Feature. We contributed the needed magic to JDT and the JDT-Team accept and polished our contribution.

javadoc

If you look closely to the right you notice that there’s no JavaDoc on all those methods so without the fix in JDT you would have seen fairly no JavaDoc JavaFX-Property accessors.

Posted in e(fx)clipse | Tagged | 8 Comments

e(fx)clipse 1.0 – New Features – StyledText control to build a code editor (framework)

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

StyledText control to build a code editor (framework)

We’ve been experimenting with the new Text-API part of OpenJFX8 since its inception in the first weekly builds. In the 1.0 cycle we’ve moved the code from an external repository to e(fx)clipse and improved it adding support for:

  • Copy & Paste
  • Selection
  • Line numbers
  • use CSS for text-styles

The API is not yet complete and there are many many many features missing but you can already build really cool and fancy IDE like applications. The control still has some bugs but we decided to include the current version so that you can give it a spin and provide feedback or even contribute fixes, features, … .

This is a simple Java-Editor built with the StyledText-Control and the Eclipse-Text-Framework who does the paritioning, … of the sourcecode

java_default

and because all colors are not hard coded into the the UI nor set in preferences like in e.g. in Eclipse you can flip the theme and your editor will renderer in a dark theme like this (I used the same colors as IntelliJ IDEA in Dracula mode)

java_dark

The cool thing about the syntax highlighting is that you need to write (fairly) no code because we have a DSL defined via Xtext who allows you specify the highlighting rules to apply. Look for example at this groovy-file

groovy

and the specification of the highlighting
hsl

and the following CSS-Stylesheets for a bright and dark L&F
css-def

You notice that the token names simply match the CSS-Class-Selectors used!

Above I said there’s fairly no code you need to write because for complex rules like the variable interpolation in groovy strings we require you to write some JavaScript and we use Nashorn to load the rule definition which looks like this for variables inside strings.

groovy-js-inter


The text-editor framework that we started to build is not part of the release it is more of a research project that we started to build in this release cycle to exploit Eclipse4+JavaFX and other Eclipse technologies. All building blocks we used although are part of the release and you can build something similar yourself.

Posted in e(fx)clipse | Tagged | 13 Comments

e(fx)clipse 1.0 – New Features – The clever CSS-Editor who got more clever

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

The clever CSS-Editor who got more clever

As all of you probably know we have a fairly clever CSS-Editor who not only knows all JavaFX CSS attributes/properties but also knows on which CSS-Selector they apply. The only problem is that since JavaFX8 library developers like the people behind ControlsFX, JFXtras, miglayout can add Styleable-Properties to their controls, layout-containers, … . So you probably need a CSS-Editor who not only knows the properties of the OpenJFX library but is able to learn those of all the extra libraries out there.

While most know that we provide auto-complete, basic validation, … I guess it’s not publicly known how we manage to do it and where the information is coming from. I won’t go into detail but the main idea is that we defined something similar you know from XML/HTML where one often has Schema or DTD which defines all elements and properties of an XML-Document and your favorite XML-Editor makes use of it. We’ve learned from them and defined our own description language which holds all informations what selectors and properties are defined inside JavaFX and use this language in our tooling.

Let’s look at an example which helps to understand how it works. The file which can be compared to an XML-Schema or DTD is named CSSExt and looks like this:

def_1

def_2

You see some basic attribute definitions like enumerated values e.g. in Node the -fx-blend-mode one but also more complex attribtues in Region which e.g. results in auto-completes like

auto_1

auto_2

This is all stuff that you are used to when e(fx)clipse 0.9.0 is installed into your IDE. The new feature is that we are now analyzing the classpath of your project and if we find other .cssext-Files in e.g. libraries you’ve added to the classpath we take them into account. Let for example assume you’re using our Layout-Panes who have been enhanced in 1.0 to use StyleableProperties as outlined in our first blog post in the series.

Your build path looks like this:
cp

import javafx.scene.layout.Pane

package org.eclipse.fx.ui.panes {
  AbstractLayoutPane extends Pane {
		
  }
  GridLayoutPane extends AbstractLayoutPane {
    -fx-columns @INT default: 1;
    -fx-columns-equal-width <javafx.boolean> default: false;
    -fx-inner-margin-width <javafx.length> default: 5;
    -fx-inner-margin-height <javafx.length> default: 5;
    -fx-inner-margin-left <javafx.length> default: 0;
    -fx-inner-margin-top <javafx.length> default: 0;
    -fx-inner-margin-right <javafx.length> default: 0;
    -fx-inner-margin-bottom <javafx.length> default: 0;
    -fx-hspace <javafx.length> default: 5;
    -fx-vspace <javafx.length> default: 5;
  }

… and because of this you’ll get the following auto-complete in the CSS-Editor
auto_extra

We’d like to start in the next few months with JavaFX library developers like the ones mentionned above and convince them to add a cssext-File to their library so that you as a user of those libs get the best development experience inside e(fx)clipse. BTW if other IDEs would like to make use of our CSSExt-Files we’d appreciate to help anyone.

Posted in e(fx)clipse | Tagged | 9 Comments

e(fx)clipse 1.0 – New Features – Drag and Drop for e4/JavaFX applications

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

Drag and Drop for e4/JavaFX applications

One of the major missing features of the the e4 JavaFX Runtime Platform was the missing support for Drag and Drop to reorder, reparent and split PartStacks using DnD. I’m happy that we managed to get in those missing feature into the 1.0 release and that we are in the process of moveing our implementation to OpenJFX so that others get this support in 8u40 as well.

The cool thing is that you can customize the DnD feedback using

  1. CSS to control colors, …
  2. org.eclipse.fx.ui.workbench.renderers.base.services.DnDFeedbackService if you need more control over the feedback

The default implementation provides feedback like this:

  • Reorder Feedback
    reorder
  • Reparent Feedback
    reparent
  • Split Feedback
    split

Not yet supported is detaching a Tab to a floating window but we’ll hopefully get that support into the next release. In case you e.g. don’t like the colors used you are able modify them in your CSS-File.

.tab-outline-marker {
	-fx-fill: green;
}

.position-marker {
	-fx-fill: darkmagenta;
}
Posted in e(fx)clipse | Tagged | 8 Comments

e(fx)clipse 1.0 – New Features – CSS Gradient Editor

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

CSS Gradient Editor

When defining CSS-Stylesheets one sometimes wants to define a gradient instead of a solid background color. While one can easily remember how to define color e.g. by using the hex encoding. Defining a linear or radial gradient is more complex and you most likely need a WYSIWYG-Editor. So a good CSS-Tool should provide you such an editor.

  • Open a css file and create a property who expects a paint e.g. -fx-background-color
    editor
  • In the proposal select “Paint…” which will open a Paint-Editorgradient_editor
  • Once you are happy with your gradient. Hit ok and the gradient is inserted into your CSS-Stylesheet and in case your FXML-File is connected to the currently edited stylesheet the preview will update itselffinal-result
Posted in e(fx)clipse | Tagged | 13 Comments

e(fx)clipse 1.0 – New Features – LayoutPanes can be controlled by CSS

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

Controlling our layout panes with CSS

The JavaFX library makes heavy use of CSS allowing you to control fairly any L&F aspect of your application through CSS, while this API was not available as API in JavaFX 2.2, JavaFX introduced StyleableProperties as public API and so it can be consumed by external libraries like e.g. our LayoutPanes

Let’s look at an example when using our Pane-Library who provides:

  • FillLayoutPane: who uses the same layout algorithm you know from SWT-FillLayout
  • GridLayoutPane: who uses the same layout algorithm you know from SWT-GridLayout
  • RowLayoutPane: who uses the same layout algorithm you know from SWT-RowLayout

Let’s take GridLayoutPane as an example which allows you to control the horizontal & vertical space between cells like this:

package application;
	
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

import org.eclipse.fx.ui.panes.GridData;
import org.eclipse.fx.ui.panes.GridLayoutPane;


public class Main extends Application {
  @Override
  public void start(Stage primaryStage) {
    GridLayoutPane p = new GridLayoutPane();
    p.setHorizontalSpacing(50);
    p.setVerticalSpacing(5);
    p.setNumColumns(2);
			
    {
      TextField field = new TextField();
      GridLayoutPane.setConstraint(field, 
        new GridData(GridData.FILL_HORIZONTAL));
      p.getChildren().addAll(new Label("Firstname"), field);				
    }
			
    {
      TextField field = new TextField();
      GridLayoutPane.setConstraint(field, 
        new GridData(GridData.FILL_HORIZONTAL));
      p.getChildren().addAll(new Label("Lastname"), field);				
    }
			
    Scene scene = new Scene(p,400,400);
    scene.getStylesheets().add(
      getClass().getResource("application.css").toExternalForm());
    primaryStage.setScene(scene);
    primaryStage.show();
  }
	
  public static void main(String[] args) {
    launch(args);
  }
}

which would produce an UI like this
app

In the above case we are defining the gaps between the cells in a programmatic fashion which is not that nice but should be better controlled via CSS which is possible with the 1.0 version of the e(fx)clipse layout panes because they make use of the new public StyleProperty-API provided, let’s take a glance at the implementation:

package org.eclipse.fx.ui.panes;

public class GridLayoutPane extends AbstractLayoutPane<GridData> {
  // ....
  private static final CssMetaData<GridLayoutPane, Number> HORIZONTAL_SPACING = 
    new CssMetaData<GridLayoutPane, Number>(
      "-fx-hspace", SizeConverter.getInstance(), Integer.valueOf(5)) { //$NON-NLS-1$

    public boolean isSettable(GridLayoutPane node) {
      return !node.horizontalSpacingProperty().isBound();
    }

    public StyleableProperty<Number> getStyleableProperty(GridLayoutPane node) {
      return (StyleableProperty<Number>) node.horizontalSpacingProperty();
    }
  };

  @NonNull
  private final IntegerProperty horizontalSpacing = 
    new SimpleStyleableIntegerProperty(HORIZONTAL_SPACING, this, 
      "horizontalSpacing", Integer.valueOf(5)); //$NON-NLS-1$

  public final void setHorizontalSpacing(int value) {
    horizontalSpacingProperty().set(value);
  }

  public final int getHorizontalSpacing() {
    return horizontalSpacingProperty().get();
  }

  public final @NonNull IntegerProperty horizontalSpacingProperty() {
    return this.horizontalSpacing;
  }
}

the effect of the code above is that we can now instead of setting the horizontal & vertical properties via Java code let our css-file control them.

GridLayoutPane {
  -fx-hspace: 50px;
  -fx-vspace: 5px;
}
Posted in e(fx)clipse | Tagged | 9 Comments

e(fx)clipse 1.0 – New Features – Generate JavaFX Properties accessors

e(fx)clipse 1.0.0 is just around the corner and scheduled to be released on August 15th, while we are polishing the final bits, the Eclipse IP-Team checks our IP-Log, … .

I’d like to introduce you the new and exiting features that we worked on in the last months since we released 0.9.0 in February.

Blog series

Other posts in this series are:

The first feature we’d like to introduce is small helper who allows you to generate get*/set*/*Property methods for your JavaFX properties.

For those not familiar with JavaFX development: A JavaFX Bean works a bit different than a plain Java Bean. I guess all of you are familiar with the JavaBean-Pattern which looks like this:

public class MyBean {
  private int myInt;
  private int myReadonlyInt;

  private PropertyChangeSupport support = 
    new PropertyChangeSupport(this);

  public void addPropertyChangeListener(
    PropertyChangeListener l) {
      support.addPropertyChangeListener(l);
  }

  public void removePropertyChangeListener(
    PropertyChangeListener l) {
      support.removePropertyChangeListener(l);
  }

  public int getMyInt() {
    return myInt;
  }

  public void setMyInt(int myInt) {
    support.firePropertyChange(
      "myInt",this.myInt,this.myInt=myInt);
    setMyReadonlyInt(myInt*2);
  }

  public int getMyReadonlyInt() {
    return myReadonlyInt;
  }

  private void setMyReadonlyInt(int myReadonlyInt) {
    support.firePropertyChange(
      "myReadonlyInt",this.myReadonlyInt,this.myReadonlyInt=myReadonlyInt);
  }
}

which is written in JavaFX like this:

public class MyFXBean {
  private IntegerProperty myInt = new SimpleIntegerPropery(this,"myInt");
  private ReadOnlyIntegerWrapper myReadonlyInt = new ReadOnlyIntegerWrapper(this,"myReadonlyInt");
  
  public int getMyInt() {
    return myIntProperty().get();
  }

  public void setMyInt(int myInt) {
    myIntProperty().set(myInt);
  }

  public IntegerProperty myIntProperty() {
    return myInt;
  }

  public final ReadOnlyIntegerProperty myReadonlyIntProperty() {
    return this.myReadonlyInt.getReadOnlyProperty();
  }

  public final int getMyReadonlyInt() {
    return this.myReadonlyIntProperty().get();
  }
}

While Eclipse allows you to generate Getters/Setters for the JavaBean pattern would invalid Getters/Setters for a JavaFX Bean and no accessor at all for property itself.

So this makes a good first new feature to be introduced by e(fx)clipse tooling:

A wizard who generates the methods

  • Bring up the context menu on the Editor
    context-menu
  • Select Generate JavaFX Getters and Setters
  • A dialog opens and shows you all JavaFX-Propertiesdialog
  • Select the properties you want to generate the accessors for the “make methods final” is good JavaFX design because subclasses should not be able to overwrite your methods. See for example also JavaFX Tip 4: Have the Final Word hence making them final is the default
  • Simply hit OK and you get the resultfinal-result

For those who prefer to use keyboard short-cuts you can use:

  • CTRL/CMD+3 – To open the Quick Assist
  • Type “Generate JavaFX” and you should already see the command you want to execute and on subsequent Quick-Assist is very likely in the previos choice section
    quick

Give it a try and get Eclipse Luna + e(fx)clipse 1.0.0 nightly build from our update-site or simply download the all-in-one package from http://efxclipse.bestsolution.at/install.html.

Posted in e(fx)clipse | Tagged | 9 Comments

Reorder and Drag and Drop with JavaFX TabPane

Upon public request I’ve extracted my draggable TabPane from my code and made it available in a bundle who holds only controls. If you have a need for a TabPane with drag support it is as easy as grabbing “org.eclipse.fx.ui.controls_1.0.0.$TIMESTAMP.jar” from our build server (I’ll work on publishing the stuff to maven central)

Once you have the jar added to your project adding the drag support involves only:

HBox h = new HBox();
			
{
  Pane pane = DndTabPaneFactory.createDefaultDnDPane(
    FeedbackType.MARKER, this::setupTb1);
  HBox.setHgrow(pane, Priority.ALWAYS);
  h.getChildren().add(pane);
}
			
{
  Pane pane = DndTabPaneFactory.createDefaultDnDPane(
    FeedbackType.MARKER, this::setupTb2);
  HBox.setHgrow(pane, Priority.ALWAYS);
  h.getChildren().add(pane);
}

and the 2 methods setupTb1 and setupTb2 look like this:

private void setupTb1(TabPane tb) {
  {
    Tab tab = new Tab("T 1.1");
    Rectangle r = new Rectangle(100, 100);
    r.setFill(Color.GREEN);
    tab.setContent(new BorderPane(r));
    tb.getTabs().add(tab);
  }
		
  {
    Tab tab = new Tab("Tab 1.2");
    Rectangle r = new Rectangle(100, 100);
    r.setFill(Color.RED);
    tab.setContent(new BorderPane(r));
    tb.getTabs().add(tab);
  }
}

// ....
Posted in e(fx)clipse | 5 Comments

JFace Viewers in a Java8 world – Part 1 ListViewer

Most people who write RCP applications today know about JFace Viewers and in my opinion the Viewer framework is one of the best programming patterns that came out of Eclipse – easy to understand, easy to apply but still powerful.

Still working with viewers in a world of Java8 feels really bad because of 2 things:

  • JFace Viewers don’t have generics and useage of Object[] in the API
  • JFace APIs does not use SAM-Types

There’s a google summer of code project that tries to add generics to the JFace Viewer API but this does not change the 2nd IMHO as important part – the API feels alien in a Java8 world of lambda expressions and method references.

A few weeks back a discussion came up at the GEF mailing list in conjunction with GEF4 who thought API adopting the JFace API to setup graph viewers but that brought up a 3rd problem – JFace Viewer does not completely hide the SWT API and because GEF4 is designed to be widget toolkit agnostic then JFace Viewer API.

So the requirements for a revised JFace API is:

  1. Use generics to provide type safety
  2. Make use of SAM types
  3. Do not depend of any toolkit technology

Today I had to make a break from my day work and thought about how an Viewer 2.0 would look like and this what I came up with:

Viewer.java

/**
 * Base interface of all viewers
 * 
 * @param <O>
 *            the domain object representing a row
 * @param <I>
 *            the input to the viewer
 * @param <C>
 *            the content provider responsible to translate the input into the
 *            internal structure
 */
public interface Viewer<O, I, C extends ContentProvider<O, I>> {
  public void setContentProvider(
    @NonNull Supplier<@NonNull C> contentProvider);

  public void setInput(@NonNull Supplier<@NonNull I> input);
}

You notice that the content-provider and input are not set directly but through suppliers, the reason for that is the input most of the time is not created next to viewer but through a method call into the business layer and for the content provider one often uses a factory to reuse content provider implementations.

So the 2nd and 3rd step of setting up Viewers 2.0 would look like this:

public class Demo {

  private void setup(ListViewer<Person,List<Person>,ContentProvider<Person, List<Person>>> viewer) {
    // ... (setup of labels, ...)
    viewer.setContentProvider(
      ContentProviderFactory::createListContentProvider);
    viewer.setInput(this::listInput);
  }

  // ....
}

and the helper methods could look like this:

private List<Person> listInput() {
  try {
    return Arrays.asList(
      new Person(false, "Tom", "Schindl", format.parse("01.05.1979")),
      new Person(true, "Maria", "Musterfrau", format.parse("01.05.1970"))
    );
  } catch (ParseException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }
  return Collections.emptyList();
}
public class ContentProviderFactory {
  public static <O> ContentProvider<O, List<O>> createListContentProvider() {
    return new ContentProvider<O, List<O>>() {
      @Override
      public List<O> getRootElements(List<O> input) {
        return input;
      }
    };
  }

  // ... more factory
}

Let’s go on with the translation of the domain element into information a the viewer can present so we need to take a look at the ListViewer interface:

public interface ListViewer<O, I, C extends ContentProvider<O, I>> extends Viewer<O, I, C> {
  /**
   * Translate the domain object into a string
   * 
   * @param converter
   *            the converter
   * @return the list viewer
   */
  public ListViewer<O, I, C> textProvider(
    Function<@NonNull O, @Nullable String> converter);

  /**
   * Translate the domain object into a style information to style the cell
   * and its contents e.g. background color
   * 
   * @param converter
   *            the converter
   * @return the list viewer
   */
  public ListViewer<O, I, C> styleProvider(
    Function<@NonNull O, @Nullable String> converter);

  /**
   * Translate the domain object into a style ranges
   * 
   * @param converter
   *            the converter
   * @return the list viewer
   */
  public ListViewer<O, I, C> textStyleRangeProvider(
    Function<@NonNull O, @NonNull List<@NonNull StyleRange>> converter);

  /**
   * Translate the domain object into an image definition
   * 
   * @param converter
   *            the converter
   * @return the list viewer
   */
  public ListViewer<O, I, C> graphicProvider(
    Function<@NonNull O, @Nullable String> converter);

This makes our complete setup look like this:

public class Demo {

  private void setup(ListViewer<Person,List<Person>,ContentProvider<Person, List<Person>>> viewer) {
    viewer
     .textProvider(this::personFullText)
     .graphicProvider(this::genderImage);

    viewer.setContentProvider(
      ContentProviderFactory::createListContentProvider);
    viewer.setInput(this::listInput);
  }

  // ....
}

where the textProvider and graphicProvider-Function look like this:

private String personFullText(Person p) {
  return p.getFirstname() + "," + p.getLastname() 
   + "("+format.format(p.getBirthdate())+")";
}
private String genderImage(Person p) {
  return p.isFemale() ? "female.png" : "male.png";
}

That’s it for today – in the next post I’ll show you how a revised TableViewer API could look like

Posted in e(fx)clipse, Eclipse, Enhanced RCP | 2 Comments

Restarting an e4 application with the intial workbench.e4xmi

e4 applications by default remember the state when getting shutdown and restore that state on the next restart. This is the behavior most people expect from an application but there are situations people would like to reset the application into its original state or maybe the developer wants that e.g. after having installed/uninstalled certain new bundles.

Unfortunately the workbench currently does not provide a way restart and clear the current state. So I’ve implemented a small library you can make use of in your e4 applications.

There are 2 parts:

  1. a service called RestartService which has a method restart(boolean)
  2. a Lifecycle-Addon you can reuse or copy the code from min to yours

Useage is very simple e.g. in your handler:

import org.eclipse.e4.core.di.annotations.Execute;

import at.bestsolution.e4.extensions.core.services.RestartService;

public class RestartHandler {
  @Execute
  public void restart(RestartService service) {
    service.restart(true);
  }
}

and to enable the addon you make your plugin.xml look like this:

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
  <extension
    id="product"
    point="org.eclipse.core.runtime.products">
    <product
      name="SampleProject"
      application="org.eclipse.e4.ui.workbench.swt.E4Application">
      <property
        name="applicationCSS"
        value="platform:/plugin/SampleProject/css/default.css">
      </property>
      <property
        name="lifeCycleURI"
        value="bundleclass://at.bestsolution.e4.extensions.lifecycle/at.bestsolution.e4.extensions.lifecycle.ExtensibleLifecycle">
      </property>
      <property
        name="appName"
        value="SampleProject">
      </property>
    </product>
  </extension>
</plugin>

If you want to make use of it you can find the p2-repo at http://downloads.foss.bestsolution.at/e4-extensions/nightly/ or if you prefer the source it is hosted at the github account of BestSolution.at at https://github.com/BestSolution-at/e4-extensions.

Posted in e4 | 7 Comments