Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### Railroad ###
.railroad/

### NetBeans ###
/nbproject/private/
/nbbuild/
Expand All @@ -47,4 +50,4 @@ bin/
*.class

### Logs ###
hs_err_pid*.log
hs_err_pid*.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
implementation-class=dev.railroadide.railroadplugin.RailroadProjectPlugin
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ dependencies {
implementation 'org.apache.maven:maven-repository-metadata:4.0.0-rc-4'
implementation 'org.codehaus.plexus:plexus-container-default:2.1.1'

implementation 'dev.railroadide:java-version-extractor-plugin:1.0.0'
implementation 'dev.railroadide:fabric-extractor-plugin:1.0.0'
implementation 'dev.railroadide:RailroadGradlePlugin:1.0.0'

implementation 'io.get-coursier:interface:1.0.29-M1'
implementation 'org.eclipse.jgit:org.eclipse.jgit:7.4.0.202509020913-r'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@
* Supports different sizes, styles, and icon integration.
*/
public class RRButton extends Button {

public static final String[] DEFAULT_STYLE_CLASSES = { "rr-button", "button" };
public static final String[] DEFAULT_STYLE_CLASSES = {"rr-button", "button"};

private FontIcon icon;

private Node originalGraphic;
private FontIcon loadingSpinner;

private final BooleanProperty isLoading = new SimpleBooleanProperty(this, "isLoading", false);

public boolean getIsLoading() {
return isLoading.get();
}

private final LocalizedTextProperty localizedText = new LocalizedTextProperty(this, "localizedText", null);

private final BooleanProperty isSquare = new SimpleBooleanProperty(this, "isSquare", false);
Expand Down Expand Up @@ -124,7 +124,7 @@ public static RRButton warning(String text) {

protected void initialize(String localizationKey, Object... args) {
getStyleClass().setAll(RRButton.DEFAULT_STYLE_CLASSES);

setAlignment(Pos.CENTER);
setPadding(new Insets(8, 16, 8, 16));

Expand Down
278 changes: 227 additions & 51 deletions railroad-core/src/main/java/dev/railroadide/core/ui/RRToggleButton.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@
import org.kordamp.ikonli.fontawesome6.FontAwesomeSolid;
import org.kordamp.ikonli.javafx.FontIcon;

import dev.railroadide.core.ui.localized.LocalizedTextProperty;
import javafx.animation.ScaleTransition;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ToggleButton;
import javafx.util.Duration;
import dev.railroadide.core.ui.localized.LocalizedTextProperty;
import dev.railroadide.core.ui.styling.ButtonSize;
import dev.railroadide.core.ui.styling.ButtonVariant;
import javafx.animation.ScaleTransition;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ToggleButton;
import javafx.util.Duration;

public class RRToggleButton extends ToggleButton {

Expand All @@ -28,7 +33,12 @@ public boolean getIsLoading() {
return isLoading.get();
}

private final LocalizedTextProperty localizedText = new LocalizedTextProperty(this, "localizedText", null);
private final LocalizedTextProperty localizedText = new LocalizedTextProperty(this, "localizedText", null);
private final BooleanProperty isSquare = new SimpleBooleanProperty(this, "isSquare", false);
private final BooleanProperty isOutlined = new SimpleBooleanProperty(this, "isOutlined", false);
private final BooleanProperty isFlat = new SimpleBooleanProperty(this, "isFlat", false);
private final ObjectProperty<ButtonVariant> variant = new SimpleObjectProperty<>(this, "variant", ButtonVariant.PRIMARY);
private final ObjectProperty<ButtonSize> size = new SimpleObjectProperty<>(this, "size", ButtonSize.MEDIUM);

public RRToggleButton() {
this("");
Expand All @@ -48,16 +58,71 @@ public RRToggleButton(String localizationKey, Node graphic, Object... args) {
setGraphic(graphic);
}

public RRToggleButton(String localizationKey, Object... args) {
super();

initialize(localizationKey, args);
}

protected void initialize(String localizationKey, Object... args) {
getStyleClass().setAll(RRToggleButton.DEFAULT_STYLE_CLASSES);

setPadding(new Insets(8, 16, 8, 16));
public RRToggleButton(String localizationKey, Object... args) {
super();

initialize(localizationKey, args);
}

/**
* Create a primary toggle button
*/
public static RRToggleButton primary(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.PRIMARY);
return button;
}

/**
* Create a secondary toggle button
*/
public static RRToggleButton secondary(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.SECONDARY);
return button;
}

/**
* Create a ghost toggle button
*/
public static RRToggleButton ghost(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.GHOST);
return button;
}

/**
* Create a danger toggle button
*/
public static RRToggleButton danger(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.DANGER);
return button;
}

/**
* Create a success toggle button
*/
public static RRToggleButton success(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.SUCCESS);
return button;
}

/**
* Create a warning toggle button
*/
public static RRToggleButton warning(String text) {
var button = new RRToggleButton(text);
button.setVariant(ButtonVariant.WARNING);
return button;
}

protected void initialize(String localizationKey, Object... args) {
getStyleClass().setAll(RRToggleButton.DEFAULT_STYLE_CLASSES);

setAlignment(Pos.CENTER);
setPadding(new Insets(8, 16, 8, 16));

textProperty().bindBidirectional(localizedText);
localizedText.setTranslation(localizationKey, args);
Expand All @@ -84,16 +149,23 @@ protected void initialize(String localizationKey, Object... args) {
}
});

isLoading.addListener($ -> {
if (getIsLoading()) {
onLoading();
} else {
onNotLoading();
}
});

updateContent();
}
isLoading.addListener($ -> {
if (getIsLoading()) {
onLoading();
} else {
onNotLoading();
}
});

