diff --git a/imageloader/.gitignore b/imageloader/.gitignore new file mode 100644 index 0000000..d34da8a --- /dev/null +++ b/imageloader/.gitignore @@ -0,0 +1,15 @@ +# ---> Java +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +target/ diff --git a/imageloader/README.md b/imageloader/README.md new file mode 100644 index 0000000..9bc6d9e --- /dev/null +++ b/imageloader/README.md @@ -0,0 +1,2 @@ +# swing-image-loader + diff --git a/imageloader/pom.xml b/imageloader/pom.xml new file mode 100644 index 0000000..227b98c --- /dev/null +++ b/imageloader/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + + 1.8 + 1.8 + + + fr.uha.gabalier + swing-image-loader + 0.1 + + + \ No newline at end of file diff --git a/imageloader/src/main/java/fr/uha/gabalier/controller/Controller.java b/imageloader/src/main/java/fr/uha/gabalier/controller/Controller.java new file mode 100644 index 0000000..e8c33eb --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/controller/Controller.java @@ -0,0 +1,29 @@ +package fr.uha.gabalier.controller; + +import fr.uha.gabalier.view.View; + +public class Controller { + + private T model; + private View view; + + protected Controller(T model) { + this.model = model; + } + + protected T getModel() { + return model; + } + + protected void setModel(T model) { + this.model = model; + } + + protected View getView() { + return view; + } + + public void setView(View v) { + this.view = v; + } +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/controller/ImageController.java b/imageloader/src/main/java/fr/uha/gabalier/controller/ImageController.java new file mode 100644 index 0000000..f689ef8 --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/controller/ImageController.java @@ -0,0 +1,58 @@ +package fr.uha.gabalier.controller; + +import fr.uha.gabalier.view.Preview; +import fr.uha.gabalier.view.View; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class ImageController extends Controller> implements ActionListener { + + private int index; + + public ImageController(List newModel) { + super(newModel); + this.index = 0; + } + + @Override + public void actionPerformed(ActionEvent evt) { + switch (evt.getActionCommand()) { + case Preview.LEFT_COMMAND : + doLeft(); + break; + case Preview.RIGHT_COMMAND: + doRight(); + break; + } + } + + private void doRight() { + if (getModel() == null) return; + if (getModel().size() == 0) return; + if (++index > getModel().size() - 1) index = 0; + getView().repaint(); + } + + private void doLeft() { + if (getModel() == null) return; + if (getModel().size() == 0) return; + if (--index < 0) index = getModel().size() - 1; + getView().repaint(); + } + + public int getIndex() { + return index; + } + + public void resetIndex() { + this.index = 0; + } + + public void setModel(List model) { + super.setModel(model); + this.index = 0; + } +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/core/ImageLoader.java b/imageloader/src/main/java/fr/uha/gabalier/core/ImageLoader.java new file mode 100644 index 0000000..f16dbfe --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/core/ImageLoader.java @@ -0,0 +1,70 @@ +package fr.uha.gabalier.core; + +import fr.uha.gabalier.util.ImageLib; +import fr.uha.gabalier.view.Preview; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; + +public class ImageLoader extends SwingWorker, Integer> { + + private final File root; + private Preview app; + private List images; + private final int iconWidth; + + public ImageLoader(Preview app, int iconWidth, File root) { + this.root = root; + this.app = app; + this.iconWidth = iconWidth; + this.images = new ArrayList<>(); + } + + private void loadImages(File current) throws NullPointerException { + if (current.isFile()) { + final Image icon = ImageLib.createScaledImage(current, this.iconWidth, -1); + if (icon != null) { + images.add(icon); + publish(images.size()); + } + return; + } + + final File[] files = current.listFiles(); + if (files == null) throw new NullPointerException(); + for (File f : files) { + loadImages(f); + } + } + + @Override + protected List doInBackground() throws Exception { + loadImages(root); + return images; + } + + @Override + protected void process(List data) { + if (this.isCancelled()) return; + app.setStatus(String.valueOf(data.get(data.size() - 1)) + " images loaded"); + } + + @Override + protected void done() { + try { + app.setModel(this.get()); + app.setStatus(app.getModel().size() + " images loaded"); + } catch (CancellationException e) { + app.setStatus("Cancelled"); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } finally { + app.postLoad(); + } + } +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/util/ImageLib.java b/imageloader/src/main/java/fr/uha/gabalier/util/ImageLib.java new file mode 100644 index 0000000..cd962ee --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/util/ImageLib.java @@ -0,0 +1,24 @@ +package fr.uha.gabalier.util; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +public final class ImageLib { + + public static Image createScaledImage(File file, int iconWidth, int iconHeight) { + final BufferedImage img; + try { + if ((img = ImageIO.read(file)) != null) { + return img.getScaledInstance(iconWidth, iconHeight, Image.SCALE_DEFAULT); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + private ImageLib() {} +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/view/ImageView.java b/imageloader/src/main/java/fr/uha/gabalier/view/ImageView.java new file mode 100644 index 0000000..3e25f18 --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/view/ImageView.java @@ -0,0 +1,25 @@ +package fr.uha.gabalier.view; + +import fr.uha.gabalier.controller.ImageController; + +import java.awt.*; +import java.util.List; + +public class ImageView extends View> { + + public ImageView(List model) { + super(model); + this.setPreferredSize(new Dimension(Preview.VIEW_WIDTH, Preview.VIEW_HEIGHT)); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + final List model = this.getModel(); + if (model == null) return; + if (model.size() == 0) return; + + final int index = ((ImageController) this.getController()).getIndex(); + g.drawImage(model.get(index), 10, 10, this); + } +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/view/Preview.java b/imageloader/src/main/java/fr/uha/gabalier/view/Preview.java new file mode 100644 index 0000000..8b9b2eb --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/view/Preview.java @@ -0,0 +1,130 @@ +package fr.uha.gabalier.view; + +import fr.uha.gabalier.controller.ImageController; +import fr.uha.gabalier.core.ImageLoader; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +public class Preview extends JFrame { + + static final int VIEW_WIDTH = 256; + static final int VIEW_HEIGHT = 128; + + public static final String LEFT_COMMAND = "<"; + public static final String RIGHT_COMMAND = ">"; + private static final int ICON_WIDTH = 256; + + private List model; + private ImageLoader loader; + private ImageView imageView; + + // UI elements + private JMenuItem loadItem; + private JMenuItem cancelItem; + private JButton rightNavButton; + private JButton leftNavButton; + private final JTextField statusText; + + public Preview() throws HeadlessException { + model = new ArrayList<>(); + // UI elements + JMenuBar menuBar = new JMenuBar(); + setJMenuBar(menuBar); + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + + loadItem = new JMenuItem("Load"); + fileMenu.add(loadItem); + loadItem.addActionListener(actionEvent -> doLoad()); + cancelItem = new JMenuItem("Cancel"); + fileMenu.add(cancelItem); + cancelItem.addActionListener(actionEvent -> doCancel()); + final JMenuItem exitItem = new JMenuItem("Exit"); + exitItem.addActionListener(actionEvent -> doExit()); + exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK)); + fileMenu.add(exitItem); + + setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); + + imageView = new ImageView(model); + final ImageController controller = new ImageController(model); + imageView.setController(controller); + controller.setView(imageView); + getContentPane().add(imageView); + + final JPanel navPanel = new JPanel(); + getContentPane().add(navPanel); + leftNavButton = new JButton(LEFT_COMMAND); + leftNavButton.addActionListener(controller); + navPanel.add(leftNavButton); + rightNavButton = new JButton(RIGHT_COMMAND); + rightNavButton.addActionListener(controller); + navPanel.add(rightNavButton); + + final JPanel statusPanel = new JPanel(); + getContentPane().add(statusPanel); + statusText = new JTextField("0000 images loaded"); + statusPanel.add(new JLabel("status :")); + statusPanel.add(statusText); + + pack(); + setVisible(true); + } + + public void setModel(List images) { + this.model.clear(); + this.model.addAll(images); + ((ImageController) imageView.getController()).resetIndex(); + } + + public List getModel() { + return model; + } + + public void setStatus(String status) { + this.statusText.setText(status); + } + + private void doLoad() { + final JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + final int ret = fc.showOpenDialog(this); + if (ret == JFileChooser.APPROVE_OPTION) { + loader = new ImageLoader(this, ICON_WIDTH, fc.getSelectedFile()); + preLoad(); + loader.execute(); + } + } + + private void doExit() { + System.exit(0); + } + + private void doCancel() { + loader.cancel(true); + } + + public void preLoad() { + loadItem.setEnabled(false); + cancelItem.setEnabled(true); + rightNavButton.setEnabled(false); + leftNavButton.setEnabled(false); + } + + public void postLoad() { + loadItem.setEnabled(true); + cancelItem.setEnabled(false); + rightNavButton.setEnabled(true); + leftNavButton.setEnabled(true); + } + + public static void main(String[] args) { + EventQueue.invokeLater(Preview::new); + } + +} diff --git a/imageloader/src/main/java/fr/uha/gabalier/view/View.java b/imageloader/src/main/java/fr/uha/gabalier/view/View.java new file mode 100644 index 0000000..6ef11ea --- /dev/null +++ b/imageloader/src/main/java/fr/uha/gabalier/view/View.java @@ -0,0 +1,27 @@ +package fr.uha.gabalier.view; + +import fr.uha.gabalier.controller.Controller; + +import javax.swing.*; + +public class View extends JPanel { + + private final T model; + private Controller controller; + + protected View(T model) { + this.model = model; + } + + protected T getModel() { + return model; + } + + protected Controller getController() { + return controller; + } + + protected void setController(Controller controller) { + this.controller = controller; + } +}