Package at.bestsolution.efxclipse.runtime.workbench.renderers.fx

Source Code of at.bestsolution.efxclipse.runtime.workbench.renderers.fx.DefWindowRenderer$MultiMessageDialog

/*******************************************************************************
* Copyright (c) 2012 BestSolution.at 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:
*     Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
*******************************************************************************/
package at.bestsolution.efxclipse.runtime.workbench.renderers.fx;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import javafx.util.Callback;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.translation.TranslationService;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindowElement;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.workbench.IResourceUtilities;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.ISaveHandler.Save;
import org.eclipse.emf.common.util.URI;
import org.eclipse.osgi.service.localization.BundleLocalization;
import org.osgi.framework.Bundle;

import at.bestsolution.efxclipse.runtime.di.InjectingFXMLLoader;
import at.bestsolution.efxclipse.runtime.dialogs.Dialog;
import at.bestsolution.efxclipse.runtime.dialogs.MessageDialog;
import at.bestsolution.efxclipse.runtime.dialogs.MessageDialog.QuestionCancelResult;
import at.bestsolution.efxclipse.runtime.panels.FillLayoutPane;
import at.bestsolution.efxclipse.runtime.services.theme.Theme;
import at.bestsolution.efxclipse.runtime.services.theme.ThemeManager;
import at.bestsolution.efxclipse.runtime.services.theme.ThemeManager.Registration;
import at.bestsolution.efxclipse.runtime.workbench.fx.key.KeyBindingDispatcher;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.BaseRenderer;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.BaseWindowRenderer;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.services.WindowTransitionService;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.services.WindowTransitionService.AnimationDelegate;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WLayoutedWidget;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WWidget;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WWindow;
import at.bestsolution.efxclipse.runtime.workbench.renderers.fx.widget.WLayoutedWidgetImpl;

@SuppressWarnings("restriction")
public class DefWindowRenderer extends BaseWindowRenderer<Stage> {

  protected Save[] promptToSave(MWindow element, Collection<MPart> dirtyParts, WWindow<Stage> widget) {
    Save[] response = new Save[dirtyParts.size()];
    @SuppressWarnings("unchecked")
    IResourceUtilities<Image> resourceUtilities = getModelContext(element).get(IResourceUtilities.class);

    MultiMessageDialog d = new MultiMessageDialog((Stage) widget.getWidget(), dirtyParts, resourceUtilities);
    if (d.open() == Dialog.OK_BUTTON) {
      List<MPart> parts = d.getSelectedParts();
      Arrays.fill(response, Save.NO);
      for (MPart p : parts) {
        response[parts.indexOf(p)] = Save.YES;
      }
    } else {
      Arrays.fill(response, Save.CANCEL);
    }

    return response;
  }

  protected Save promptToSave(MWindow element, MPart dirtyPart, WWindow<Stage> widget) {
    QuestionCancelResult r = MessageDialog.openQuestionCancelDialog((Stage) widget.getWidget(), "Unsaved changes", "'" + dirtyPart.getLocalizedLabel() + "' has been modified. Save changes?");

    switch (r) {
    case CANCEL:
      return Save.CANCEL;
    case NO:
      return Save.NO;
    case YES:
      return Save.YES;
    }

    return Save.CANCEL;
  }

  @Override
  protected Class<? extends WWindow<Stage>> getWidgetClass(MWindow window) {
    return WWindowImpl.class;
  }

  public static class WWindowImpl extends WLayoutedWidgetImpl<Stage, BorderPane, MWindow> implements WWindow<Stage> {
    private boolean support3d;
    private BorderPane rootPane;
    private BorderPane trimPane;
    private FillLayoutPane contentPane;
    private KeyBindingDispatcher dispatcher;
    private BorderPane decoratorPane;
    private WindowResizeButton windowResizeButton;
    private Stage stage;

    @Inject
    @Optional
    ThemeManager themeManager;

    private Registration sceneRegistration;

    private String decorationFXML;
   
    private boolean fullscreen;

    @Inject
    IEclipseContext context;
   
    IEclipseContext modelContext;
   
    MWindow mWindow;
   
    @Inject
    TranslationService translationService;

    @Inject
    BundleLocalization localizationService; //FIXME We should get rid of this
   
    @Inject
    @Optional
    WindowTransitionService<Stage> windowTransitionService;
   
    @Inject
    private IResourceUtilities<Image> resourceUtilities;
   
    boolean initDone;
   
    private boolean undecorated;
   
    @Inject
    public WWindowImpl(@Named(BaseRenderer.CONTEXT_DOM_ELEMENT) MWindow mWindow, @Optional KeyBindingDispatcher dispatcher) {
      this.mWindow = mWindow;
     
      if( mWindow.getPersistedState().get("fx.scene.3d") != null ) {
        System.err.println("Usage of deprecated persisted state 'fx.scene.3d' please use 'efx.window.scene.3d' instead.");
        this.support3d = Boolean.parseBoolean(mWindow.getPersistedState().get("fx.scene.3d"))
      } else {
        this.support3d = Boolean.parseBoolean(mWindow.getPersistedState().get("efx.window.scene.3d"));
      }
     
      this.dispatcher = dispatcher;
      this.modelContext = mWindow.getContext();
      this.decorationFXML = mWindow.getPersistedState().get("fx.stage.decoration");
     
      if( decorationFXML == null ) {
        decorationFXML = mWindow.getPersistedState().get("efx.window.decoration.fxml");
      } else {
        System.err.println("Useage of deprecated persisted state 'fx.stage.decoration' please use 'efx.window.decoration.fxml' instead.");
      }
     
      this.undecorated = Boolean.parseBoolean(mWindow.getPersistedState().get("efx.window.undecorated"));
    }
   
    @PostConstruct
    protected void init() {
      this.initDone = true;
      super.init();
    }

    @Override
    protected void doCleanup() {
      super.doCleanup();
      sceneRegistration.dispose();
    }

    @Override
    protected Stage createWidget() {
      stage = new Stage();
      stage.focusedProperty().addListener(new ChangeListener<Boolean>() {

        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
          if( newValue.booleanValue() ) {
            activate();
          }
        }
      });
      stage.setFullScreen(fullscreen);
      stage.fullScreenProperty().addListener(new ChangeListener<Boolean>() {

        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
          mWindow.getPersistedState().put(BaseWindowRenderer.KEY_FULL_SCREEN, newValue.toString());
        }
      });
     
      if( dispatcher != null ) {
        stage.addEventFilter(KeyEvent.KEY_PRESSED, dispatcher.getKeyHandler())
      }
     
      this.rootPane = new BorderPane() {
        @Override
        protected void layoutChildren() {
          super.layoutChildren();
          if (windowResizeButton != null) {
            windowResizeButton.autosize();
           
            windowResizeButton.setLayoutX(getWidth() - windowResizeButton.getLayoutBounds().getWidth());
            windowResizeButton.setLayoutY(getHeight() - windowResizeButton.getLayoutBounds().getHeight());
          }
        }
      };

      this.trimPane = new BorderPane();
      this.rootPane.setCenter(trimPane);
      this.contentPane = new FillLayoutPane();
      this.trimPane.setCenter(contentPane);

      if (decorationFXML != null) {
        windowResizeButton = new WindowResizeButton(stage, 50, 50);
        decoratorPane = new BorderPane();
        decoratorPane.setTop(createTopDecoration(stage));
        rootPane.setTop(decoratorPane);
      }
     
      if( undecorated ) {
        stage.initStyle(StageStyle.UNDECORATED);
      }

      // TODO Should we create the scene on show???
      Scene s;
      if (support3d && Platform.isSupported(ConditionalFeature.SCENE3D)) {
        s = new Scene(rootPane, -1, -1, true);
        s.setCamera(new PerspectiveCamera());

      } else {
        s = new Scene(rootPane);
      }

