/*******************************************************************************
* Copyright (c) 2011 Kai Toedter and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Kai Toedter - initial API and implementation
******************************************************************************/
package com.toedter.e4.ui.workbench.renderers.javafx;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javax.inject.Inject;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.fx.ui.services.theme.Theme;
import org.eclipse.fx.ui.services.theme.ThemeManager;
import com.toedter.e4.ui.workbench.generic.GenericRenderer;
import com.toedter.e4.ui.workbench.generic.PresentationEngine;
@SuppressWarnings("restriction")
public class WorkbenchWindowRenderer extends GenericRenderer {
@Inject
@Optional
ThemeManager themeManager;
private static class PosAndSizeListener implements ChangeListener<Number> {
private final Stage stage;
private final MWindow mWindow;
public PosAndSizeListener(Stage stage, MWindow mWindow) {
super();
this.stage = stage;
this.mWindow = mWindow;
}
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
mWindow.setX(((Double) stage.getX()).intValue());
mWindow.setY(((Double) stage.getY()).intValue());
mWindow.setWidth(((Double) stage.getWidth()).intValue());
mWindow.setHeight(((Double) stage.getHeight()).intValue());
}
}
@Override
public void createWidget(MUIElement element, MElementContainer<MUIElement> parent) {
if (element instanceof MWindow) {
final MWindow mWindow = (MWindow) element;
Stage stage = new Stage();
stage.setX(mWindow.getX());
stage.setY(mWindow.getY());
stage.setWidth(mWindow.getWidth());
stage.setHeight(mWindow.getHeight());
stage.setTitle(((MWindow) element).getLocalizedLabel());
BorderPane root = new BorderPane();
VBox topAreaBox = new VBox();
root.setTop(topAreaBox);
root.setStyle("-fx-background-color: #999;");
Scene scene = new Scene(root,-1,-1, Platform.isSupported(ConditionalFeature.SCENE3D));
if( Platform.isSupported(ConditionalFeature.SCENE3D) ) {
scene.setCamera(new PerspectiveCamera());
}
stage.setScene(scene);
if (themeManager != null) {
Theme theme = themeManager.getCurrentTheme();
if (theme != null) {
List<String> sUrls = new ArrayList<String>();
for (URL url : theme.getStylesheetURL()) {
sUrls.add(url.toExternalForm());
}
scene.getStylesheets().addAll(sUrls);
}
themeManager.registerScene(scene);
}
element.setWidget(stage);
}
}
@Override
public void processContents(MElementContainer<MUIElement> element) {
if ((MUIElement) element instanceof MWindow) {
Stage stage = (Stage) element.getWidget();
BorderPane root = (BorderPane) stage.getScene().getRoot();
VBox topBox = (VBox) root.getTop();
PresentationEngine renderer = (PresentationEngine) context.get(IPresentationEngine.class.getName());
for (MUIElement child : element.getChildren()) {
root.setCenter((Node) child.getWidget());
}
MWindow window = (MWindow) (MUIElement) element;
// topBox.getChildren().removeAll(topBox.getChildren());
if (window.getMainMenu() != null) {
Node node = (Node) renderer.createGui(window.getMainMenu(), element);
if (node != null) {
topBox.getChildren().add(node);
}
}
if (window instanceof MTrimmedWindow) {
MTrimmedWindow tWindow = (MTrimmedWindow) window;
for (MTrimBar trim : tWindow.getTrimBars()) {
Node node = (Node) renderer.createGui(trim);
if (node != null) {
switch (trim.getSide()) {
case BOTTOM:
root.setBottom(node);
break;
case LEFT:
root.setLeft(node);
break;
case RIGHT:
root.setRight(node);
break;
case TOP:
topBox.getChildren().add(node);
break;
}
}
}
}
// now the hole stage is created and we can show it
stage.toFront();
stage.show();
}
}
@Override
public void doLayout(MElementContainer<?> element) {
if (element instanceof MWindow) {
Stage stage = (Stage) element.getWidget();
BorderPane root = (BorderPane) stage.getScene().getRoot();
VBox topBox = (VBox) root.getTop();
MWindow window = (MWindow) (MUIElement) element;
if (window instanceof MTrimmedWindow) {
MTrimmedWindow trimmedWindow = (MTrimmedWindow) window;
for (MTrimBar trim : trimmedWindow.getTrimBars()) {
Node node = (Node) trim.getWidget();
if (!trim.isVisible()) {
node = null;
}
switch (trim.getSide()) {
case BOTTOM:
root.setBottom(node);
break;
case LEFT:
root.setLeft(node);
break;
case RIGHT:
root.setRight(node);
break;
}
}
}
}
}
@Override
public void hookControllerLogic(MUIElement element) {
if (element instanceof MWindow) {
MWindow window = (MWindow) element;
Stage stage = (Stage) element.getWidget();
ChangeListener<Number> resizeListener = new PosAndSizeListener(stage, window);
stage.widthProperty().addListener(resizeListener);
stage.heightProperty().addListener(resizeListener);
stage.xProperty().addListener(resizeListener);
stage.yProperty().addListener(resizeListener);
}
}
@Override
public void removeChild(MUIElement element, MElementContainer<MUIElement> parent) {
System.out.println("GenericRenderer.removeChild(): " + element + ", parent: " + parent);
if ((MUIElement) parent instanceof MWindow) {
MWindow window = (MWindow) (MUIElement) parent;
Stage stage = (Stage) window.getWidget();
BorderPane root = (BorderPane) stage.getScene().getRoot();
root.setCenter(null);
}
}
}