All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mmm.ui.fx.widget.window.FxAbstractWindow Maven / Gradle / Ivy

The newest version!
/* Copyright (c) The m-m-m Team, Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0 */
package io.github.mmm.ui.fx.widget.window;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import io.github.mmm.ui.api.attribute.AttributeWriteMaximized;
import io.github.mmm.ui.api.attribute.AttributeWriteMinimized;
import io.github.mmm.ui.api.attribute.AttributeWritePositionRange;
import io.github.mmm.ui.api.attribute.AttributeWriteSizeRange;
import io.github.mmm.ui.api.datatype.UiEnabledFlags;
import io.github.mmm.ui.api.event.UiHideEvent;
import io.github.mmm.ui.api.event.UiShowEvent;
import io.github.mmm.ui.api.widget.UiRegularWidget;
import io.github.mmm.ui.api.widget.composite.UiComposite;
import io.github.mmm.ui.api.widget.window.UiAbstractWindow;
import io.github.mmm.ui.api.widget.window.UiPopup;
import io.github.mmm.ui.fx.FxApplication;
import io.github.mmm.ui.fx.widget.FxWidget;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

/**
 * Implementation of {@link UiAbstractWindow} for JavaFx.
 *
 * @since 1.0.0
 */
public abstract class FxAbstractWindow extends FxWidget
    implements UiAbstractWindow, AttributeWriteMinimized, AttributeWriteMaximized {

  private static Logger LOG = Logger.getLogger(FxAbstractWindow.class.getName());

  /** The optional {@link ScrollPane} if {@link #isScrollable() scrollable}. */
  protected final ScrollPane scrollPane;

  /** The {@link Stage#getScene() scene}. */
  protected final Scene scene;

  /** The composite where to add children. */
  protected final VBox composite;

  /** @see #getChild(int) */
  protected final List children;

  /**
   * @see #getPosition()
   * @see #getSize()
   */
  protected final FxAbstractWindowPositionAndSize positionAndSize;

  /**
   * The constructor.
   *
   * @param widget the {@link #getWidget() JavaFx widget}.
   */
  public FxAbstractWindow(Stage widget) {

    super(widget);
    this.children = new ArrayList<>();
    this.positionAndSize = new FxAbstractWindowPositionAndSize(widget);
    this.composite = new VBox();
    if (isScrollable()) {
      this.scrollPane = new ScrollPane(this.composite);
      this.scene = new Scene(this.scrollPane);
    } else {
      this.scrollPane = null;
      this.scene = new Scene(this.composite);
    }

    try {
      Enumeration stylesheets = ClassLoader.getSystemResources(FxApplication.CSS_LOCATION);
      if (stylesheets.hasMoreElements()) {
        while (stylesheets.hasMoreElements()) {
          URL url = stylesheets.nextElement();
          String stylesheetUri = url.toExternalForm();
          this.scene.getStylesheets().add(stylesheetUri);
        }
      } else {
        LOG.warning("Could not find stylesheet at " + FxApplication.CSS_LOCATION);
      }
    } catch (IOException e) {
      LOG.log(Level.SEVERE, "Error while trying to load stylesheet from " + FxApplication.CSS_LOCATION, e);
      e.printStackTrace();
    }
    widget.setScene(this.scene);
  }

  @Override
  protected boolean isInitiallyVisible() {

    return false;
  }

  @Override
  protected boolean isVisibleWithoutRoot() {

    return true;
  }

  @Override
  public UiAbstractWindow getParent() {

    return (UiAbstractWindow) super.getParent();
  }

  @Override
  protected void setParent(UiComposite parent) {

    assert ((parent == null) || (parent instanceof UiAbstractWindow));
    super.setParent(parent);
  }

  /**
   * @return {@code true} to use a {@link ScrollPane} and allow the content to scroll, {@code false} otherwise.
   */
  protected boolean isScrollable() {

    return (this instanceof UiPopup);
  }

  @Override
  protected void registerHandlers() {

    super.registerHandlers();
    this.widget.setOnHidden(this::onHidden);
    this.widget.setOnShown(this::onShown);
  }

  private void onHidden(WindowEvent event) {

    fireEvent(new UiHideEvent(this, getProgrammaticEventType() == UiHideEvent.TYPE));
  }

  private void onShown(WindowEvent event) {

    fireEvent(new UiShowEvent(this, getProgrammaticEventType() == UiShowEvent.TYPE));
  }

  @Override
  public Stage getWidget() {

    return this.widget;
  }

  @Override
  protected void setIdNative(String id) {

    // not supported by Stage or Scene...
  }

  @Override
  protected void setVisibleNative(boolean visible) {

    if (visible) {
      this.positionAndSize.centerOnScreen(false);
      this.widget.show();
    } else {
      this.widget.hide();
    }
  }

  @Override
  protected void setTooltipNative(String newTooltip) {

    // currently not supported...
  }

  @Override
  public AttributeWritePositionRange getPosition() {

    return this.positionAndSize;
  }

  @Override
  public AttributeWriteSizeRange getSize() {

    return this.positionAndSize;
  }

  @Override
  public boolean isResizable() {

    return this.widget.isResizable();
  }

  @Override
  public void setResizable(boolean resizable) {

    this.widget.setResizable(resizable);
  }

  @Override
  public String getTitle() {

    String title = this.widget.getTitle();
    if (title == null) {
      title = "";
    }
    return title;
  }

  @Override
  public void setTitle(String title) {

    this.widget.setTitle(title);
  }

  @Override
  protected void setEnabledNative(boolean enabled) {

    for (UiRegularWidget child : this.children) {
      child.setEnabled(enabled, UiEnabledFlags.PARENT);
    }
  }

  /**
   * @return the offset for the composite if internal widgets are on top.
   */
  protected int getChildOffset() {

    return 0;
  }

  @Override
  public int getChildCount() {

    return this.children.size();
  }

  @Override
  public UiRegularWidget getChild(int index) {

    if ((index < 0) || (index >= this.children.size())) {
      return null;
    }
    return this.children.get(index);
  }

  @Override
  public int getChildIndex(UiRegularWidget child) {

    if (child == null) {
      return -1;
    }
    return this.children.indexOf(child);
  }

  @Override
  public void addChild(UiRegularWidget child, int index) {

    setParent(child, this);
    if (index == -1) {
      index = this.children.size();
    }
    this.composite.getChildren().add(index + getChildOffset(), getTopNode(child));
    this.children.add(index, child);
  }

  @Override
  public UiRegularWidget removeChild(int index) {

    UiRegularWidget child = this.children.remove(index);
    this.composite.getChildren().remove(index + getChildOffset());
    setParent(child, null);
    return child;
  }

  @Override
  public boolean isMaximized() {

    return this.widget.isMaximized();
  }

  @Override
  public void setMaximized(boolean maximized) {

    this.widget.setMaximized(maximized);
  }

  @Override
  public boolean isMinimized() {

    return this.widget.isIconified();
  }

  @Override
  public void setMinimized(boolean minimized) {

    this.widget.setIconified(minimized);
  }

  @Override
  protected final void doDispose() {

    setVisible(false);
    super.doDispose();
    this.widget.setOnHidden(null);
    this.widget.setOnShown(null);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy