From 8e4c32df6808e5b137e940f55b4c8510849ae196 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 16 Oct 2023 18:01:50 +0300 Subject: [PATCH 1/3] Created Lab3 module --- Lab3/src/main/java/org/lumijiez/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lab3/src/main/java/org/lumijiez/Main.java b/Lab3/src/main/java/org/lumijiez/Main.java index b8820be..9bd2ff2 100644 --- a/Lab3/src/main/java/org/lumijiez/Main.java +++ b/Lab3/src/main/java/org/lumijiez/Main.java @@ -6,7 +6,7 @@ public class Main { public static void main(String[] args) { // Press Alt+Enter with your caret at the highlighted text to see how // IntelliJ IDEA suggests fixing it. - System.out.print("Hello and welcome!"); + System.out.println("Hello and welcome!"); // Press Shift+F10 or click the green arrow button in the gutter to run the code. for (int i = 1; i <= 5; i++) { From 985934f90c1ce036deb10269ee52b298c7a5b4ef Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 16 Oct 2023 18:56:48 +0300 Subject: [PATCH 2/3] MVP Gui and Logic --- Lab3/src/main/java/org/lumijiez/Main.java | 18 +-- .../main/java/org/lumijiez/gui/MainFrame.java | 133 ++++++++++++++++++ .../org/lumijiez/tracker/TrackerThread.java | 60 ++++++++ 3 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 Lab3/src/main/java/org/lumijiez/gui/MainFrame.java create mode 100644 Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java diff --git a/Lab3/src/main/java/org/lumijiez/Main.java b/Lab3/src/main/java/org/lumijiez/Main.java index 9bd2ff2..b7c22c9 100644 --- a/Lab3/src/main/java/org/lumijiez/Main.java +++ b/Lab3/src/main/java/org/lumijiez/Main.java @@ -1,19 +1,11 @@ package org.lumijiez; -// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`, -// then press Enter. You can now see whitespace characters in your code. +import org.lumijiez.gui.MainFrame; + +import javax.swing.*; + public class Main { public static void main(String[] args) { - // Press Alt+Enter with your caret at the highlighted text to see how - // IntelliJ IDEA suggests fixing it. - System.out.println("Hello and welcome!"); - - // Press Shift+F10 or click the green arrow button in the gutter to run the code. - for (int i = 1; i <= 5; i++) { - - // Press Shift+F9 to start debugging your code. We have set one breakpoint - // for you, but you can always add more by pressing Ctrl+F8. - System.out.println("i = " + i); - } + SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); } } \ No newline at end of file diff --git a/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java b/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java new file mode 100644 index 0000000..837fc28 --- /dev/null +++ b/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java @@ -0,0 +1,133 @@ +package org.lumijiez.gui; +import org.lumijiez.tracker.TrackerThread; + +import javax.swing.*; +import java.awt.*; +import java.nio.file.Path; + +public class MainFrame extends JFrame { + private final JScrollPane fileListScrollPane = new JScrollPane(); + private final JList fileList = new JList<>(); + private final JLabel pathLabel = new JLabel(); + private final JScrollPane mainScrollPane = new JScrollPane(); + private final JTextPane mainTextPane = new JTextPane(); + private final JLabel snapshotLabel = new JLabel(); + private final JButton CommitButton = new JButton(); + private final JButton StatusButton = new JButton(); + private final JMenuBar MainMenubar = new JMenuBar(); + private final JMenu fileMenu = new JMenu(); + private final JMenuItem pickFolder = new JMenuItem(); + private final JMenu settingsMenu = new JMenu(); + private final JMenuItem settings = new JMenuItem(); + + public MainFrame() { + initComponents(); + } + + private void initComponents() { + + + JFileChooser folderChooser = new JFileChooser(); + folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + int returnVal = folderChooser.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + System.out.println("Selected folder: " + folderChooser.getSelectedFile().getAbsolutePath()); + TrackerThread tr = new TrackerThread(mainTextPane, Path.of(folderChooser.getSelectedFile().getAbsolutePath())); + tr.start(); + } + + setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + fileList.setModel(new AbstractListModel<>() { + final String[] strings = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"}; + + public int getSize() { + return strings.length; + } + + public String getElementAt(int i) { + return strings[i]; + } + }); + fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + fileListScrollPane.setViewportView(fileList); + + snapshotLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N + snapshotLabel.setText("Last snapshot:"); + + mainScrollPane.setViewportView(mainTextPane); + + pathLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N + pathLabel.setText("Currently tracking: "); + + CommitButton.setText("Commit"); + CommitButton.addActionListener(this::CommitButtonActionPerformed); + + StatusButton.setText("Status"); + StatusButton.addActionListener(this::StatusButtonActionPerformed); + + fileMenu.setText("File"); + + pickFolder.setText("Pick another folder"); + fileMenu.add(pickFolder); + + MainMenubar.add(fileMenu); + + settingsMenu.setText("Edit"); + + settings.setText("Settings"); + settingsMenu.add(settings); + + MainMenubar.add(settingsMenu); + + setJMenuBar(MainMenubar); + + GroupLayout layout = new GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(pathLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(snapshotLabel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(fileListScrollPane, GroupLayout.PREFERRED_SIZE, 195, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(mainScrollPane, GroupLayout.PREFERRED_SIZE, 599, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(CommitButton) + .addGap(0, 1, Short.MAX_VALUE)) + .addComponent(StatusButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(snapshotLabel, GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pathLabel, GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false) + .addComponent(fileListScrollPane, GroupLayout.DEFAULT_SIZE, 573, Short.MAX_VALUE) + .addComponent(mainScrollPane)) + .addGroup(layout.createSequentialGroup() + .addComponent(CommitButton) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(StatusButton))) + .addContainerGap()) + ); + + pack(); + } + + private void CommitButtonActionPerformed(java.awt.event.ActionEvent evt) { + } + + private void StatusButtonActionPerformed(java.awt.event.ActionEvent evt) { + } +} diff --git a/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java b/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java new file mode 100644 index 0000000..c9bd174 --- /dev/null +++ b/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java @@ -0,0 +1,60 @@ +package org.lumijiez.tracker; + +import javax.swing.*; +import java.io.IOException; +import java.nio.file.*; + +public class TrackerThread extends Thread { + private final JTextPane textPane; + private final Path path; + + public TrackerThread(JTextPane textPane, Path path) { + this.textPane = textPane; + this.path = path; + } + + public void checkDirectory(Path path) { + try { + WatchService watchService = FileSystems.getDefault().newWatchService(); + path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); + + while (true) { + WatchKey key; + try { + key = watchService.take(); + } catch (InterruptedException e) { + return; + } + + for (WatchEvent event : key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + + @SuppressWarnings("unchecked") + WatchEvent ev = (WatchEvent) event; + Path fileName = ev.context(); + + System.out.println(kind.name() + ": " + fileName); + + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + textPane.setText(textPane.getText() + " file created\n"); + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { + textPane.setText(textPane.getText() + " file modified\n"); + } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { + textPane.setText(textPane.getText() + " file deleted\n"); + } + } + + boolean valid = key.reset(); + if (!valid) { + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + @Override + public void run() { + checkDirectory(path); + } +} From 4ecd73d4ed4d7f14a02dc263209ebd1d00359cea Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 16 Oct 2023 22:03:31 +0300 Subject: [PATCH 3/3] Improved logic, broke down in classes, Thread quicker --- Lab3/src/main/java/org/lumijiez/Main.java | 9 +- .../main/java/org/lumijiez/gui/MainFrame.java | 41 +++---- .../org/lumijiez/tracker/TrackerThread.java | 106 ++++++++++++------ .../main/java/org/lumijiez/util/DiffType.java | 5 + .../java/org/lumijiez/util/FileDiffer.java | 61 ++++++++++ .../java/org/lumijiez/util/StateType.java | 14 +++ 6 files changed, 179 insertions(+), 57 deletions(-) create mode 100644 Lab3/src/main/java/org/lumijiez/util/DiffType.java create mode 100644 Lab3/src/main/java/org/lumijiez/util/FileDiffer.java create mode 100644 Lab3/src/main/java/org/lumijiez/util/StateType.java diff --git a/Lab3/src/main/java/org/lumijiez/Main.java b/Lab3/src/main/java/org/lumijiez/Main.java index b7c22c9..aa6e1f9 100644 --- a/Lab3/src/main/java/org/lumijiez/Main.java +++ b/Lab3/src/main/java/org/lumijiez/Main.java @@ -3,9 +3,16 @@ package org.lumijiez; import org.lumijiez.gui.MainFrame; import javax.swing.*; +import java.io.IOException; public class Main { public static void main(String[] args) { - SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); + SwingUtilities.invokeLater(() -> { + try { + new MainFrame().setVisible(true); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); } } \ No newline at end of file diff --git a/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java b/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java index 837fc28..0d31c42 100644 --- a/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java +++ b/Lab3/src/main/java/org/lumijiez/gui/MainFrame.java @@ -3,7 +3,10 @@ import org.lumijiez.tracker.TrackerThread; import javax.swing.*; import java.awt.*; +import java.io.File; +import java.io.IOException; import java.nio.file.Path; +import java.util.*; public class MainFrame extends JFrame { private final JScrollPane fileListScrollPane = new JScrollPane(); @@ -19,47 +22,38 @@ public class MainFrame extends JFrame { private final JMenuItem pickFolder = new JMenuItem(); private final JMenu settingsMenu = new JMenu(); private final JMenuItem settings = new JMenuItem(); + private final Map fileContents = new HashMap<>(); + private TrackerThread tracker; - public MainFrame() { + public MainFrame() throws IOException { initComponents(); } private void initComponents() { + mainTextPane.setContentType("text/html"); JFileChooser folderChooser = new JFileChooser(); folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - int returnVal = folderChooser.showOpenDialog(this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - System.out.println("Selected folder: " + folderChooser.getSelectedFile().getAbsolutePath()); - TrackerThread tr = new TrackerThread(mainTextPane, Path.of(folderChooser.getSelectedFile().getAbsolutePath())); - tr.start(); - } - setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - fileList.setModel(new AbstractListModel<>() { - final String[] strings = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"}; + int returnVal = folderChooser.showOpenDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + tracker = new TrackerThread(mainTextPane, Path.of(folderChooser.getSelectedFile().getAbsolutePath()), fileContents, fileList); + tracker.start(); + } - public int getSize() { - return strings.length; - } - - public String getElementAt(int i) { - return strings[i]; - } - }); fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fileListScrollPane.setViewportView(fileList); snapshotLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N - snapshotLabel.setText("Last snapshot:"); + snapshotLabel.setText("Last snapshot: " + new Date()); mainScrollPane.setViewportView(mainTextPane); pathLabel.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, 18)); // NOI18N - pathLabel.setText("Currently tracking: "); + pathLabel.setText("Currently tracking: " + folderChooser.getSelectedFile().getAbsolutePath()); CommitButton.setText("Commit"); CommitButton.addActionListener(this::CommitButtonActionPerformed); @@ -119,13 +113,14 @@ public class MainFrame extends JFrame { .addComponent(CommitButton) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(StatusButton))) - .addContainerGap()) - ); - + .addContainerGap())); pack(); } private void CommitButtonActionPerformed(java.awt.event.ActionEvent evt) { + tracker.reset(); + mainTextPane.setText(""); + snapshotLabel.setText("Last snapshot: " + new Date()); } private void StatusButtonActionPerformed(java.awt.event.ActionEvent evt) { diff --git a/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java b/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java index c9bd174..b50045b 100644 --- a/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java +++ b/Lab3/src/main/java/org/lumijiez/tracker/TrackerThread.java @@ -1,60 +1,100 @@ package org.lumijiez.tracker; +import org.lumijiez.util.DiffType; +import org.lumijiez.util.FileDiffer; +import org.lumijiez.util.StateType; + import javax.swing.*; -import java.io.IOException; +import java.io.File; import java.nio.file.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; public class TrackerThread extends Thread { private final JTextPane textPane; private final Path path; + private Map fileContents; + private final JList fileList; + private final Map fileStates = new HashMap<>(); - public TrackerThread(JTextPane textPane, Path path) { + public TrackerThread(JTextPane textPane, Path path, Map files, JList fileList) { this.textPane = textPane; this.path = path; + this.fileContents = files; + this.fileList = fileList; + init(); } - public void checkDirectory(Path path) { - try { - WatchService watchService = FileSystems.getDefault().newWatchService(); - path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); + public void init() { + System.out.println("Init called"); + fileContents = FileDiffer.crawlDirectory(path); - while (true) { - WatchKey key; - try { - key = watchService.take(); - } catch (InterruptedException e) { - return; - } + ArrayList fileNames = new ArrayList<>(); - for (WatchEvent event : key.pollEvents()) { - WatchEvent.Kind kind = event.kind(); + for (File file : fileContents.keySet()) { + fileNames.add(file.getName()); + } + fileList.setModel(new AbstractListModel<>() { + public int getSize() { + return fileNames.size(); + } + public String getElementAt(int i) { + return fileNames.get(i); + } + }); + } - @SuppressWarnings("unchecked") - WatchEvent ev = (WatchEvent) event; - Path fileName = ev.context(); + public void reset() { + fileStates.clear(); + } - System.out.println(kind.name() + ": " + fileName); + public void checkDirectory() { + Map> result = FileDiffer.diff(fileContents, FileDiffer.crawlDirectory(path)); - if (kind == StandardWatchEventKinds.ENTRY_CREATE) { - textPane.setText(textPane.getText() + " file created\n"); - } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { - textPane.setText(textPane.getText() + " file modified\n"); - } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { - textPane.setText(textPane.getText() + " file deleted\n"); - } - } + StringBuilder toShow = new StringBuilder(); - boolean valid = key.reset(); - if (!valid) { - break; + boolean created = false, deleted = false, modified = false; + if (!result.get(DiffType.CREATE).isEmpty()) { + created = true; + for (File file : result.get(DiffType.CREATE)) { + fileStates.put(file, StateType.NEW); + } + System.out.println("Created"); + } + + if (!result.get(DiffType.DELETE).isEmpty()) { + deleted = true; + for (File file : result.get(DiffType.DELETE)) { + fileStates.put(file, StateType.DELETED); + } + System.out.println("Deleted"); + } + + if (!result.get(DiffType.MODIFY).isEmpty()) { + modified = true; + for (File file : result.get(DiffType.MODIFY)) { + fileStates.put(file, StateType.MODIFIED); + } + System.out.println("Modified"); + } + + if (created || deleted || modified) { + init(); + for (File file : fileStates.keySet()) { + if (fileStates.get(file) != StateType.NONE) { + toShow.append(file.getName()).append(" has been ").append(fileStates.get(file).getName()).append("
"); } } - } catch (IOException e) { - e.printStackTrace(); + textPane.setText(toShow.toString()); } } + @Override public void run() { - checkDirectory(path); + while(this.isAlive()) { + checkDirectory(); + //Thread.sleep(200); + } } } diff --git a/Lab3/src/main/java/org/lumijiez/util/DiffType.java b/Lab3/src/main/java/org/lumijiez/util/DiffType.java new file mode 100644 index 0000000..2be9dfd --- /dev/null +++ b/Lab3/src/main/java/org/lumijiez/util/DiffType.java @@ -0,0 +1,5 @@ +package org.lumijiez.util; + +public enum DiffType { + CREATE, DELETE, MODIFY, NONE +} diff --git a/Lab3/src/main/java/org/lumijiez/util/FileDiffer.java b/Lab3/src/main/java/org/lumijiez/util/FileDiffer.java new file mode 100644 index 0000000..5316fe5 --- /dev/null +++ b/Lab3/src/main/java/org/lumijiez/util/FileDiffer.java @@ -0,0 +1,61 @@ +package org.lumijiez.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public class FileDiffer { + public static Map> diff(Map oldFiles, Map newFiles) { + Map> result = new HashMap<>(); + + ArrayList newFileList = new ArrayList<>(); + ArrayList deletedFileList = new ArrayList<>(); + ArrayList modifiedFileList = new ArrayList<>(); + + for (File file : oldFiles.keySet()) { + if (newFiles.get(file) != null) { + if (Arrays.compare(oldFiles.get(file), newFiles.get(file)) != 0) { + modifiedFileList.add(file); + } + } else { + deletedFileList.add(file); + } + } + + for (File file : newFiles.keySet()) { + if (oldFiles.get(file) == null) { + newFileList.add(file); + } + } + + result.put(DiffType.CREATE, newFileList); + result.put(DiffType.DELETE, deletedFileList); + result.put(DiffType.MODIFY, modifiedFileList); + + return result; + } + + public static Map crawlDirectory(Path path) { + Map newFileContents = new HashMap<>(); + try (Stream paths = Files.walk(path)) { + paths.forEach(p -> { + if (Files.isRegularFile(p)) { + try { + newFileContents.put(p.toFile(), Files.readAllBytes(p)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + return newFileContents; + } +} diff --git a/Lab3/src/main/java/org/lumijiez/util/StateType.java b/Lab3/src/main/java/org/lumijiez/util/StateType.java new file mode 100644 index 0000000..66483ab --- /dev/null +++ b/Lab3/src/main/java/org/lumijiez/util/StateType.java @@ -0,0 +1,14 @@ +package org.lumijiez.util; + +public enum StateType { + NEW("Created"), MODIFIED("Modified"), DELETED("Deleted"), NONE("Nothing"); + + private final String name; + StateType(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +}