/*
* The MIT License
*
* Copyright 2014 noko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package net.nokok.twitduke.core.view.javafx;
import com.google.common.io.Files;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Objects;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ToolBar;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javax.imageio.ImageIO;
import net.nokok.twitduke.core.event.Event;
import net.nokok.twitduke.core.type.Retrievable;
import net.nokok.twitduke.core.type.TweetLength;
import net.nokok.twitduke.resources.FXMLResources;
import net.nokok.twitduke.resources.ImageResources;
import net.nokok.twitduke.resources.draft.DraftIO;
import net.nokok.twitduke.resources.draft.DraftIOFactory;
public class TweetTextareaToolbarController implements ComponentAppendable<Node>, Event<TweetLength> {
@FXML
private Label tweetTextLengthLabel;
@FXML
private ToolBar tweetTextareaToolbar;
@FXML
private ImageView draftButtonIcon;
private Retrievable<String> textAreaStringReceiver;
private TweetTextareaController tweetTextareaController;
private final DraftIO draftIO = DraftIOFactory.newInstance();
@Override
public void addComponent(Node component) {
tweetTextareaToolbar.getItems().add(component);
}
@Override
public void onEvent(TweetLength t) {
tweetTextLengthLabel.setText(String.valueOf(140 - t.length()));
if ( t.isSendable() ) {
tweetTextLengthLabel.setStyle("-fx-text-fill: #ecf0f1;"); //default.css normal-text-color
} else {
tweetTextLengthLabel.setStyle("-fx-text-fill: #c0392b;"); //default.css error-text-color
}
}
@FXML
void takeScreenshot(ActionEvent event) throws IOException {
Stage stage = new Stage(StageStyle.TRANSPARENT);
FXMLLoader screenShotLoader = FXMLResources.TAKE_SCREENSHOT.loader();
BorderPane root = screenShotLoader.load();
ScreenShotAreaSelector controller = screenShotLoader.getController();
controller.areaSelected((start, end) -> {
stage.close();
BufferedImage image = takeScreenShot(start, end);
saveImage("tmp.png", image);
});
Dimension screenSize = getScreenSize();
Scene scene = new Scene(root, screenSize.width, screenSize.height);
scene.setFill(null);
stage.setScene(scene);
stage.show();
}
private BufferedImage takeScreenShot(Point start, Point end) {
int height = end.x - start.x;
int width = end.y - start.y;
if ( height < 0 ) {
int x = start.x;
start.x = end.x;
end.x = x;
}
if ( width < 0 ) {
int y = start.y;
start.y = end.y;
end.y = y;
}
try {
Robot robot = new Robot();
BufferedImage capturedImage = robot.createScreenCapture(new Rectangle(start.x, start.y, end.x - start.x, end.y - start.y));
return capturedImage;
} catch (AWTException ex) {
throw new RuntimeException(ex);
}
}
private void saveImage(String fileName, BufferedImage image) {
try {
ImageIO.write(image, "png", new File(fileName));
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
@FXML
void choosePicture(ActionEvent event) {
Stage stage = new Stage();
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("画像を選択してください");
File file = fileChooser.showOpenDialog(stage);
try {
Files.copy(file, new File("tmp.png"));
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
@FXML
void saveDraft(ActionEvent event) {
String text = textAreaStringReceiver.get();
draftIO.saveDraft(text);
if ( draftIO.draftList().isEmpty() ) {
draftButtonIcon.setImage(ImageResources.DRAFT_EMPTY);
} else {
draftButtonIcon.setImage(ImageResources.DRAFT_FULL);
}
}
public void setSaveDraftButtonListener(Retrievable<String> textAreaStringReceiver) {
this.textAreaStringReceiver = Objects.requireNonNull(textAreaStringReceiver);
}
private Dimension getScreenSize() {
return Toolkit.getDefaultToolkit().getScreenSize();
}
public void addTweetTextAreaController(TweetTextareaController controller) {
this.tweetTextareaController = Objects.requireNonNull(controller);
tweetTextareaController.onInput(this::onEvent);
}
}