forked from ikmdev/komet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/finished/iia 1328 read only component set control (ikmdev#258)
* Update version to start feature: IIA-1328-Read-Only-Component-Set-Control * Feature/IIA-1328: Implement Identicons for Read-Only Component Set Control * Update version to finish feature: IIA-1328-Read-Only-Component-Set-Control
- Loading branch information
Showing
7 changed files
with
348 additions
and
15 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
kview/src/main/java/dev/ikm/komet/kview/controls/ComponentItem.java
This file contains 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,29 @@ | ||
package dev.ikm.komet.kview.controls; | ||
|
||
import javafx.beans.property.ObjectProperty; | ||
import javafx.beans.property.SimpleObjectProperty; | ||
import javafx.beans.property.SimpleStringProperty; | ||
import javafx.beans.property.StringProperty; | ||
import javafx.scene.image.Image; | ||
|
||
public class ComponentItem { | ||
|
||
public ComponentItem() { } | ||
|
||
public ComponentItem(String text, Image icon) { | ||
this.text.set(text); | ||
this.icon.set(icon); | ||
} | ||
|
||
// -- text | ||
private StringProperty text = new SimpleStringProperty(); | ||
public String getText() { return text.get(); } | ||
public StringProperty textProperty() { return text; } | ||
public void setText(String text) { this.text.set(text); } | ||
|
||
// -- icon | ||
private ObjectProperty<Image> icon = new SimpleObjectProperty<>(); | ||
public Image getIcon() { return icon.get(); } | ||
public ObjectProperty<Image> iconProperty() { return icon; } | ||
public void setIcon(Image icon) { this.icon.set(icon); } | ||
} |
66 changes: 66 additions & 0 deletions
66
kview/src/main/java/dev/ikm/komet/kview/controls/KLReadOnlyComponentSetControl.java
This file contains 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,66 @@ | ||
package dev.ikm.komet.kview.controls; | ||
|
||
import dev.ikm.komet.kview.controls.skin.KLReadOnlyComponentSetControlSkin; | ||
import javafx.beans.property.BooleanProperty; | ||
import javafx.beans.property.ObjectProperty; | ||
import javafx.beans.property.SimpleBooleanProperty; | ||
import javafx.beans.property.SimpleObjectProperty; | ||
import javafx.beans.property.SimpleStringProperty; | ||
import javafx.beans.property.StringProperty; | ||
import javafx.collections.FXCollections; | ||
import javafx.collections.ObservableSet; | ||
import javafx.scene.control.Control; | ||
import javafx.scene.control.Skin; | ||
|
||
import java.util.function.Consumer; | ||
|
||
public class KLReadOnlyComponentSetControl extends Control { | ||
|
||
public KLReadOnlyComponentSetControl() { | ||
getStyleClass().add("read-only-component-set-control"); | ||
} | ||
|
||
// -- title | ||
private StringProperty title = new SimpleStringProperty(); | ||
public String getTitle() { return title.get(); } | ||
public StringProperty titleProperty() { return title; } | ||
public void setTitle(String title) { this.title.set(title); } | ||
|
||
// -- prompt text | ||
private StringProperty promptText = new SimpleStringProperty("[Placeholder]"); | ||
public String getPromptText() { return promptText.get(); } | ||
public StringProperty promptTextProperty() { return promptText; } | ||
public void setPromptText(String text) { this.promptText.set(text); } | ||
|
||
// -- edit mode | ||
private BooleanProperty editMode = new SimpleBooleanProperty(); | ||
public boolean isEditMode() { return editMode.get(); } | ||
public BooleanProperty editModeProperty() { return editMode; } | ||
public void setEditMode(boolean editMode) { this.editMode.set(editMode); } | ||
|
||
// -- on edit action | ||
private ObjectProperty<Runnable> onEditAction = new SimpleObjectProperty<>(); | ||
public Runnable getOnEditAction() { return onEditAction.get(); } | ||
public ObjectProperty<Runnable> onEditActionProperty() { return onEditAction; } | ||
public void setOnEditAction(Runnable onEditAction) { this.onEditAction.set(onEditAction); } | ||
|
||
// -- on remove action | ||
private ObjectProperty<Consumer<ComponentItem>> onRemoveAction = new SimpleObjectProperty<>(); | ||
public Consumer<ComponentItem> getOnRemoveAction() { return onRemoveAction.get(); } | ||
public ObjectProperty<Consumer<ComponentItem>> onRemoveActionProperty() { return onRemoveAction; } | ||
public void setOnRemoveAction(Consumer<ComponentItem> onEditAction) { this.onRemoveAction.set(onEditAction); } | ||
|
||
// items | ||
private ObservableSet<ComponentItem> items = FXCollections.observableSet(); | ||
public ObservableSet<ComponentItem> getItems() { return items; } | ||
|
||
@Override | ||
protected Skin<?> createDefaultSkin() { | ||
return new KLReadOnlyComponentSetControlSkin(this); | ||
} | ||
|
||
@Override | ||
public String getUserAgentStylesheet() { | ||
return KLReadOnlyComponentControl.class.getResource("read-only-component-set-control.css").toExternalForm(); | ||
} | ||
} |
This file contains 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
181 changes: 181 additions & 0 deletions
181
kview/src/main/java/dev/ikm/komet/kview/controls/skin/KLReadOnlyComponentSetControlSkin.java
This file contains 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,181 @@ | ||
package dev.ikm.komet.kview.controls.skin; | ||
|
||
import dev.ikm.komet.kview.controls.ComponentItem; | ||
import dev.ikm.komet.kview.controls.KLReadOnlyComponentSetControl; | ||
import dev.ikm.komet.kview.controls.KometIcon; | ||
import javafx.beans.binding.StringBinding; | ||
import javafx.collections.SetChangeListener; | ||
import javafx.css.PseudoClass; | ||
import javafx.event.ActionEvent; | ||
import javafx.event.EventHandler; | ||
import javafx.scene.Node; | ||
import javafx.scene.control.ContextMenu; | ||
import javafx.scene.control.Label; | ||
import javafx.scene.control.MenuItem; | ||
import javafx.scene.control.SeparatorMenuItem; | ||
import javafx.scene.control.SkinBase; | ||
import javafx.scene.image.ImageView; | ||
import javafx.scene.input.ContextMenuEvent; | ||
import javafx.scene.layout.HBox; | ||
import javafx.scene.layout.Priority; | ||
import javafx.scene.layout.Region; | ||
import javafx.scene.layout.VBox; | ||
|
||
import java.util.HashMap; | ||
|
||
public class KLReadOnlyComponentSetControlSkin extends SkinBase<KLReadOnlyComponentSetControl> { | ||
private final VBox mainContainer = new VBox(); | ||
|
||
private final Label titleLabel = new Label(); | ||
private final Label promptTextLabel = new Label(); | ||
|
||
private final VBox componentsContainer = new VBox(); | ||
|
||
private final HashMap<ComponentItem, Node> componentUIItems = new HashMap<>(); | ||
|
||
/** | ||
* @param control The control for which this Skin should attach to. | ||
*/ | ||
public KLReadOnlyComponentSetControlSkin(KLReadOnlyComponentSetControl control) { | ||
super(control); | ||
|
||
mainContainer.getChildren().addAll( | ||
titleLabel, | ||
componentsContainer | ||
); | ||
|
||
getChildren().add(mainContainer); | ||
|
||
// title | ||
titleLabel.textProperty().bind(new StringBinding() { | ||
{ | ||
super.bind(control.titleProperty()); | ||
} | ||
@Override | ||
protected String computeValue() { | ||
String title = control.getTitle(); | ||
if (title != null) { | ||
return control.getTitle().toUpperCase(); | ||
} else { | ||
return ""; | ||
} | ||
} | ||
}); | ||
|
||
// sync items observableSet | ||
for (ComponentItem componentItem : control.getItems()) { | ||
addNewUIItem(componentItem); | ||
} | ||
control.getItems().addListener(this::itemsChanged); | ||
|
||
// CSS | ||
mainContainer.getStyleClass().add("main-container"); | ||
componentsContainer.getStyleClass().add("components-container"); | ||
titleLabel.getStyleClass().add("title"); | ||
promptTextLabel.getStyleClass().add("prompt-text"); | ||
} | ||
|
||
private void itemsChanged(SetChangeListener.Change<? extends ComponentItem> change) { | ||
if (change.wasAdded()) { | ||
addNewUIItem(change.getElementAdded()); | ||
} else if (change.wasRemoved()) { | ||
removeUIItem(change.getElementRemoved()); | ||
} | ||
} | ||
|
||
private void addNewUIItem(ComponentItem componentItem) { | ||
Node componentUIItem = new ComponentItemNode(this, componentItem);; | ||
componentsContainer.getChildren().add(componentUIItem); | ||
componentUIItems.put(componentItem, componentUIItem); | ||
} | ||
|
||
private void removeUIItem(ComponentItem componentItem) { | ||
Node componentUIItem = componentUIItems.get(componentItem); | ||
componentsContainer.getChildren().remove(componentUIItem); | ||
componentUIItems.remove(componentItem); | ||
} | ||
|
||
private static MenuItem createMenuItem(String text, KometIcon.IconValue icon, EventHandler<ActionEvent> actionHandler) { | ||
MenuItem menuItem = new MenuItem(text, KometIcon.create(icon, "icon-klcontext-menu")); | ||
menuItem.setOnAction(actionHandler); | ||
return menuItem; | ||
} | ||
|
||
protected void fireOnEditAction(ActionEvent actionEvent) { | ||
if (getSkinnable().getOnEditAction() != null) { | ||
getSkinnable().getOnEditAction().run(); | ||
} | ||
} | ||
|
||
protected void fireOnRmoveAction(ActionEvent actionEvent, ComponentItem componentItem) { | ||
if (getSkinnable().getOnRemoveAction() != null) { | ||
getSkinnable().getOnRemoveAction().accept(componentItem); | ||
} | ||
} | ||
|
||
/******************************************************************************* | ||
* * | ||
* Supporting Classes * | ||
* * | ||
******************************************************************************/ | ||
|
||
public static class ComponentItemNode extends Region { | ||
private static final PseudoClass EDIT_MODE_PSEUDO_CLASS = PseudoClass.getPseudoClass("edit-mode"); | ||
|
||
private final HBox container = new HBox(); | ||
private final ImageView iconImageView = new ImageView(); | ||
private final Label textLabel = new Label(); | ||
|
||
private ContextMenu contextMenu = new ContextMenu(); | ||
|
||
public ComponentItemNode(KLReadOnlyComponentSetControlSkin componentSetControlSkin, ComponentItem componentItem) { | ||
// Image View | ||
iconImageView.imageProperty().bind(componentItem.iconProperty()); | ||
iconImageView.setFitHeight(20); | ||
iconImageView.setFitWidth(20); | ||
|
||
// Label (Image View Icon + Text) | ||
textLabel.textProperty().bind(componentItem.textProperty()); | ||
|
||
container.getChildren().addAll(iconImageView, textLabel); | ||
getChildren().add(container); | ||
|
||
textLabel.setMaxWidth(Double.MAX_VALUE); | ||
HBox.setHgrow(textLabel, Priority.ALWAYS); | ||
|
||
|
||
contextMenu.getStyleClass().add("klcontext-menu"); | ||
contextMenu.getItems().addAll( | ||
createMenuItem("Edit Set", KometIcon.IconValue.PENCIL, componentSetControlSkin::fireOnEditAction), | ||
new SeparatorMenuItem(), | ||
createMenuItem("Remove", KometIcon.IconValue.TRASH, actionEvent -> componentSetControlSkin.fireOnRmoveAction(actionEvent, componentItem)) | ||
); | ||
|
||
setOnContextMenuRequested(this::onContextMenuRequested); | ||
|
||
// CSS | ||
getStyleClass().add("component-item"); | ||
container.getStyleClass().add("container"); | ||
} | ||
|
||
private void onContextMenuRequested(ContextMenuEvent contextMenuEvent) { | ||
pseudoClassStateChanged(EDIT_MODE_PSEUDO_CLASS, true); | ||
|
||
contextMenu.setOnHidden(event -> pseudoClassStateChanged(EDIT_MODE_PSEUDO_CLASS, false)); | ||
contextMenu.show(this, contextMenuEvent.getScreenX(), contextMenuEvent.getScreenY()); | ||
} | ||
|
||
@Override | ||
protected void layoutChildren() { | ||
double leftInsets = snappedLeftInset(); | ||
double rightInsets = snappedRightInset(); | ||
double topInsets = snappedTopInset(); | ||
double bottomInsets = snappedBottomInset(); | ||
double width = getWidth(); | ||
double height = getHeight(); | ||
|
||
container.resizeRelocate(leftInsets, topInsets, | ||
width - leftInsets - rightInsets, height - topInsets - bottomInsets); | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
Oops, something went wrong.