package AndroidDevToolbox;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.apache.commons.io.FilenameUtils;
import org.imgscalr.Scalr;
import org.imgscalr.Scalr.Method;
import utils.AppConfig;
import utils.FileHelper;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
/**
* Created by AtomInvention on 14/12/13.
*/
public class StatefulButtonController extends BaseController implements Initializable {
private static final String XML_TEMPLATE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
"\t<item android:state_focused=\"true\" android:drawable=\"@drawable/$focused$\"/>\n" +
"\t<item android:state_pressed=\"true\" android:drawable=\"@drawable/$pressed$\" />\n" +
"\t<item android:state_enabled=\"false\" android:drawable=\"@drawable/$disabled$\" />\n" +
"\t<item android:drawable=\"@drawable/$normal$\"/>\n" +
"</selector>";
public interface OnStyleSetListener {
public void onSet(int brightness, int transparency, State state);
}
private static final String XML_PRESSED_HOLDER = "$pressed$";
private static final String XML_FOCUSED_HOLDER = "$focused$";
private static final String XML_DISABLED_HOLDER = "$disabled$";
private static final String XML_NORMAL_HOLDER = "$normal$";
private ResourceBundle resourceBundle;
private OnStyleSetListener onStyleSetListener;
private GenerateStatefulFilesService generateStatefulFilesService;
public TextField inputImageTextField;
public Button inputSelectBrowseBtn;
public TextField normalFilenameTextField;
public TextField pressedFilenameTextField;
public TextField focusedFilenameTextField;
public TextField disabledFilenameTextField;
public CheckBox pressedCheckBox;
public CheckBox focusedCheckBox;
public CheckBox disabledCheckBox;
public Button pressedStyleBtn;
public Button focusedStyleBtn;
public Button disabledStyleBtn;
public ImageView normalPreviewImageView;
public ImageView pressedPreviewImageView;
public ImageView focusedPreviewImageView;
public ImageView disabledPreviewImageView;
public TextField outputFolderTextField;
public Button outputSelectBrowseBtn;
public Button generateFilesbtn;
public Label normalFilenameLabel;
public Label pressedFilenameLabel;
public Label focusedFilenameLabel;
public Label disabledFilenameLabel;
public Label normalExtLabel;
public Label pressedExtLabel;
public Label focusedExtLabel;
public Label disabledExtLabel;
public HBox normalHbox;
public HBox pressedHbox;
public HBox focusedHbox;
public HBox disabledHbox;
public enum State {
NORMAL,
PRESSED,
FOCUSED,
DISABLED
}
private interface DefaultStateFileName {
String NORMAL = "normal";
String PRESSED = "pressed";
String FOCUSED = "focused";
String DISABLED = "disabled";
}
private interface PressedDefaultImgValue {
float BRIGHTNESS = -30.0f;
float TRANSPARENCY = 0.0f;
}
private interface FocusedDefaultImgValue {
float BRIGHTNESS = -15.0f;
float TRANSPARENCY = 0.0f;
}
private interface DisabledDefaultImgValue {
float BRIGHTNESS = 25.0f;
float TRANSPARENCY = 5.0f;
}
private String imageFilePath;
private String outputFolderPath;
private Label[] fileNameLabels;
private Label[] fileExtLabels;
private String[] defaultStateFileNames;
private TextField[] fileNameTextFields;
private ImageStyle pressedImgStyle;
private ImageStyle focusedImgStyle;
private ImageStyle disabledImgStyle;
private boolean imageFileSelected;
private boolean outputFolderSelected;
private boolean pressedStateEnabled;
private boolean focusedStateEnabled;
private boolean disabledStateEnabled;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
fileNameLabels = new Label[4];
fileNameLabels[0] = normalFilenameLabel;
fileNameLabels[1] = pressedFilenameLabel;
fileNameLabels[2] = focusedFilenameLabel;
fileNameLabels[3] = disabledFilenameLabel;
fileExtLabels = new Label[4];
fileExtLabels[0] = normalExtLabel;
fileExtLabels[1] = pressedExtLabel;
fileExtLabels[2] = focusedExtLabel;
fileExtLabels[3] = disabledExtLabel;
defaultStateFileNames = new String[4];
defaultStateFileNames[0] = DefaultStateFileName.NORMAL;
defaultStateFileNames[1] = DefaultStateFileName.PRESSED;
defaultStateFileNames[2] = DefaultStateFileName.FOCUSED;
defaultStateFileNames[3] = DefaultStateFileName.DISABLED;
fileNameTextFields = new TextField[4];
fileNameTextFields[0] = normalFilenameTextField;
fileNameTextFields[1] = pressedFilenameTextField;
fileNameTextFields[2] = focusedFilenameTextField;
fileNameTextFields[3] = disabledFilenameTextField;
pressedImgStyle = new ImageStyle(PressedDefaultImgValue.BRIGHTNESS
, PressedDefaultImgValue.TRANSPARENCY);
focusedImgStyle = new ImageStyle(FocusedDefaultImgValue.BRIGHTNESS
, FocusedDefaultImgValue.TRANSPARENCY);
disabledImgStyle = new ImageStyle(DisabledDefaultImgValue.BRIGHTNESS
, DisabledDefaultImgValue.TRANSPARENCY);
onStyleSetListener = new OnStyleSetListener() {
@Override
public void onSet(int brightness, int transparency, State state) {
System.out.println("onSet brightness: " + brightness
+ " transparency: " + transparency + " state: " + state);
switch (state) {
case PRESSED:
pressedImgStyle.setBrightness(brightness);
pressedImgStyle.setTransparency(transparency);
break;
case DISABLED:
disabledImgStyle.setBrightness(brightness);
disabledImgStyle.setTransparency(transparency);
break;
case FOCUSED:
focusedImgStyle.setBrightness(brightness);
focusedImgStyle.setTransparency(transparency);
break;
}
updatePreviewImage(state);
}
};
generateStatefulFilesService = new GenerateStatefulFilesService();
}
private void updatePreviewImage(State state) {
switch (state) {
case PRESSED:
if (pressedStateEnabled) {
setImageAndStyle(pressedImgStyle.getBrightness()
, pressedImgStyle.getTransparency(), pressedPreviewImageView);
} else {
pressedPreviewImageView.setImage(null);
}
break;
case DISABLED:
if (disabledStateEnabled) {
setImageAndStyle(disabledImgStyle.getBrightness()
, disabledImgStyle.getTransparency(), disabledPreviewImageView);
} else {
disabledPreviewImageView.setImage(null);
}
break;
case FOCUSED:
if (focusedStateEnabled) {
setImageAndStyle(focusedImgStyle.getBrightness()
, focusedImgStyle.getTransparency(), focusedPreviewImageView);
} else {
focusedPreviewImageView.setImage(null);
}
break;
}
}
private void setImageAndStyle(float brightness, float transparency, ImageView imageView) {
imageView.setImage(SwingFXUtils.toFXImage(getStyledImage(brightness, transparency, 200), null));
}
private BufferedImage getStyledImage(float brightness, float transparency, int size) {
BufferedImage outputImage = null;
try {
BufferedImage readBufferedImage = ImageIO.read(new File(imageFilePath));
BufferedImage inputBufferedImage = convertToArgb(readBufferedImage);
outputImage = inputBufferedImage;
if (size > 0) {
outputImage = Scalr.resize(inputBufferedImage
, Method.BALANCED
, size
, size);
}
float brightnessFactor = 1.0f + brightness/100.0f;
float transparencyFactor = Math.abs(transparency/100.0f - 1.0f);
RescaleOp rescale = new RescaleOp(
new float[]{brightnessFactor, brightnessFactor, brightnessFactor, transparencyFactor},
new float[]{0f, 0f, 0f, 0f}, null);
rescale.filter(outputImage, outputImage);
} catch (Exception e) {
e.printStackTrace();
}
return outputImage;
}
public void browseForImageFile() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("ResizeSelectImageFile"));
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("All Images", "*.*"),
new FileChooser.ExtensionFilter("JPG", "*.jpg"),
new FileChooser.ExtensionFilter("PNG", "*.png")
);
// open file dialog
File file = fileChooser.showOpenDialog(inputSelectBrowseBtn.getScene().getWindow());
if (file != null) {
inputImageTextField.setText(file.getPath());
imageFilePath = file.getPath();
imageFileSelected = true;
updateStartBtnState();
updateStateSettingsBox();
updateNormalImageView(new File(imageFilePath));
updatePreviewImage(State.PRESSED);
updatePreviewImage(State.FOCUSED);
updatePreviewImage(State.DISABLED);
}
}
public void browseForOutputFolder() {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(resourceBundle.getString("ResizeSelectOutputFolder"));
File outputFolder = directoryChooser.showDialog(outputSelectBrowseBtn.getScene().getWindow());
if (outputFolder != null) {
outputFolderTextField.setText(outputFolder.getPath());
outputFolderSelected = true;
outputFolderPath = outputFolder.getPath();
updateStartBtnState();
}
}
public void updateNormalImageView(File file) {
Image image = new Image("file:" + file.getPath());
normalPreviewImageView.setImage(image);
}
public void updateStateSettingsBox() {
normalHbox.setVisible(true);
pressedHbox.setVisible(true);
focusedHbox.setVisible(true);
disabledHbox.setVisible(true);
normalHbox.setDisable(false);
pressedCheckBox.setDisable(false);
focusedCheckBox.setDisable(false);
disabledCheckBox.setDisable(false);
String fileName = new File(imageFilePath).getName();
// force png output
String fileExt = "png";
String originalExt = FilenameUtils.getExtension(fileName);
fileName = fileName.replace("."+originalExt, "").replace(" ", "_").toLowerCase();
for (int i=0; i<fileNameLabels.length; i++) {
fileNameLabels[i].setText(fileName + "_");
fileExtLabels[i].setText("." + fileExt);
fileNameTextFields[i].setText(defaultStateFileNames[i]);
}
}
public void onPressedStateChecked() {
pressedStateEnabled = !pressedStateEnabled;
pressedStyleBtn.setDisable(!pressedStateEnabled);
pressedHbox.setDisable(!pressedStateEnabled);
updatePreviewImage(State.PRESSED);
updateStartBtnState();
}
public void onFocusedStateChecked() {
focusedStateEnabled = !focusedStateEnabled;
focusedStyleBtn.setDisable(!focusedStateEnabled);
focusedHbox.setDisable(!focusedStateEnabled);
updatePreviewImage(State.FOCUSED);
updateStartBtnState();
}
public void onDisabledStateChecked() {
disabledStateEnabled = !disabledStateEnabled;
disabledStyleBtn.setDisable(!disabledStateEnabled);
disabledHbox.setDisable(!disabledStateEnabled);
updatePreviewImage(State.DISABLED);
updateStartBtnState();
}
public void setStyle(MouseEvent event) {
float defaultBrightness = 0.0f;
float defaultTransparency = 0.0f;
float currentBrightness = 0.0f;
float currentTransparency = 0.0f;
State state = State.PRESSED;
Button button = (Button) event.getSource();
if (button == pressedStyleBtn) {
defaultBrightness = PressedDefaultImgValue.BRIGHTNESS;
defaultTransparency = PressedDefaultImgValue.TRANSPARENCY;
currentBrightness = pressedImgStyle.getBrightness();
currentTransparency = pressedImgStyle.getTransparency();
state = State.PRESSED;
} else if (button == focusedStyleBtn) {
defaultBrightness = FocusedDefaultImgValue.BRIGHTNESS;
defaultTransparency = FocusedDefaultImgValue.TRANSPARENCY;
currentBrightness = focusedImgStyle.getBrightness();
currentTransparency = focusedImgStyle.getTransparency();
state = State.FOCUSED;
} else if (button == disabledStyleBtn) {
defaultBrightness = DisabledDefaultImgValue.BRIGHTNESS;
defaultTransparency = DisabledDefaultImgValue.TRANSPARENCY;
currentBrightness = disabledImgStyle.getBrightness();
currentTransparency = disabledImgStyle.getTransparency();
state = State.DISABLED;
}
try {
FXMLLoader fxmlLoader = new FXMLLoader(FileHelper.getFxmlUrl(
getClass(), "EditStyleDialog.fxml"), resourceBundle);
Parent root = (Parent) fxmlLoader.load();
Stage dialogStage = new Stage();
dialogStage.initModality(Modality.APPLICATION_MODAL);
Scene scene = new Scene(root);
String cssURL = getClass().getClassLoader().getResource(AppConfig.APP_CSS_PATH).toExternalForm();
scene.getStylesheets().add(cssURL);
dialogStage.setScene(scene);
EditStyleDialogController controller = fxmlLoader.getController();
BufferedImage readBufferedImage = ImageIO.read(new File(imageFilePath));
BufferedImage inputBufferedImage = convertToArgb(readBufferedImage);
BufferedImage resizedImage = Scalr.resize(inputBufferedImage
, Method.BALANCED
, 200
, 200);
controller.initImage(state, resizedImage, defaultBrightness, defaultTransparency
, currentBrightness, currentTransparency);
controller.setOnStyleSetListener(onStyleSetListener);
dialogStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateStartBtnState() {
boolean anyExtraStateSelected = pressedStateEnabled || focusedStateEnabled
|| disabledStateEnabled;
if (imageFileSelected && outputFolderSelected && anyExtraStateSelected) {
generateFilesbtn.setDisable(false);
} else {
if (generateFilesbtn != null) {
generateFilesbtn.setDisable(true);
}
}
}
public static class ImageStyle {
private float brightness;
private float transparency;
public ImageStyle(float brightness, float transparency) {
this.brightness = brightness;
this.transparency = transparency;
}
public float getBrightness() {
return brightness;
}
public void setBrightness(float brightness) {
this.brightness = brightness;
}
public float getTransparency() {
return transparency;
}
public void setTransparency(float transparency) {
this.transparency = transparency;
}
}
public void startGenerateFiles() {
generateStatefulFilesService.restart();
}
private BufferedImage convertToArgb(java.awt.Image image) {
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null)
, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()
, new Color(0, 0, 0, 0), null);
return bufferedImage;
}
private class GenerateStatefulFilesService extends Service<Void> {
@Override
protected Task<Void> createTask() {
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
updateMessage(resourceBundle.getString("StateGenerationStarted"));
// create folder
String rootFolder = outputFolderPath + File.separator +
AppConfig.FOLDER_STATEFUL_PREFIX + "_" + System.currentTimeMillis();
FileHelper.makeFolder(rootFolder);
String fileName = new File(imageFilePath).getName().replace(" ", "_").toLowerCase();
// force png output
String fileExt = "png";
String originalExt = FilenameUtils.getExtension(fileName);
String dotFileExt = "." + fileExt;
String fileNameNoExt = fileName.replace("."+originalExt, "");
String normalFileName = fileNameNoExt
+ "_" + normalFilenameTextField.getText() + dotFileExt;
String pressedFileName = fileNameNoExt
+ "_" + pressedFilenameTextField.getText() + dotFileExt;
String focusedFileName = fileNameNoExt
+ "_" + focusedFilenameTextField.getText() + dotFileExt;
String disabledFileName = fileNameNoExt
+ "_" + disabledFilenameTextField.getText() + dotFileExt;
String normalFilePath = rootFolder + File.separator + normalFileName;
String pressedFilePath = rootFolder + File.separator + pressedFileName;
String focusedFilePath = rootFolder + File.separator + focusedFileName;
String disabledFilePath = rootFolder + File.separator + disabledFileName;
// copy original(normal) file first
FileHelper.copyFile(imageFilePath, normalFilePath);
// output images of other states
BufferedImage outputBufferedImage = null;
if (pressedStateEnabled) {
outputBufferedImage = getStyledImage(
pressedImgStyle.getBrightness(), pressedImgStyle.getTransparency(), 0);
ImageIO.write(outputBufferedImage, fileExt, new File(pressedFilePath));
}
if (focusedStateEnabled) {
outputBufferedImage = getStyledImage(
focusedImgStyle.getBrightness(), focusedImgStyle.getTransparency(), 0);
ImageIO.write(outputBufferedImage, fileExt, new File(focusedFilePath));
}
if (disabledStateEnabled) {
outputBufferedImage = getStyledImage(
disabledImgStyle.getBrightness(), disabledImgStyle.getTransparency(), 0);
ImageIO.write(outputBufferedImage, fileExt, new File(disabledFilePath));
}
// output xml
String fileContent = XML_TEMPLATE;
normalFileName = normalFileName.replace("."+fileExt, "");
pressedFileName = pressedFileName.replace("."+fileExt, "");
focusedFileName = focusedFileName.replace("."+fileExt, "");
disabledFileName = disabledFileName.replace("."+fileExt, "");
fileContent = fileContent
.replace(XML_PRESSED_HOLDER
, pressedStateEnabled?pressedFileName:normalFileName)
.replace(XML_FOCUSED_HOLDER
, focusedStateEnabled?focusedFileName:normalFileName)
.replace(XML_DISABLED_HOLDER
, disabledStateEnabled?disabledFileName:normalFileName)
.replace(XML_NORMAL_HOLDER, normalFileName);
FileHelper.saveToFile(fileContent
, rootFolder + File.separator + fileNameNoExt + ".xml");
updateMessage(resourceBundle.getString("StateGenerationCompleted"));
return null;
}
};
getStatusBarLabel().textProperty().bind(task.messageProperty());
return task;
}
@Override
protected void running() {
super.running();
if (getBackgroundTaskExecutionListener() != null) {
getBackgroundTaskExecutionListener().taskStart();
}
inputSelectBrowseBtn.setDisable(true);
normalFilenameTextField.setDisable(true);
pressedFilenameTextField.setDisable(true);
focusedFilenameTextField.setDisable(true);
disabledFilenameTextField.setDisable(true);
pressedCheckBox.setDisable(true);
focusedCheckBox.setDisable(true);
disabledCheckBox.setDisable(true);
pressedStyleBtn.setDisable(true);
focusedStyleBtn.setDisable(true);
disabledStyleBtn.setDisable(true);
outputSelectBrowseBtn.setDisable(true);
generateFilesbtn.setDisable(true);
}
@Override
protected void succeeded() {
super.succeeded();
getStatusBarLabel().textProperty().unbind();
if (getBackgroundTaskExecutionListener() != null) {
getBackgroundTaskExecutionListener().taskComplete();
}
inputSelectBrowseBtn.setDisable(false);
normalFilenameTextField.setDisable(false);
pressedFilenameTextField.setDisable(false);
focusedFilenameTextField.setDisable(false);
disabledFilenameTextField.setDisable(false);
pressedCheckBox.setDisable(false);
focusedCheckBox.setDisable(false);
disabledCheckBox.setDisable(false);
pressedStyleBtn.setDisable(false);
focusedStyleBtn.setDisable(false);
disabledStyleBtn.setDisable(false);
outputSelectBrowseBtn.setDisable(false);
generateFilesbtn.setDisable(false);
}
}
}