Support saving any page snapshot to a file
This commit is contained in:
parent
bbec330216
commit
38ce8e9446
@ -40,7 +40,8 @@ public class Launcher extends Application {
|
|||||||
|
|
||||||
public static final List<KeyCodeCombination> SUPPORTED_HOTKEYS = List.of(
|
public static final List<KeyCodeCombination> SUPPORTED_HOTKEYS = List.of(
|
||||||
new KeyCodeCombination(KeyCode.SLASH),
|
new KeyCodeCombination(KeyCode.SLASH),
|
||||||
new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN)
|
new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN),
|
||||||
|
new KeyCodeCombination(KeyCode.W, KeyCombination.CONTROL_DOWN)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -6,20 +6,30 @@ import static atlantafx.sampler.event.PageEvent.Action;
|
|||||||
import static javafx.scene.layout.Priority.ALWAYS;
|
import static javafx.scene.layout.Priority.ALWAYS;
|
||||||
|
|
||||||
import atlantafx.sampler.event.DefaultEventBus;
|
import atlantafx.sampler.event.DefaultEventBus;
|
||||||
|
import atlantafx.sampler.event.HotkeyEvent;
|
||||||
import atlantafx.sampler.event.PageEvent;
|
import atlantafx.sampler.event.PageEvent;
|
||||||
import atlantafx.sampler.event.ThemeEvent;
|
import atlantafx.sampler.event.ThemeEvent;
|
||||||
import atlantafx.sampler.layout.MainModel.SubLayer;
|
import atlantafx.sampler.layout.MainModel.SubLayer;
|
||||||
import atlantafx.sampler.page.Page;
|
import atlantafx.sampler.page.Page;
|
||||||
import atlantafx.sampler.theme.ThemeManager;
|
import atlantafx.sampler.theme.ThemeManager;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javafx.animation.FadeTransition;
|
import javafx.animation.FadeTransition;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.embed.swing.SwingFXUtils;
|
||||||
|
import javafx.scene.SnapshotParameters;
|
||||||
|
import javafx.scene.image.WritableImage;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyCodeCombination;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
class MainLayer extends BorderPane {
|
class MainLayer extends BorderPane {
|
||||||
|
|
||||||
@ -42,6 +52,38 @@ class MainLayer extends BorderPane {
|
|||||||
|
|
||||||
// keyboard navigation won't work without focus
|
// keyboard navigation won't work without focus
|
||||||
Platform.runLater(sidebar::begForFocus);
|
Platform.runLater(sidebar::begForFocus);
|
||||||
|
|
||||||
|
var snapshotKeys = new KeyCodeCombination(KeyCode.W, KeyCombination.CONTROL_DOWN);
|
||||||
|
DefaultEventBus.getInstance().subscribe(HotkeyEvent.class, e -> {
|
||||||
|
if (Objects.equals(e.getKeys(), snapshotKeys)) {
|
||||||
|
final Page page = (Page) subLayerPane.getChildren().stream()
|
||||||
|
.filter(c -> c instanceof Page)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
if (page == null || page.getSnapshotTarget() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileChooser = new FileChooser();
|
||||||
|
fileChooser.setInitialDirectory(Paths.get(System.getProperty("user.home")).toFile());
|
||||||
|
fileChooser.setInitialFileName("snapshot.png");
|
||||||
|
fileChooser.getExtensionFilters().addAll(
|
||||||
|
new FileChooser.ExtensionFilter("Image Files", "*.png")
|
||||||
|
);
|
||||||
|
|
||||||
|
var file = fileChooser.showSaveDialog(getScene().getWindow());
|
||||||
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
WritableImage img = page.getSnapshotTarget().snapshot(new SnapshotParameters(), null);
|
||||||
|
ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", file);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createView() {
|
private void createView() {
|
||||||
|
@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public abstract class AbstractPage extends StackPane implements Page {
|
public abstract class AbstractPage extends StackPane implements Page {
|
||||||
|
|
||||||
protected final VBox userContent = new VBox();
|
protected final VBox userContent = new VBox();
|
||||||
|
protected final StackPane userContentArea = new StackPane(userContent);
|
||||||
protected Overlay overlay;
|
protected Overlay overlay;
|
||||||
protected boolean isRendered = false;
|
protected boolean isRendered = false;
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ public abstract class AbstractPage extends StackPane implements Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void createPageLayout() {
|
protected void createPageLayout() {
|
||||||
var userContentArea = new StackPane(userContent);
|
|
||||||
userContentArea.setAlignment(Pos.TOP_CENTER);
|
userContentArea.setAlignment(Pos.TOP_CENTER);
|
||||||
userContent.setMinWidth(Math.min(Page.MAX_WIDTH, 800));
|
userContent.setMinWidth(Math.min(Page.MAX_WIDTH, 800));
|
||||||
userContent.setMaxWidth(Math.min(Page.MAX_WIDTH, 800));
|
userContent.setMaxWidth(Math.min(Page.MAX_WIDTH, 800));
|
||||||
@ -65,6 +65,11 @@ public abstract class AbstractPage extends StackPane implements Page {
|
|||||||
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getSnapshotTarget() {
|
||||||
|
return userContentArea;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ public abstract class OutlinePage extends StackPane implements Page {
|
|||||||
|
|
||||||
protected final ScrollPane scrollPane = new ScrollPane();
|
protected final ScrollPane scrollPane = new ScrollPane();
|
||||||
protected final VBox userContent = new VBox();
|
protected final VBox userContent = new VBox();
|
||||||
|
protected final StackPane userContentArea = new StackPane(userContent);
|
||||||
protected final Outline outline = new Outline(createOutlineHandler());
|
protected final Outline outline = new Outline(createOutlineHandler());
|
||||||
|
|
||||||
protected Overlay overlay;
|
protected Overlay overlay;
|
||||||
@ -52,7 +53,6 @@ public abstract class OutlinePage extends StackPane implements Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void createPageLayout() {
|
protected void createPageLayout() {
|
||||||
var userContentArea = new StackPane(userContent);
|
|
||||||
StackPane.setMargin(userContent, new Insets(0, OUTLINE_WIDTH, 0, 0));
|
StackPane.setMargin(userContent, new Insets(0, OUTLINE_WIDTH, 0, 0));
|
||||||
userContent.setMinWidth(Page.MAX_WIDTH - OUTLINE_WIDTH - 100);
|
userContent.setMinWidth(Page.MAX_WIDTH - OUTLINE_WIDTH - 100);
|
||||||
userContent.setMaxWidth(Page.MAX_WIDTH - OUTLINE_WIDTH - 100);
|
userContent.setMaxWidth(Page.MAX_WIDTH - OUTLINE_WIDTH - 100);
|
||||||
@ -177,6 +177,11 @@ public abstract class OutlinePage extends StackPane implements Page {
|
|||||||
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getSnapshotTarget() {
|
||||||
|
return userContentArea;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import javafx.scene.control.MenuItem;
|
|||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.KeyCodeCombination;
|
import javafx.scene.input.KeyCodeCombination;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
import net.datafaker.Faker;
|
import net.datafaker.Faker;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.kordamp.ikonli.feather.Feather;
|
import org.kordamp.ikonli.feather.Feather;
|
||||||
@ -58,6 +59,8 @@ public interface Page {
|
|||||||
|
|
||||||
@Nullable URI getJavadocUri();
|
@Nullable URI getJavadocUri();
|
||||||
|
|
||||||
|
@Nullable Node getSnapshotTarget();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
default <T> List<T> generate(Supplier<T> supplier, int count) {
|
default <T> List<T> generate(Supplier<T> supplier, int count) {
|
||||||
|
@ -11,6 +11,7 @@ import java.io.IOException;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
@ -21,6 +22,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public final class OverviewPage extends ScrollPane implements Page {
|
public final class OverviewPage extends ScrollPane implements Page {
|
||||||
|
|
||||||
public static final String NAME = "Overview";
|
public static final String NAME = "Overview";
|
||||||
|
private VBox wrapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@ -31,7 +33,7 @@ public final class OverviewPage extends ScrollPane implements Page {
|
|||||||
super();
|
super();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var wrapper = new VBox();
|
wrapper = new VBox();
|
||||||
wrapper.setAlignment(Pos.TOP_CENTER);
|
wrapper.setAlignment(Pos.TOP_CENTER);
|
||||||
|
|
||||||
var loader = new FXMLLoader(
|
var loader = new FXMLLoader(
|
||||||
@ -72,6 +74,11 @@ public final class OverviewPage extends ScrollPane implements Page {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getSnapshotTarget() {
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,11 @@ public abstract class ShowcasePage extends StackPane implements Page {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getSnapshotTarget() {
|
||||||
|
return showCaseContent;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user