variant.addListener($ -> updateStyle());
size.addListener($ -> updateStyle());
isSquare.addListener($ -> updateStyle());
isOutlined.addListener($ -> updateStyle());
isFlat.addListener($ -> updateStyle());

updateStyle();
updateContent();
}

/**
* Set the button text using a localization key with optional formatting arguments.
Expand All @@ -102,14 +174,28 @@ protected void initialize(String localizationKey, Object... args) {
* @param localizationKey the localization key for the text
* @param args optional formatting arguments for the localized text
*/
public void setLocalizedText(String localizationKey, Object... args) {
localizedText.setTranslation(localizationKey, args);
}

/**
* Set an icon for the button
*/
public void setIcon(Ikon iconCode) {
public void setLocalizedText(String localizationKey, Object... args) {
localizedText.setTranslation(localizationKey, args);
}

/**
* Set the button variant
*/
public void setVariant(ButtonVariant variant) {
this.variant.set(variant);
}

/**
* Set the button size
*/
public void setButtonSize(ButtonSize size) {
this.size.set(size);
}

/**
* Set an icon for the button
*/
public void setIcon(Ikon iconCode) {
if (icon != null && getGraphic() == icon) {
setGraphic(null);
}
Expand All @@ -127,13 +213,71 @@ public void setIcon(Ikon iconCode) {
}
}

/**
* Set loading state for the button
*/
public void setLoading(boolean loading) {
isLoading.set(loading);
}

/**
* Set loading state for the button.
* <p>
* When loading is true:
* - The button becomes disabled and shows a spinning icon
* - The text changes to "Loading..." if there was original text
* - The button gets a "loading" CSS class for styling
* - Click animations are disabled during loading
* <p>
* When loading is false:
* - The button is re-enabled and shows the original content
* - Original text and icon are restored
* - The "loading" CSS class is removed
* <p>
* Example usage:
* <pre>
* RRToggleButton button = RRToggleButton.primary("Save");
* button.setOnAction(e -> {
* button.setLoading(true);
* // Perform async operation
* CompletableFuture.runAsync(() -> {
* // Do work...
* Platform.runLater(() -> button.setLoading(false));
* });
* });
* </pre>
*
* @param loading true to show loading state, false to restore normal state
*/
public void setLoading(boolean loading) {
isLoading.set(loading);
}

/**
* Set the button as rounded
*/
public void setRounded(boolean rounded) {
if (rounded) {
getStyleClass().add("rounded");
} else {
getStyleClass().remove("rounded");
}
}

/**
* Force the button into a square shape.
*/
public void setSquare(boolean square) {
isSquare.set(square);
}

/**
* Set the button as outlined
*/
public void setOutlined(boolean outlined) {
isOutlined.set(outlined);
}

/**
* Set the button as flat
*/
public void setFlat(boolean flat) {
isFlat.set(flat);
}

/**
* Called when the button has started loading
*/
Expand Down Expand Up @@ -187,9 +331,41 @@ private void updateContent() {
} else {
setGraphic(icon);
}
} else {
setGraphic(null);
}
}

}
} else {
setGraphic(null);
}
}

private void updateStyle() {
ObservableList<String> styleClass = getStyleClass();

styleClass.removeAll("square", "outlined", "flat");
styleClass.removeAll("primary", "secondary", "ghost", "danger", "success", "warning");
styleClass.removeAll("small", "medium", "large");

if (isSquare.get())
styleClass.add("square");

if (isOutlined.get())
styleClass.add("outlined");

if (isFlat.get())
styleClass.add("flat");

switch (variant.get()) {
case PRIMARY -> styleClass.add("primary");
case SECONDARY -> styleClass.add("secondary");
case GHOST -> styleClass.add("ghost");
case DANGER -> styleClass.add("danger");
case SUCCESS -> styleClass.add("success");
case WARNING -> styleClass.add("warning");
}

switch (size.get()) {
case SMALL -> styleClass.add("small");
case MEDIUM -> styleClass.add("medium");
case LARGE -> styleClass.add("large");
}
}

}
Loading