PaletteGroup.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.ge.gef.palette;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
/**
* Represents a single group in the palette.
*
* @param <G> the type of the group model object
* @param <I> the type of the palette item model object
*/
public class PaletteGroup<G, I> extends VBox {
private static final String SHARED_STYLE = "-fx-border-width: 1 0 0 0;" + "-fx-border-color: rgba(0,0,0,.2);"
+ "-fx-border-style: solid, hidden, hidden, hidden;";
private static final String IDLE_GROUP_STYLE = SHARED_STYLE
+ "-fx-background-color: linear-gradient(rgb(247,247,247),rgb(200,200,200));";
private static final String HOVER_GROUP_STYLE = SHARED_STYLE
+ "-fx-background-color: #f2f2f2;";
private static final String EXPANDED_STYLE = SHARED_STYLE
+ "-fx-background-color: #f2f2f2;";
private final ToggleButton groupButton;
private final ScrollPane scrollPane;
private final VBox items;
private boolean hover = false;
/**
* Creates a new instance
* @param model the palette model which defines the contents of the palette
* @param groupModel the group object represented by this node
*/
public PaletteGroup(final PaletteModel<G, I> model, final G groupModel) {
// Group Button
groupButton = new ToggleButton(model.getGroupLabel(groupModel));
groupButton.setStyle(IDLE_GROUP_STYLE);
groupButton.setFont(new Font(12));
groupButton.setPadding(new Insets(1, 0, 1, 2));
groupButton.setAlignment(Pos.BASELINE_LEFT);
groupButton.setGraphic(new ImageView(model.getGroupIcon(groupModel)));
groupButton.setMaxWidth(Double.MAX_VALUE);
groupButton.setOnAction(e -> refresh());
groupButton.setOnMouseEntered(e -> {
hover = true;
refresh();
});
groupButton.setOnMouseExited(e -> {
hover = false;
refresh();
});
getChildren().add(groupButton);
// Palette Items
items = new VBox(2);
items.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY)));
for (I itemModel : model.getItems(groupModel)) {
PaletteItem<I> paletteItem = new PaletteItem<>(model, itemModel);
items.getChildren().add(paletteItem);
}
// Scroll Pane
scrollPane = new ScrollPane();
scrollPane.setStyle("-fx-background: transparent; -fx-background-color: transparent; ");
scrollPane.setFitToWidth(true);
scrollPane.setPadding(Insets.EMPTY);
scrollPane.setContent(items);
getChildren().add(scrollPane);
refresh();
}
/**
* Returns whether the palette group is expanded.
* @return true if the palette group is expanded. Returns false if the palette group is collapsed.
*/
public final boolean isExpanded() {
return groupButton.isSelected();
}
private void refresh() {
final boolean expanded = groupButton.isSelected();
// Refresh button style
if (hover) {
groupButton.setStyle(HOVER_GROUP_STYLE);
} else if (expanded) {
groupButton.setStyle(EXPANDED_STYLE);
} else {
groupButton.setStyle(IDLE_GROUP_STYLE);
}
// Refresh scroll pane visibility
scrollPane.setVisible(expanded);
scrollPane.setManaged(expanded);
}
@Override
protected double computePrefWidth(final double height) {
double value = 0;
// VBar policy is updated temporarily to allow computing appropriate value
scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);
for (final Node child : getChildren()) {
value = Math.max(value, child.prefWidth(-1));
}
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
// Add some additional padding
value += 20;
return value;
}
}