Skip to content

Commit

Permalink
Add Take SVG screenshot menu item.
Browse files Browse the repository at this point in the history
  • Loading branch information
heuermh committed Oct 9, 2019
1 parent 1ba4b04 commit 07394b2
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 8 deletions.
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -114,4 +119,4 @@
<type>maven-plugin</type>
</dependency>
</dependencies>
</project>
</project>
50 changes: 47 additions & 3 deletions src/main/java/amidst/gui/main/Actions.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,13 @@ public void copySeedToClipboard() {
}

@CalledOnlyBy(AmidstThread.EDT)
public void takeScreenshot() {
public void takePngScreenshot() {
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
if (viewerFacade != null) {
BufferedImage image = viewerFacade.createScreenshot();
String suggestedFilename = "screenshot_" + viewerFacade.getWorldType().getFilenameText() + "_"
+ viewerFacade.getWorldSeed().getLong() + ".png";
File file = dialogs.askForScreenshotSaveFile(suggestedFilename);
File file = dialogs.askForSvgScreenshotSaveFile(suggestedFilename);
if (file != null) {
file = appendPNGFileExtensionIfNecessary(file);
if (file.exists() && !file.isFile()) {
Expand All @@ -241,7 +241,51 @@ public void takeScreenshot() {
}
}

@CalledOnlyBy(AmidstThread.EDT)
@CalledOnlyBy(AmidstThread.EDT)
public void takeSvgScreenshot() {
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
if (viewerFacade != null) {
String suggestedFilename = "screenshot_" + viewerFacade.getWorldType().getFilenameText() + "_"
+ viewerFacade.getWorldSeed().getLong() + ".svg";
File file = dialogs.askForScreenshotSaveFile(suggestedFilename);
if (file != null) {
file = appendSvgFileExtensionIfNecessary(file);
if (file.exists() && !file.isFile()) {
String message = "Unable to write screenshot, because the target exists but is not a file: "
+ file.getAbsolutePath();
AmidstLogger.warn(message);
dialogs.displayError(message);
} else if (!canWriteToFile(file)) {
String message = "Unable to write screenshot, because you have no writing permissions: "
+ file.getAbsolutePath();
AmidstLogger.warn(message);
dialogs.displayError(message);
} else if (!file.exists() || dialogs.askToConfirmYesNo(
"Replace file?",
"File already exists. Do you want to replace it?\n" + file.getAbsolutePath() + "")) {

try {
viewerFacade.writeSvgScreenshot(file);
}
catch (IOException e) {
AmidstLogger.warn(e);
dialogs.displayError(e);
}
}
}
}
}

@CalledOnlyBy(AmidstThread.EDT)
private File appendSvgFileExtensionIfNecessary(File file) {
String filename = file.getAbsolutePath();
if (!FileExtensionChecker.hasFileExtension(filename, "svg")) {
filename += ".svg";
}
return new File(filename);
}

@CalledOnlyBy(AmidstThread.EDT)
public void selectBiomeProfile(BiomeProfile profile) {
biomeProfileSelection.set(profile);
ViewerFacade viewerFacade = viewerFacadeSupplier.get();
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/amidst/gui/main/MainWindowDialogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public File askForScreenshotSaveFile(String suggestedFilename) {
return showSaveDialogAndGetSelectedFileOrNull(createScreenshotSaveFileChooser(suggestedFilename));
}

@CalledOnlyBy(AmidstThread.EDT)
public File askForSvgScreenshotSaveFile(String suggestedFilename) {
return showSaveDialogAndGetSelectedFileOrNull(createSvgScreenshotSaveFileChooser(suggestedFilename));
}

@CalledOnlyBy(AmidstThread.EDT)
private JFileChooser createScreenshotSaveFileChooser(String suggestedFilename) {
JFileChooser result = new JFileChooser();
Expand All @@ -83,6 +88,15 @@ private JFileChooser createScreenshotSaveFileChooser(String suggestedFilename) {
return result;
}

@CalledOnlyBy(AmidstThread.EDT)
private JFileChooser createSvgScreenshotSaveFileChooser(String suggestedFilename) {
JFileChooser result = new JFileChooser();
result.setFileFilter(new SVGFileFilter());
result.setAcceptAllFileFilterUsed(false);
result.setSelectedFile(new File(suggestedFilename));
return result;
}

@CalledOnlyBy(AmidstThread.EDT)
private File showSaveDialogAndGetSelectedFileOrNull(JFileChooser fileChooser) {
if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/amidst/gui/main/SVGFileFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package amidst.gui.main;

import java.io.File;

import javax.swing.filechooser.FileFilter;

import amidst.documentation.NotThreadSafe;
import amidst.util.FileExtensionChecker;

@NotThreadSafe
public class SVGFileFilter extends FileFilter {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
return true;
} else {
return FileExtensionChecker.hasFileExtension(file.getName(), "svg");
}
}

@Override
public String getDescription() {
return "Scalable Vector Graphics (*.SVG)";
}
}
3 changes: 2 additions & 1 deletion src/main/java/amidst/gui/main/menu/AmidstMenuBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ private JMenu create_World() {
Menus.item(result, actions::howCanIMoveAPlayer, "How can I move a player?", KeyEvent.VK_M);
result.addSeparator();
Menus.item(result, actions::copySeedToClipboard, "Copy Seed to Clipboard", KeyEvent.VK_B, MenuShortcuts.COPY_SEED_TO_CLIPBOARD);
Menus.item(result, actions::takeScreenshot, "Take Screenshot ...", KeyEvent.VK_T, MenuShortcuts.TAKE_SCREENSHOT);
Menus.item(result, actions::takePngScreenshot, "Take PNG Screenshot ...", KeyEvent.VK_T, MenuShortcuts.TAKE_PNG_SCREENSHOT);
Menus.item(result, actions::takeSvgScreenshot, "Take SVG Screenshot ...", KeyEvent.VK_Y, MenuShortcuts.TAKE_SVG_SCREENSHOT);
// @formatter:on
return result;
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/amidst/gui/main/menu/MenuShortcuts.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public enum MenuShortcuts implements MenuShortcut {
SAVE_PLAYER_LOCATIONS("menu S"),
RELOAD_PLAYER_LOCATIONS("F5"),
COPY_SEED_TO_CLIPBOARD("menu C"),
TAKE_SCREENSHOT("menu T"),
TAKE_PNG_SCREENSHOT("menu T"),
TAKE_SVG_SCREENSHOT("menu Y"),

DISPLAY_DIMENSION_OVERWORLD("menu shift 1"),
DISPLAY_DIMENSION_END("menu shift 2"),
Expand Down
31 changes: 30 additions & 1 deletion src/main/java/amidst/gui/main/viewer/Viewer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@
import java.awt.Point;
import java.awt.image.BufferedImage;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JComponent;

import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.main.viewer.widget.Widget;

import org.apache.batik.dom.GenericDOMImplementation;

import org.apache.batik.svggen.SVGGraphics2D;

import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;

@NotThreadSafe
public class Viewer {
@SuppressWarnings("serial")
Expand Down Expand Up @@ -45,7 +56,20 @@ public BufferedImage createScreenshot() {
return result;
}

/**
public void writeSvgScreenshot(final File file) throws IOException {
int width = getWidth();
int height = getHeight();
Point mousePosition = getMousePositionOrNull();
try (FileWriter writer = new FileWriter(file)) {
DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
Document document = domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
drawer.drawScreenshot(svgGenerator, width, height, mousePosition, widgetFontMetrics);
svgGenerator.stream(writer, true);
}
}

/**
* The method getMousePosition() might throw a null pointer exception in
* a multi-monitor setup, as soon as the window is dragged to the other
* monitor.
Expand Down Expand Up @@ -83,6 +107,11 @@ public BufferedImage createScreenshot() {
return component.createScreenshot();
}

@CalledOnlyBy(AmidstThread.EDT)
public void writeSvgScreenshot(final File file) throws IOException {
component.writeSvgScreenshot(file);
}

@CalledOnlyBy(AmidstThread.EDT)
public Point getMousePositionOrCenter() {
Point result = component.getMousePositionOrNull();
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/amidst/gui/main/viewer/ViewerFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import java.awt.Component;
import java.awt.Point;
import java.awt.image.BufferedImage;

import java.io.File;
import java.io.IOException;

import java.util.List;

import amidst.dependency.injection.Factory1;
Expand Down Expand Up @@ -127,7 +131,12 @@ public BufferedImage createScreenshot() {
return viewer.createScreenshot();
}

@CalledOnlyBy(AmidstThread.EDT)
@CalledOnlyBy(AmidstThread.EDT)
public void writeSvgScreenshot(final File file) throws IOException {
viewer.writeSvgScreenshot(file);
}

@CalledOnlyBy(AmidstThread.EDT)
public void adjustZoom(int notches) {
zoom.adjustZoom(viewer.getMousePositionOrCenter(), notches);
}
Expand Down

0 comments on commit 07394b2

Please sign in to comment.