      s.focusOwnerProperty().addListener(new ChangeListener<Node>() {
        List<WWidget<?>> lastActivationTree = new ArrayList<WWidget<?>>();
        List<WWidget<?>> queuedTree = new ArrayList<WWidget<?>>();
       
        @Override
        public void changed(ObservableValue<? extends Node> observable, Node oldValue, Node newValue) {
          if (newValue != null) {
            final List<WWidget<?>> activationTree = new ArrayList<WWidget<?>>();

            do {
              if (newValue.getUserData() instanceof WWidget<?>) {
                activationTree.add((WWidget<?>) newValue.getUserData());
              }
            } while ((newValue = newValue.getParent()) != null);

            if (!lastActivationTree.equals(activationTree)) {
              final List<WWidget<?>> oldTreeReversed = new ArrayList<WWidget<?>>(lastActivationTree);
              final List<WWidget<?>> newTreeReversed = new ArrayList<WWidget<?>>(activationTree);
              Collections.reverse(oldTreeReversed);
              Collections.reverse(newTreeReversed);
              Iterator<WWidget<?>> it = newTreeReversed.iterator();

              while (it.hasNext()) {
                if (!oldTreeReversed.isEmpty()) {
                  if (oldTreeReversed.get(0) == it.next()) {
                    oldTreeReversed.remove(0);
                    it.remove();
                  } else {
                    break;
                  }
                } else {
                  break;
                }
              }

              Collections.reverse(oldTreeReversed);
              Collections.reverse(newTreeReversed);

              queuedTree = activationTree;

              // Delay the execution maybe there's an intermediate
              // state we are not interested in
              // http://javafx-jira.kenai.com/browse/RT-24069
              Platform.runLater(new Runnable() {

                @Override
                public void run() {
                  if (queuedTree == activationTree) {
                    lastActivationTree = activationTree;
                    for (WWidget<?> w : oldTreeReversed) {
                      w.deactivate();
                    }

                    for (WWidget<?> w : newTreeReversed) {
                      w.activate();
                    }
                  }
                }
              });
            }
          }
        }
      });

      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());
          }

          s.getStylesheets().addAll(sUrls);
        }
        sceneRegistration = themeManager.registerScene(s);
      }

      if( windowResizeButton != null ) {
        rootPane.getChildren().add(windowResizeButton);
      }
     
      stage.setScene(s);

      modelContext.set(Stage.class, stage);
      modelContext.set(Scene.class, s);
     
      return stage;
    }

    private Node createTopDecoration(final Stage stage) {
      URI uri = URI.createURI(decorationFXML);

      if (uri != null) {
        stage.initStyle(StageStyle.UNDECORATED);

        Bundle b = org.eclipse.core.runtime.Platform.getBundle(uri.segment(1));
        if (b != null) {
          try {
            StringBuilder sb = new StringBuilder();
            for (int i = 2; i < uri.segmentCount(); i++) {
              if (sb.length() != 0) {
                sb.append("/");
              }
              sb.append(uri.segment(i));
            }
           
            InjectingFXMLLoader<Node> loader = InjectingFXMLLoader.create(context, b, sb.toString());
            loader.resourceBundle(localizationService.getLocalization(b, Locale.getDefault().toString()));
           
//FIXME We should make the localization service smarter           
//            final String contributorURI = URI.createPlatformPluginURI(uri.segment(1), true).toString();
//            loader = loader.resourceBundle(new ResourceBundle() {
//
//              @Override
//              protected Object handleGetObject(String key) {
//                return translationService.translate("%" + key, contributorURI);
//              }
//
//              @Override
//              public Enumeration<String> getKeys() {
//                // TODO Can we do this???
//                return Collections.emptyEnumeration();
//              }
//            });
           
            return (Node) loader.load();
          } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }

      }

      return null;
    }

    @Override
    protected void bindProperties(Stage widget) {
      super.bindProperties(widget);
      bindProperty(UIEvents.Window.X, widget.xProperty());
      bindProperty(UIEvents.Window.Y, widget.yProperty());
      bindProperty(UIEvents.Window.WIDTH, widget.widthProperty());
      bindProperty(UIEvents.Window.HEIGHT, widget.heightProperty());
    }

    @Override
    public void setMainMenu(WLayoutedWidget<MMenu> menuWidget) {
      if (decoratorPane == null) {
        this.rootPane.setTop((Node) menuWidget.getStaticLayoutNode());
      } else {
        decoratorPane.setBottom((Node) menuWidget.getStaticLayoutNode());
      }
    }

    @Override
    protected BorderPane getWidgetNode() {
      return rootPane;
    }

    @Inject
    public void setX(@Named(UIEvents.Window.X) int x) {
      getWidget().setX(x);
    }

    @Inject
    public void setY(@Named(UIEvents.Window.Y) int y) {
      getWidget().setY(y);
    }

    @Inject
    public void setWidth(@Named(UIEvents.Window.WIDTH) int w) {
      getWidget().setWidth(w);
    }

    @Inject
    public void setHeight(@Named(UIEvents.Window.HEIGHT) int h) {
      getWidget().setHeight(h);
    }
   
    @Inject
    public void setVisible(@Named(UIEvents.UIElement.VISIBLE) boolean visible) {
      // Skip the init injection because the renderer will take care of showing the stage
      if( ! initDone ) {
        return;
      }
     
      if( visible ) {
        internalShow();
      } else {
        internalHide();
      }
    }

    @Inject
    public void setFullscreen(@Named(UIEvents.ApplicationElement.PERSISTEDSTATE + "_" + BaseWindowRenderer.KEY_FULL_SCREEN) @Optional String fullScreen) {
      if( fullScreen != null ) {
        this.fullscreen = Boolean.parseBoolean(fullScreen);
        if( stage != null ) {
          stage.setFullScreen(fullscreen);
        }
      } else {
        this.fullscreen = false;
      }
    }
   
    @Override
    public void addStyleClasses(List<String> classnames) {
      rootPane.getStyleClass().addAll(classnames);
    }

    @Override
    public void setStyleId(String id) {
      rootPane.setId(id);
    }

    @Override
    public void show() {
      internalShow();
      getWidget().toFront();
    }
   
    @Override
    public void close() {
      getWidget().close();
    }
   
    private void internalShow() {
      if( windowTransitionService != null ) {
        AnimationDelegate<Stage> delegate = windowTransitionService.getShowDelegate(mWindow);
        if( delegate != null ) {
          delegate.animate(stage);
        } else {
          getWidget().show();
        }
      } else {
        getWidget().show()
      }
    }
   
    private void internalHide() {
      if( windowTransitionService != null ) {
        AnimationDelegate<Stage> delegate = windowTransitionService.getShowDelegate(mWindow);
        if( delegate != null ) {
          delegate.animate(stage);
        } else {
          getWidget().hide();
        }
      } else {
        getWidget().hide();
      }
    }

    @Inject
    public void setTitle(@Named(ATTRIBUTE_localizedLabel) String title) {
      getWidget().setTitle(title);
    }
   
    @Inject
    public void setImageUrl(@Named(UIEvents.UILabel.ICONURI) @Optional String iconUri) {
      if( iconUri != null ) {
       
        String[] split = iconUri.split(";");
        List<Image> images = new ArrayList<>();
        for( String uri : split ) {
          Image img = resourceUtilities.imageDescriptorFromURI(URI.createURI(uri));
          if( img != null ) {
            images.add(img);
          }
        }
       
        getWidget().getIcons().setAll(images);
      } else {
        getWidget().getIcons().clear();
      }
    }

    @Override
    public void setBottomTrim(WLayoutedWidget<MTrimBar> trimBar) {
      trimPane.setBottom((Node) trimBar.getStaticLayoutNode());
    }

    @Override
    public void setLeftTrim(WLayoutedWidget<MTrimBar> trimBar) {
      trimPane.setLeft((Node) trimBar.getStaticLayoutNode());
    }

    @Override
    public void setRightTrim(WLayoutedWidget<MTrimBar> trimBar) {
      trimPane.setRight((Node) trimBar.getStaticLayoutNode());
    }

    @Override
    public void setTopTrim(WLayoutedWidget<MTrimBar> trimBar) {
      Node g = (Node) trimBar.getStaticLayoutNode();
      trimPane.setTop(g);
    }

    @Override
    public void addChild(WLayoutedWidget<MWindowElement> widget) {
      contentPane.getChildren().add((Node) widget.getStaticLayoutNode());
    }
   
    @Override
    public void removeChild(WLayoutedWidget<MWindowElement> widget) {
      contentPane.getChildren().remove((Node) widget.getStaticLayoutNode());
    }
   
    @Override
    public void addChild(int idx, WLayoutedWidget<MWindowElement> widget) {
      contentPane.getChildren().add(idx, (Node) widget.getStaticLayoutNode());
    }
  }

  static class MultiMessageDialog extends Dialog {
    private Collection<MPart> parts;
    private TableView<Row> tabView;

    private final IResourceUtilities<Image> resourceUtilities;
    private List<MPart> selectedParts;

    public MultiMessageDialog(Window parent, Collection<MPart> parts, IResourceUtilities<Image> resourceUtilities) {
      super(parent, "Save Resources");
      this.parts = parts;
      this.resourceUtilities = resourceUtilities;
    }

    public List<MPart> getSelectedParts() {
      return selectedParts;
    }

    @Override
    protected void okPressed() {
      selectedParts = new ArrayList<MPart>();
      for (Row r : tabView.getItems()) {
        if (r.isSelected()) {
          selectedParts.add(r.element.get());
        }
      }
      super.okPressed();
    }

    @Override
    protected Node createDialogArea() {
      BorderPane p = new BorderPane();
      Label l = new Label("Save resources to save");
      p.setTop(l);

      tabView = new TableView<Row>();

      {
        TableColumn<Row, Boolean> column = new TableColumn<Row, Boolean>();
        column.setCellFactory(new Callback<TableColumn<Row, Boolean>, TableCell<Row, Boolean>>() {

          @Override
          public TableCell<Row, Boolean> call(final TableColumn<Row, Boolean> param) {
            final CheckBox checkBox = new CheckBox();
            final TableCell<Row, Boolean> cell = new TableCell<Row, Boolean>() {

              @Override
              protected void updateItem(Boolean item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null) {
                  checkBox.setDisable(true);
                  checkBox.setSelected(false);
                  checkBox.setOnAction(null);
                } else {
                  checkBox.setDisable(false);
                  checkBox.setSelected(item);
                  checkBox.setOnAction(new EventHandler<ActionEvent>() {

                    @Override
                    public void handle(ActionEvent event) {
                      tabView.edit(0, param);
                      commitEdit(checkBox.isSelected());
                    }
                  });
                }
              }
            };

            cell.setGraphic(checkBox);
            return cell;
          }
        });
        column.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Row, Boolean>>() {

          @Override
          public void handle(CellEditEvent<Row, Boolean> event) {
            event.getRowValue().selected.set(event.getNewValue());
          }
        });
        column.setCellValueFactory(new PropertyValueFactory<Row, Boolean>("selected"));
        tabView.getColumns().add(column);
      }

      {
        TableColumn<Row, MPart> column = new TableColumn<Row, MPart>();
        column.setCellFactory(new Callback<TableColumn<Row, MPart>, TableCell<Row, MPart>>() {

          @Override
          public TableCell<Row, MPart> call(TableColumn<Row, MPart> param) {
            return new TableCell<DefWindowRenderer.Row, MPart>() {
              @Override
              protected void updateItem(MPart item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null) {
                  setText(item.getLocalizedLabel());
                  String uri = item.getIconURI();
                  if (uri != null) {
                    setGraphic(new ImageView(resourceUtilities.imageDescriptorFromURI(URI.createURI(uri))));
                  }
                }
              }
            };
          }
        });
        column.setCellValueFactory(new PropertyValueFactory<Row, MPart>("element"));
        tabView.getColumns().add(column);
      }
      tabView.setEditable(true);

      List<Row> list = new ArrayList<Row>();
      for (MPart m : parts) {
        list.add(new Row(m));
      }
      tabView.setItems(FXCollections.observableArrayList(list));
      p.setCenter(tabView);

      return p;
    }
  }

  static class Row {
    private BooleanProperty selected = new SimpleBooleanProperty(this, "selected", true);
    private ObjectProperty<MPart> element = new SimpleObjectProperty<MPart>(this, "element");

    public Row(MPart element) {
      this.element.set(element);
    }

    public boolean isSelected() {
      return selected.get();
    }

    public void setSelected(boolean value) {
      this.selected.set(value);
    }

    public BooleanProperty selectedProperty() {
      return this.selected;
    }

    public MPart getElement() {
      return element.get();
    }

    public void setElement(MPart value) {
      element.set(value);
    }

    public ObjectProperty<MPart> elementProperty() {
      return element;
    }
  }
 
  static class WindowResizeButton extends Region {
      private double dragOffsetX, dragOffsetY;

      public WindowResizeButton(final Stage stage, final double stageMinimumWidth, final double stageMinimumHeight) {
          setId("window-resize-button");
          setPrefSize(11,11);
          setOnMousePressed(new EventHandler<MouseEvent>() {
              @Override public void handle(MouseEvent e) {
                  dragOffsetX = (stage.getX() + stage.getWidth()) - e.getScreenX();
                  dragOffsetY = (stage.getY() + stage.getHeight()) - e.getScreenY();
                  e.consume();
              }
          });
          setOnMouseDragged(new EventHandler<MouseEvent>() {
              @Override public void handle(MouseEvent e) {
                  ObservableList<Screen> screens = Screen.getScreensForRectangle(stage.getX(), stage.getY(), 1, 1);
                  final Screen screen;
                  if(screens.size()>0) {
                      screen = Screen.getScreensForRectangle(stage.getX(), stage.getY(), 1, 1).get(0);
                  }
                  else {
                      screen = Screen.getScreensForRectangle(0,0,1,1).get(0);
                  }
                  Rectangle2D visualBounds = screen.getVisualBounds();            
                  double maxX = Math.min(visualBounds.getMaxX(), e.getScreenX() + dragOffsetX);
                  double maxY = Math.min(visualBounds.getMaxY(), e.getScreenY() - dragOffsetY);
                  stage.setWidth(Math.max(stageMinimumWidth, maxX - stage.getX()));
                  stage.setHeight(Math.max(stageMinimumHeight, maxY - stage.getY()));
                  e.consume();
              }
          });
      }
  }
}
TOP

Related Classes of at.bestsolution.efxclipse.runtime.workbench.renderers.fx.DefWindowRenderer$MultiMessageDialog

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.