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

com.jfoenix.controls.JFXAutoCompletePopup Maven / Gradle / Ivy

There is a newer version: 17-0.1.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.jfoenix.controls;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

import com.jfoenix.controls.events.JFXAutoCompleteEvent;
import com.jfoenix.skins.JFXAutoCompletePopupSkin;
import com.sun.javafx.stage.PopupWindowHelper;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.css.CssMetaData;
import javafx.css.SimpleStyleableDoubleProperty;
import javafx.css.SimpleStyleableIntegerProperty;
import javafx.css.Styleable;
import javafx.css.StyleableProperty;
import javafx.css.converter.SizeConverter;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.PopupControl;
import javafx.scene.control.Skin;
import javafx.scene.layout.Region;
import javafx.stage.Window;
import javafx.util.Callback;

/**
 * JFXAutoCompletePopup is an animated popup list view that allow filtering suggestions according to
 * some predicate.
 *
 * @author Shadi Shaheen
 * @version 1.1.0
 * @since 2018-02-01
 */
public class JFXAutoCompletePopup extends PopupControl
{

   private final ObservableList suggestions = FXCollections.observableArrayList();
   private final ObjectProperty>> selectionHandler = new SimpleObjectProperty<>();
   private final FilteredList filteredData = new FilteredList(suggestions, s -> true);
   private final ObjectProperty, ListCell>> suggestionsCellFactory = new SimpleObjectProperty, ListCell>>();

   private static final String DEFAULT_STYLE_CLASS = "jfx-autocomplete-popup";

   public JFXAutoCompletePopup()
   {
      super();
      bridge = new CSSBridge();
      PopupWindowHelper.getContent(this).setAll(new Node[] {this.bridge});
      setAutoFix(true);
      setAutoHide(true);
      setHideOnEscape(true);
      getStyleClass().add(DEFAULT_STYLE_CLASS);
   }

   @Override
   protected Skin createDefaultSkin()
   {
      return new JFXAutoCompletePopupSkin(this);
   }

   public void show(Node node)
   {
      if (!isShowing())
      {
         if (node.getScene() == null || node.getScene().getWindow() == null)
            throw new IllegalStateException("Can not show popup. The node must be attached to a scene/window.");
         Window parent = node.getScene().getWindow();
         this.show(parent,
                   parent.getX() + node.localToScene(0, 0).getX() + node.getScene().getX(),
                   parent.getY() + node.localToScene(0, 0).getY() + node.getScene().getY() + ((Region) node).getHeight());
         ((JFXAutoCompletePopupSkin) getSkin()).animate();
      }
   }

   public ObservableList getSuggestions()
   {
      return suggestions;
   }

   public void filter(Predicate predicate)
   {
      filteredData.setPredicate(predicate);
   }

   public ObservableList getFilteredSuggestions()
   {
      return filteredData;
   }

   public EventHandler> getSelectionHandler()
   {
      return selectionHandler.get();
   }

   public void setSelectionHandler(EventHandler> selectionHandler)
   {
      this.selectionHandler.set(selectionHandler);
   }

   public final ObjectProperty, ListCell>> suggestionsCellFactoryProperty()
   {
      return this.suggestionsCellFactory;
   }

   public final Callback, ListCell> getSuggestionsCellFactory()
   {
      return this.suggestionsCellFactoryProperty().get();
   }

   public final void setSuggestionsCellFactory(final javafx.util.Callback, ListCell> suggestionsCellFactory)
   {
      this.suggestionsCellFactoryProperty().set(suggestionsCellFactory);
   }

   /**
    * limits the number of cells to be shown, used to compute the list size
    */
   private IntegerProperty cellLimit = new SimpleStyleableIntegerProperty(StyleableProperties.CELL_LIMIT, JFXAutoCompletePopup.this, "cellLimit", 10);

   public final void setCellLimit(int value)
   {
      cellLimitProperty().set(value);
   }

   public final int getCellLimit()
   {
      return cellLimitProperty().get();
   }

   public final IntegerProperty cellLimitProperty()
   {
      return cellLimit;
   }

   /**
    * cell size, used to compute the list size
    */
   private DoubleProperty fixedCellSize = new SimpleStyleableDoubleProperty(StyleableProperties.FIXED_CELL_SIZE,
                                                                            JFXAutoCompletePopup.this,
                                                                            "fixedCellSize",
                                                                            24d);

   public final void setFixedCellSize(double value)
   {
      fixedCellSizeProperty().set(value);
   }

   public final double getFixedCellSize()
   {
      return fixedCellSizeProperty().get();
   }

   public final DoubleProperty fixedCellSizeProperty()
   {
      return fixedCellSize;
   }

   private final class CSSBridge extends PopupControl.CSSBridge
   {
      private JFXAutoCompletePopup popup = JFXAutoCompletePopup.this;

      CSSBridge()
      {
         super();
      }
   }

   private static class StyleableProperties
   {
      private static final CssMetaData FIXED_CELL_SIZE = new CssMetaData("-fx-fixed-cell-size",
                                                                                                                                                         SizeConverter.getInstance(),
                                                                                                                                                         24)
      {
         @Override
         public Double getInitialValue(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return bridge.popup.getFixedCellSize();
         }

         @Override
         public boolean isSettable(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return bridge.popup.fixedCellSize == null || !bridge.popup.fixedCellSize.isBound();
         }

         @Override
         public StyleableProperty getStyleableProperty(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return (StyleableProperty) bridge.popup.fixedCellSizeProperty();
         }
      };
      private static final CssMetaData CELL_LIMIT = new CssMetaData("-jfx-cell-limit",
                                                                                                                                                    SizeConverter.getInstance(),
                                                                                                                                                    10)
      {
         @Override
         public Number getInitialValue(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return bridge.popup.getCellLimit();
         }

         @Override
         public boolean isSettable(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return bridge.popup.cellLimit == null || !bridge.popup.cellLimit.isBound();
         }

         @Override
         public StyleableProperty getStyleableProperty(JFXAutoCompletePopup.CSSBridge bridge)
         {
            return (StyleableProperty) bridge.popup.cellLimitProperty();
         }
      };

      private static final List> STYLEABLES;

      static
      {
         final List> styleables = new ArrayList<>(PopupControl.getClassCssMetaData());
         styleables.add(FIXED_CELL_SIZE);
         styleables.add(CELL_LIMIT);
         STYLEABLES = Collections.unmodifiableList(styleables);
      }
   }

   public static List> getClassCssMetaData()
   {
      return StyleableProperties.STYLEABLES;
   }

   @Override
   public List> getCssMetaData()
   {
      return getClassCssMetaData();
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy