2021년 11월 21일 일요일

Java FX Comics Viewer

1. Java FX Comics Viewer

package com.home.app;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;

import com.home.fx.FX;
import com.home.fx.FxImageView;
import com.home.fx.FxRunnable;
import com.home.java.UnZipApi;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;

import javax.imageio.ImageIO;

public class FxComicsViewer extends Application {

	final String title = "ComicsViewer";
	int fontSize = 12;
	FxImageView imageView;
	UnZipApi images;
	Stage primaryStage;
	ComboBox<String> pages;
	Label status;
	int imagesIndex;
	boolean ctrl_pressed = false;

	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage stage) throws IOException {
		primaryStage = stage;
		BorderPane pane = new BorderPane();
		Scene scene = new Scene(pane, 480, 320);
		stage.setTitle("Comics Viewer");
		setIcon(stage, "res/application.png");

		images = new UnZipApi();
		imagesIndex = 0;
		pages = FX.getComboBox( this::gotoPage, null);
		imageView = new FxImageView(fontSize, keyHandle); //FxApi.getImageView();
		status = new Label("Ready");

		HBox hbox = FX.getHBox();
		FX.addHbox(hbox, FX.getButton("|<", (e) -> firstPage() ), false);
		FX.addHbox(hbox, FX.getButton("<", (e) -> prevPage() ), false);
		FX.addHbox(hbox, FX.getButton(">", (e) -> nextPage() ), false);
		FX.addHbox(hbox, FX.getButton(">|", (e) -> lastPage() ), false);
		FX.addHbox(hbox, FX.getButton("W", (e) -> fitWidth() ), false);
		FX.addHbox(hbox, FX.getButton("H", (e) -> fitHeight() ), false);
		FX.addHbox(hbox, FX.getButton("N", (e) -> fitNone() ), false);
		FX.addHbox(hbox, FX.getButton("+", (e) -> zoomIn() ), false);
		FX.addHbox(hbox, FX.getButton("-", (e) -> zoomOut() ), false);
		FX.addHbox(hbox, pages, false);
		VBox vbox = FX.getVBox();
		FX.addVbox(vbox, getMenuBar(), true);
		FX.addVbox(vbox, hbox, false);

		FX.setDropHandler(imageView.getLayout(), dropHandle);
		pane.setPadding(new Insets(0, 0, 0, 0));
		pane.setBottom(status);
		pane.setTop(vbox);
		pane.setCenter(imageView.getLayout());


		scene.setOnKeyPressed(ke -> {
			if( ke.getCode() == KeyCode.CONTROL ) { ctrl_pressed = true; }
			if( ke.getCode() == KeyCode.MINUS && ctrl_pressed ) { zoomOut(); }
			if( ke.getCode() == KeyCode.EQUALS && ctrl_pressed ) { zoomIn(); }
		});
		scene.setOnKeyReleased(ke -> {
			if( ke.getCode() == KeyCode.CONTROL ) { ctrl_pressed = false; }
		});
		scene.setOnScroll((ScrollEvent event) -> {
			double deltaY = event.getDeltaY();
			if( ctrl_pressed ) {
				if( deltaY > 0 ) { zoomIn(); }
				else { zoomOut(); }
			}
		});

		stage.setOnCloseRequest( (e) -> System.exit(0) ); //Platform->exit()
		stage.setScene(scene);
		stage.show();
	}

	void setIcon(Stage stage, String image) throws IOException {
		ClassLoader cl = getClass().getClassLoader();
		InputStream is = cl.getResourceAsStream(image);
		if( is != null ) {
			stage.getIcons().add(SwingFXUtils.toFXImage(ImageIO.read(is), null));
		}
	}

	Runnable runnableExit = new Runnable() {
		@Override public void run() {
			boolean result = yesnoDialog("Exit", "Do you want exit progrma ?");
			if( result ) { System.exit(0); }
		}
	};

	FxRunnable keyHandle = new FxRunnable() {
		@Override public void run(Object... object) {
			if( images != null ) {
				KeyCode e = (KeyCode)object[0];		

		        if ( e.equals(KeyCode.UP) ) {
		            System.out.println("Up Pressed");
		        }
		        if ( e.equals(KeyCode.DOWN) ) {
		            System.out.println("Down Pressed");
		        }
		        if ( e.equals(KeyCode.RIGHT) ) {
		            System.out.println("Right Pressed");
		            nextPage();
		        }
		        if ( e.equals(KeyCode.LEFT) ) {
		            System.out.println("Left Pressed");
		            prevPage();
		        }
		        if ( e.equals(KeyCode.PAGE_UP) ) {
		            System.out.println("PageUp Pressed");
		        }
		        if ( e.equals(KeyCode.PAGE_DOWN) ) {
		            System.out.println("PageDown Pressed");
		        }
		        if ( e.equals(KeyCode.HOME) ) {
		            System.out.println("Home Pressed");
		        }
		        if ( e.equals(KeyCode.END) ) {
		            System.out.println("End Pressed");
		        }
		        if ( e.equals(KeyCode.ENTER) ) {
		            System.out.println("Enter Pressed");
		        }

			}
		}
	};
	
	FxRunnable dropHandle = new FxRunnable() {
		@SuppressWarnings("unchecked")
		@Override public void run(Object... object) {
			if( object[0] instanceof List<?> ) {
				List<File> f = (List<File>)object[0];
				try {
					loadComicsFile(f.get(0).getAbsolutePath());
				} catch (Exception e) {
				}
			}
		}
	};

    public void loadComicsFile(String filePath) {
		if( new File(filePath).isFile() ) {
			try {
				images.load(filePath, "EUC_KR");
				pages.getItems().clear();
				for( int i = 0; i < images.size(); i++ ) {
					System.out.println( "- " + images.getName(i));
					pages.getItems().add(images.getName(i));
				}
				firstPage();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }

    public void setImage(int index) {
		try {
			imageView.setImage(images.unzipEntry(index));
			status.setText(" [ " + (index+1) + " / " + images.size() + " ] ");
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
    
	public void firstPage() {
		imagesIndex = 0;
		pages.getSelectionModel().selectFirst();
	}
	
	public void lastPage() {
		imagesIndex = images.size() - 1;
		pages.getSelectionModel().selectLast();
	}
		
	public void nextPage() {
		if( imagesIndex < (images.size()-1) ) {
			imagesIndex++;
			pages.getSelectionModel().select(imagesIndex);
		}
	}
	
	public void prevPage() {
		if( imagesIndex > 0 ) {
			imagesIndex--;
			pages.getSelectionModel().select(imagesIndex);
		}
	}
	
	public void gotoPage() {
		int index  = pages.getSelectionModel().getSelectedIndex();
		if( index >= 0 && index <= (images.size()-1) ) {
			imagesIndex = index;
			setImage(imagesIndex);
		}
	}

	public void fitWidth() { imageView.fitWidth(); }
	public void fitHeight() { imageView.fitHeight(); }
	public void fitNone() { imageView.fitNone(); }
	public void zoomIn() { imageView.zoomIn(); }
	public void zoomOut() { imageView.zoomOut(); }


	MenuBar getMenuBar() {
		int fontSize = 12;
		MenuBar menubar = new MenuBar();
		menubar.getMenus().add(getFileMenu());
		menubar.setStyle("-fx-font: " + fontSize + " arial;");
		return menubar;
	}
	public Menu getFileMenu() {
		Menu menu = new Menu("File");
		MenuItem item = new MenuItem("Exit");
		item.setOnAction( (e) -> { System.exit(0); });
		menu.getItems().add(item);
		menu.setStyle("-fx-font: " + fontSize + " arial;");
		item.setStyle("-fx-font: " + fontSize + " arial;");
		return menu;
	}

	public boolean yesnoDialog(String title, String message) {
		Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
		alert.setTitle(title);
		alert.setHeaderText(null);
		alert.setContentText(message);
		alert.initModality(Modality.APPLICATION_MODAL);
		alert.initOwner(primaryStage);
		Optional<ButtonType> result = alert.showAndWait();
		if (result.get() == ButtonType.OK ){
			return true;
		} else {
			return false;
		}
	}
}

댓글 없음:

댓글 쓰기