-
Notifications
You must be signed in to change notification settings - Fork 870
将 JFXTextField 右键菜单改为 JFX 样式 #5292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
The head ref may contain hidden characters: "\u8FD0\u5E37\u5E44\u82F1\u96C4\u51E0\u62C2\u8896\u9634\u8C0B\u9633\u8C0B\u660E\u4EC7\u6697\u6597\u5316\u4F5C\u4E00\u6C5F\u6D4A\u6D6A\u4E1C\u6D41"
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
414141c
UPDATE
CiiLu bb23123
UPDATE
CiiLu 67da0f5
UPDATE
CiiLu 19071aa
feat: JFXPasswordField
CiiLu b85cbb9
update
CiiLu 8ad0792
update
CiiLu 557ea29
update
CiiLu 2195cd1
update
CiiLu 2adad0f
update
CiiLu 97d2110
fix: redo
CiiLu c827336
update
CiiLu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
357 changes: 357 additions & 0 deletions
357
HMCL/src/main/java/com/jfoenix/controls/JFXComboBox.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,357 @@ | ||
| /* | ||
| * 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 com.jfoenix.converters.base.NodeConverter; | ||
| import com.jfoenix.skins.JFXComboBoxListViewSkin; | ||
| import javafx.beans.property.ObjectProperty; | ||
| import javafx.beans.property.SimpleObjectProperty; | ||
| import javafx.collections.ObservableList; | ||
| import javafx.css.*; | ||
| import javafx.css.converter.BooleanConverter; | ||
| import javafx.css.converter.PaintConverter; | ||
| import javafx.geometry.Insets; | ||
| import javafx.geometry.Pos; | ||
| import javafx.scene.Node; | ||
| import javafx.scene.control.*; | ||
| import javafx.scene.layout.Background; | ||
| import javafx.scene.layout.BackgroundFill; | ||
| import javafx.scene.layout.StackPane; | ||
| import javafx.scene.paint.Color; | ||
| import javafx.scene.paint.Paint; | ||
| import javafx.util.StringConverter; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| import static org.jackhuang.hmcl.ui.FXUtils.useJFXContextMenu; | ||
|
|
||
| /** | ||
| * JFXComboBox is the material design implementation of a combobox. | ||
| * | ||
| * @author Shadi Shaheen | ||
| * @version 1.0 | ||
| * @since 2016-03-09 | ||
| */ | ||
| public class JFXComboBox<T> extends ComboBox<T> { | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public JFXComboBox() { | ||
| initialize(); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public JFXComboBox(ObservableList<T> items) { | ||
| super(items); | ||
| initialize(); | ||
| } | ||
|
|
||
| private void initialize() { | ||
| getStyleClass().add(DEFAULT_STYLE_CLASS); | ||
| this.setCellFactory(listView -> new JFXListCell<T>() { | ||
| @Override | ||
| public void updateItem(T item, boolean empty) { | ||
| super.updateItem(item, empty); | ||
| updateDisplayText(this, item, empty); | ||
| } | ||
| }); | ||
|
|
||
| // had to refactor the code out of the skin class to allow | ||
| // customization of the button cell | ||
| this.setButtonCell(new ListCell<T>() { | ||
| { | ||
| // fixed clearing the combo box value is causing | ||
| // java prompt text to be shown because the button cell is not updated | ||
| JFXComboBox.this.valueProperty().addListener(observable -> { | ||
| if (JFXComboBox.this.getValue() == null) { | ||
| updateItem(null, true); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| @Override | ||
| protected void updateItem(T item, boolean empty) { | ||
| updateDisplayText(this, item, empty); | ||
| this.setVisible(item != null || !empty); | ||
| } | ||
|
|
||
| }); | ||
|
|
||
| useJFXContextMenu(editorProperty().get()); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| protected Skin<?> createDefaultSkin() { | ||
| return new JFXComboBoxListViewSkin<T>(this); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize the style class to 'jfx-combo-box'. | ||
| * <p> | ||
| * This is the selector class from which CSS can be used to style | ||
| * this control. | ||
| */ | ||
| private static final String DEFAULT_STYLE_CLASS = "jfx-combo-box"; | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * Node Converter Property * | ||
| * * | ||
| **************************************************************************/ | ||
| /** | ||
| * Converts the user-typed input (when the ComboBox is | ||
| * {@link #editableProperty() editable}) to an object of type T, such that | ||
| * the input may be retrieved via the {@link #valueProperty() value} property. | ||
| */ | ||
| public ObjectProperty<NodeConverter<T>> nodeConverterProperty() { | ||
| return nodeConverter; | ||
| } | ||
|
|
||
| private ObjectProperty<NodeConverter<T>> nodeConverter = new SimpleObjectProperty<>(this, "nodeConverter", | ||
| JFXComboBox.<T>defaultNodeConverter()); | ||
|
|
||
| public final void setNodeConverter(NodeConverter<T> value) { | ||
| nodeConverterProperty().set(value); | ||
| } | ||
|
|
||
| public final NodeConverter<T> getNodeConverter() { | ||
| return nodeConverterProperty().get(); | ||
| } | ||
|
|
||
| private static <T> NodeConverter<T> defaultNodeConverter() { | ||
| return new NodeConverter<T>() { | ||
| @Override | ||
| public Node toNode(T object) { | ||
| if (object == null) { | ||
| return null; | ||
| } | ||
| StackPane selectedValueContainer = new StackPane(); | ||
| selectedValueContainer.getStyleClass().add("combo-box-selected-value-container"); | ||
| selectedValueContainer.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, null, null))); | ||
| Label selectedValueLabel = object instanceof Label ? new Label(((Label) object).getText()) : new Label( | ||
| object.toString()); | ||
| selectedValueLabel.setTextFill(Color.BLACK); | ||
| selectedValueContainer.getChildren().add(selectedValueLabel); | ||
| StackPane.setAlignment(selectedValueLabel, Pos.CENTER_LEFT); | ||
| StackPane.setMargin(selectedValueLabel, new Insets(0, 0, 0, 5)); | ||
| return selectedValueContainer; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| @Override | ||
| public T fromNode(Node node) { | ||
| return (T) node; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString(T object) { | ||
| if (object == null) { | ||
| return null; | ||
| } | ||
| if (object instanceof Label) { | ||
| return ((Label) object).getText(); | ||
| } | ||
| return object.toString(); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| private boolean updateDisplayText(ListCell<T> cell, T item, boolean empty) { | ||
| if (empty) { | ||
| // create empty cell | ||
| if (cell == null) { | ||
| return true; | ||
| } | ||
| cell.setGraphic(null); | ||
| cell.setText(null); | ||
| return true; | ||
| } else if (item instanceof Node) { | ||
| Node currentNode = cell.getGraphic(); | ||
|
CiiLu marked this conversation as resolved.
|
||
| Node newNode = (Node) item; | ||
| // create a node from the selected node of the listview | ||
| // using JFXComboBox {@link #nodeConverterProperty() NodeConverter}) | ||
| NodeConverter<T> nc = this.getNodeConverter(); | ||
| Node node = nc == null ? null : nc.toNode(item); | ||
| if (currentNode == null || !currentNode.equals(newNode)) { | ||
| cell.setText(null); | ||
| cell.setGraphic(node == null ? newNode : node); | ||
| } | ||
| return node == null; | ||
| } else { | ||
| // run item through StringConverter if it isn't null | ||
| StringConverter<T> c = this.getConverter(); | ||
| String s = item == null ? this.getPromptText() : (c == null ? item.toString() : c.toString(item)); | ||
| cell.setText(s); | ||
|
CiiLu marked this conversation as resolved.
|
||
| cell.setGraphic(null); | ||
| return s == null || s.isEmpty(); | ||
| } | ||
| } | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * styleable Properties * | ||
| * * | ||
| **************************************************************************/ | ||
|
|
||
| /** | ||
| * set true to show a float the prompt text when focusing the field | ||
| */ | ||
| private StyleableBooleanProperty labelFloat = new SimpleStyleableBooleanProperty(StyleableProperties.LABEL_FLOAT, | ||
| JFXComboBox.this, | ||
| "lableFloat", | ||
|
CiiLu marked this conversation as resolved.
|
||
| false); | ||
|
|
||
| public final StyleableBooleanProperty labelFloatProperty() { | ||
| return this.labelFloat; | ||
| } | ||
|
|
||
| public final boolean isLabelFloat() { | ||
| return this.labelFloatProperty().get(); | ||
| } | ||
|
|
||
| public final void setLabelFloat(final boolean labelFloat) { | ||
| this.labelFloatProperty().set(labelFloat); | ||
| } | ||
|
|
||
| /** | ||
| * default color used when the field is unfocused | ||
| */ | ||
| private StyleableObjectProperty<Paint> unFocusColor = new SimpleStyleableObjectProperty<>(StyleableProperties.UNFOCUS_COLOR, | ||
| JFXComboBox.this, | ||
| "unFocusColor", | ||
| Color.rgb(77, | ||
| 77, | ||
| 77)); | ||
|
|
||
| public Paint getUnFocusColor() { | ||
| return unFocusColor == null ? Color.rgb(77, 77, 77) : unFocusColor.get(); | ||
| } | ||
|
|
||
| public StyleableObjectProperty<Paint> unFocusColorProperty() { | ||
| return this.unFocusColor; | ||
| } | ||
|
|
||
| public void setUnFocusColor(Paint color) { | ||
| this.unFocusColor.set(color); | ||
| } | ||
|
|
||
| /** | ||
| * default color used when the field is focused | ||
| */ | ||
| private StyleableObjectProperty<Paint> focusColor = new SimpleStyleableObjectProperty<>(StyleableProperties.FOCUS_COLOR, | ||
| JFXComboBox.this, | ||
| "focusColor", | ||
| Color.valueOf("#4059A9")); | ||
|
|
||
| public Paint getFocusColor() { | ||
| return focusColor == null ? Color.valueOf("#4059A9") : focusColor.get(); | ||
| } | ||
|
|
||
| public StyleableObjectProperty<Paint> focusColorProperty() { | ||
| return this.focusColor; | ||
| } | ||
|
|
||
| public void setFocusColor(Paint color) { | ||
| this.focusColor.set(color); | ||
| } | ||
|
|
||
| private final static class StyleableProperties { | ||
| private static final CssMetaData<JFXComboBox<?>, Paint> UNFOCUS_COLOR = new CssMetaData<JFXComboBox<?>, Paint>( | ||
| "-jfx-unfocus-color", | ||
| PaintConverter.getInstance(), | ||
| Color.valueOf("#A6A6A6")) { | ||
|
CiiLu marked this conversation as resolved.
|
||
| @Override | ||
| public boolean isSettable(JFXComboBox<?> control) { | ||
| return control.unFocusColor == null || !control.unFocusColor.isBound(); | ||
| } | ||
|
|
||
| @Override | ||
| public StyleableProperty<Paint> getStyleableProperty(JFXComboBox<?> control) { | ||
| return control.unFocusColorProperty(); | ||
| } | ||
| }; | ||
| private static final CssMetaData<JFXComboBox<?>, Paint> FOCUS_COLOR = new CssMetaData<JFXComboBox<?>, Paint>( | ||
| "-jfx-focus-color", | ||
| PaintConverter.getInstance(), | ||
| Color.valueOf("#3f51b5")) { | ||
|
CiiLu marked this conversation as resolved.
|
||
| @Override | ||
| public boolean isSettable(JFXComboBox<?> control) { | ||
| return control.focusColor == null || !control.focusColor.isBound(); | ||
| } | ||
|
|
||
| @Override | ||
| public StyleableProperty<Paint> getStyleableProperty(JFXComboBox<?> control) { | ||
| return control.focusColorProperty(); | ||
| } | ||
| }; | ||
| private static final CssMetaData<JFXComboBox<?>, Boolean> LABEL_FLOAT = new CssMetaData<JFXComboBox<?>, Boolean>( | ||
| "-jfx-label-float", | ||
| BooleanConverter.getInstance(), | ||
| false) { | ||
| @Override | ||
| public boolean isSettable(JFXComboBox<?> control) { | ||
| return control.labelFloat == null || !control.labelFloat.isBound(); | ||
| } | ||
|
|
||
| @Override | ||
| public StyleableBooleanProperty getStyleableProperty(JFXComboBox<?> control) { | ||
| return control.labelFloatProperty(); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| private static final List<CssMetaData<? extends Styleable, ?>> CHILD_STYLEABLES; | ||
|
|
||
| static { | ||
| final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>( | ||
| Control.getClassCssMetaData()); | ||
| Collections.addAll(styleables, UNFOCUS_COLOR, FOCUS_COLOR, LABEL_FLOAT); | ||
| CHILD_STYLEABLES = Collections.unmodifiableList(styleables); | ||
| } | ||
| } | ||
|
|
||
| // inherit the styleable properties from parent | ||
| private List<CssMetaData<? extends Styleable, ?>> STYLEABLES; | ||
|
|
||
| @Override | ||
| public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { | ||
| if (STYLEABLES == null) { | ||
| final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>( | ||
| Control.getClassCssMetaData()); | ||
| styleables.addAll(getClassCssMetaData()); | ||
| styleables.addAll(Control.getClassCssMetaData()); | ||
|
CiiLu marked this conversation as resolved.
|
||
| STYLEABLES = Collections.unmodifiableList(styleables); | ||
| } | ||
| return STYLEABLES; | ||
| } | ||
|
|
||
| public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { | ||
| return StyleableProperties.CHILD_STYLEABLES; | ||
| } | ||
| } | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.