diff --git a/README.md b/README.md new file mode 100644 index 0000000..c553427 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# basic-text-editor + +A basic Text Editor created using Java and Swing. + +## Functionalities Included: + - A 1920x1080 window + - Loading text files from hard drive for editing + - Finding occurences of a specific string using the search bar on the editor window + - Saving file to hard drive + +## Supported File Types + - .txt + - .rtf + - .csv + - .json + - .md + - other forms of text files... + + Makes it a good tool for cleaning data and finding specific entries used in fields such as Data Science which deal with these file formats, with an easy to use GUI. + +## How to Run: + - Download here: [TextEditor.exe](https://github.com/kritgrover/basic-text-editor/releases) + - Run + +All source files used to compile executable are in the 'src' folder. diff --git a/src/ApplicationRunner.java b/src/ApplicationRunner.java index e2b952c..c689f69 100644 --- a/src/ApplicationRunner.java +++ b/src/ApplicationRunner.java @@ -1,3 +1,7 @@ +/* Runner Class + * Contains main method for the application to run + * Use this to start the app +*/ public class ApplicationRunner { public static void main(String[] args) { new TextEditor(); diff --git a/src/MatchedGroup.java b/src/MatchedGroup.java index 33028f3..85ad4bd 100644 --- a/src/MatchedGroup.java +++ b/src/MatchedGroup.java @@ -1,17 +1,24 @@ +/* MatchedGroup Class + * Methods to return Start and End Indexes for given String +*/ public class MatchedGroup { private final int startIndex; private final int endIndex; - + + //Constructor to set indexes public MatchedGroup(int start, int end) { this.startIndex = start; this.endIndex = end; } - - public int getEndIndex() { - return endIndex; - } - + + //Getter for StartIndex public int getStartIndex() { return startIndex; } + + //Getter for EndIndex + public int getEndIndex() { + return endIndex; + } + } diff --git a/src/SearchCompleteHandler.java b/src/SearchCompleteHandler.java index 24187f1..2957e8e 100644 --- a/src/SearchCompleteHandler.java +++ b/src/SearchCompleteHandler.java @@ -1,5 +1,6 @@ import java.util.List; +//Handler interface for TextSearcher implementation public interface SearchCompleteHandler { void handle(List result); } diff --git a/src/TextEditor.java b/src/TextEditor.java index 49a9d29..faddc1d 100644 --- a/src/TextEditor.java +++ b/src/TextEditor.java @@ -9,6 +9,11 @@ import java.nio.file.Files; import java.util.ArrayList; +/* Editor Class + * Class for building the Text Editor Window + * Uses Swing framework for building the window and the buttons + * Contains methods for functionality + */ public class TextEditor extends JFrame { private JTextArea textArea; private JTextField searchField; @@ -17,7 +22,7 @@ public class TextEditor extends JFrame { private int currentIndex; private java.util.List matchedGroups = new ArrayList<>(); - + //Method for building the editor window public TextEditor() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(1920, 1080); @@ -25,7 +30,9 @@ public TextEditor() { initComponent(); setVisible(true); } - + + + //Adding components private void initComponent() { fileChooser = new JFileChooser(); fileChooser.setName("FileChooser"); @@ -34,11 +41,14 @@ private void initComponent() { buildTop(); buildMenuBar(); } - + + + //Method to build File Menu on Menu Bar private void buildMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("File"); - + + //adding operations JMenuItem loadMenuItem = new JMenuItem("Load"); JMenuItem saveMenuItem = new JMenuItem("Save"); JMenuItem exitMenuItem = new JMenuItem("Exit"); @@ -47,25 +57,30 @@ private void buildMenuBar() { loadMenuItem.setName("MenuOpen"); saveMenuItem.setName("MenuSave"); exitMenuItem.setName("MenuExit"); - + + //executing operations loadMenuItem.addActionListener(l -> loadContent()); saveMenuItem.addActionListener(l -> saveFile(textArea.getText())); exitMenuItem.addActionListener(l -> System.exit(0)); - + + //displaying options menu.add(loadMenuItem); menu.add(saveMenuItem); menu.addSeparator(); menu.add(exitMenuItem); - + menuBar.add(menu); menuBar.add(createSearchMenu()); setJMenuBar(menuBar); } - + + + //Method to build Search Menu for Menu Bar private JMenu createSearchMenu() { JMenu menu = new JMenu("Search"); menu.setName("MenuSearch"); - + + //adding options JMenuItem startMenuItem = new JMenuItem("Start search"); JMenuItem prevMenuItem = new JMenuItem("Previous search"); JMenuItem nextMenuItem = new JMenuItem("Next match"); @@ -75,11 +90,14 @@ private JMenu createSearchMenu() { nextMenuItem.setName("MenuNextMatch"); prevMenuItem.setName("MenuPreviousMatch"); regExMenuItem.setName("MenuUseRegExp"); - + + //executing operations prevMenuItem.addActionListener(l -> onPrev()); nextMenuItem.addActionListener(l -> onNext()); startMenuItem.addActionListener(l -> onSearch()); regExMenuItem.addActionListener(l -> toggleCheckBox()); + + //displaying options menu.add(startMenuItem); menu.add(prevMenuItem); menu.add(nextMenuItem); @@ -87,33 +105,18 @@ private JMenu createSearchMenu() { return menu; } - - private void toggleCheckBox() { - boolean currentChecked = !checkBox.isSelected(); - checkBox.setSelected(currentChecked); - } - - private void addTextArea() { - JScrollPane scrollPane = new JScrollPane(); - scrollPane.setEnabled(true); - scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); - scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - addBorder(scrollPane, 0, 8, 8, 8); - scrollPane.setName("ScrollPane"); - setLocationRelativeTo(null); - textArea = new JTextArea(); - textArea.setName("TextArea"); - textArea.setLineWrap(true); - scrollPane.setViewportView(textArea); - add(scrollPane, BorderLayout.CENTER); - } - + + + //Method for building buttons above text area private void buildTop() { JPanel panel = new JPanel(); panel.setAlignmentX(Component.LEFT_ALIGNMENT); + + //Images folder not added in this code but can be used if needed ImageIcon saveButtonImage = new ImageIcon("images/diskette.png"); ImageIcon loadImageIcon = new ImageIcon("images/open.png"); - + + //Initializing Load and Save Buttons JButton saveButton = new JButton(saveButtonImage); JLabel saveButtonLabel = new JLabel("Save"); JButton loadButton = new JButton(loadImageIcon); @@ -121,11 +124,12 @@ private void buildTop() { loadButton.setName("OpenButton"); saveButton.setName("SaveButton"); - + + //Adding functionality loadButton.addActionListener(l -> loadContent()); saveButton.addActionListener(l -> saveFile(textArea.getText())); - + //Displaying Buttons panel.add(loadButton); panel.add(loadButtonLabel); panel.add(saveButton); @@ -140,39 +144,65 @@ private void buildTop() { layout.setAlignment(FlowLayout.LEFT); add(container, BorderLayout.NORTH); } - + + + //Method for building Text Area where the editing takes place + private void addTextArea() { + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setEnabled(true); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + addBorder(scrollPane, 0, 8, 8, 8); + scrollPane.setName("ScrollPane"); + setLocationRelativeTo(null); + textArea = new JTextArea(); + textArea.setName("TextArea"); + textArea.setLineWrap(true); + scrollPane.setViewportView(textArea); + add(scrollPane, BorderLayout.CENTER); + } + + /* + * Method for creating Search panel and regex options + * - Creates a search bar for finding specific string in loaded file + * - Next and Previous Buttons are used to find corresponding occurences of the string + */ private JPanel createSearchPanel() { JPanel panel = new JPanel(); - + + //Images folder not included in this code but can be used if needed ImageIcon nextIcon = new ImageIcon("images/next.jpg"); ImageIcon prevIcon = new ImageIcon("images/previous.png"); ImageIcon searchIcon = new ImageIcon("images/search.png"); - + + //Initializing buttons JButton searchButton = new JButton(searchIcon); JLabel searchButtonLabel = new JLabel("Search"); JButton nextButton = new JButton(nextIcon); JLabel nextButtonLabel = new JLabel("Next"); JButton prevButton = new JButton(prevIcon); JLabel prevButtonLabel = new JLabel("Prev"); - + searchButton.setName("StartSearchButton"); prevButton.setName("PreviousMatchButton"); nextButton.setName("NextMatchButton"); - + + //Adding functionality searchButton.addActionListener(l -> onSearch()); - nextButton.addActionListener(l -> onNext()); prevButton.addActionListener(l -> onPrev()); - + + //Making search bar searchField = new JTextField(18); searchField.setName("SearchField"); searchField.setPreferredSize(new Dimension(18, 35)); - + + //Making Use Regex checkbox checkBox = new JCheckBox(); checkBox.setName("UseRegExCheckbox"); JLabel checkBoxLabel = new JLabel("Use regex"); - + //Displaying buttons panel.add(searchField); panel.add(searchButton); panel.add(searchButtonLabel); @@ -185,16 +215,13 @@ private JPanel createSearchPanel() { return panel; } - - private void onSearch() { - currentIndex = 0; - matchedGroups = java.util.List.of(); - TextSearcher textSearcher = new TextSearcher(this::handleSearch); - textSearcher.setTextToSearch(searchField.getText()); - textSearcher.setContent(textArea.getText()); - textSearcher.execute(); + + private void toggleCheckBox() { + boolean currentChecked = !checkBox.isSelected(); + checkBox.setSelected(currentChecked); } - + + //Adding borders for components private void addBorder(JComponent component, int top, int right, int bottom, int left) { Border border = component.getBorder(); Border empty = new EmptyBorder(top, left, bottom, right); @@ -204,7 +231,20 @@ private void addBorder(JComponent component, int top, int right, int bottom, int } component.setBorder(new CompoundBorder(empty, border)); } - + + + //Functionality for Search Button + private void onSearch() { + currentIndex = 0; + matchedGroups = java.util.List.of(); + TextSearcher textSearcher = new TextSearcher(this::handleSearch); + textSearcher.setTextToSearch(searchField.getText()); //Specifying string to find + textSearcher.setContent(textArea.getText()); //Specifying data to look through + textSearcher.execute(); //Runs doInBackground() and done() + } + + + //Functionality for Load button private void loadContent() { int returnedValue = fileChooser.showOpenDialog(null); if(returnedValue == JFileChooser.APPROVE_OPTION) { @@ -217,17 +257,9 @@ private void loadContent() { } } } - - private void handleSearch(java.util.List matchedGroupList) { - if(!matchedGroupList.isEmpty()) { - this.matchedGroups = matchedGroupList; - MatchedGroup matchedGroup = matchedGroupList.get(currentIndex); - setCaretPosition(matchedGroup); - } else { - this.matchedGroups = java.util.List.of(); - } - } - + + + //Functionality for Next button private void onNext() { if(matchedGroups.isEmpty()) return; @@ -237,7 +269,9 @@ private void onNext() { } setCaretPosition(matchedGroups.get(currentIndex)); } - + + + //Functionality for Previous button private void onPrev() { if(matchedGroups.isEmpty()) return; @@ -247,20 +281,40 @@ private void onPrev() { } setCaretPosition(matchedGroups.get(currentIndex)); } - + + + //Functionality for Save button private void saveFile(String content) { fileChooser.setDialogTitle("Save File"); fileChooser.showOpenDialog(null); File file = fileChooser.getSelectedFile(); if(file == null) return; + try(FileWriter fileWriter = new FileWriter(file)) { fileWriter.write(content); } catch (IOException e) { //do nothing } } - + + + /* HandleSearch Method + * Stores given MatchedGroup List to instance variable + * Creates new MatchedCroup with current index + */ + private void handleSearch(java.util.List matchedGroupList) { + if(!matchedGroupList.isEmpty()) { + this.matchedGroups = matchedGroupList; + MatchedGroup matchedGroup = matchedGroupList.get(currentIndex); + setCaretPosition(matchedGroup); + } else { + this.matchedGroups = java.util.List.of(); + } + } + + + //Method for highlighting String found using Search Bar private void setCaretPosition(MatchedGroup matchedGroup) { textArea.setCaretPosition(matchedGroup.getEndIndex()); textArea.select(matchedGroup.getStartIndex(), matchedGroup.getEndIndex()); diff --git a/src/TextSearcher.java b/src/TextSearcher.java index c73db35..6d054fa 100644 --- a/src/TextSearcher.java +++ b/src/TextSearcher.java @@ -5,16 +5,36 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/* Searcher class to find strings + * Sets input + * Sets content to search from + * Returns ArrayList of found positions + * Confirms execution +*/ public class TextSearcher extends SwingWorker,Void> { private String textToSearch = ""; private String content; private final SearchCompleteHandler searchCompleteHandler; - + + //Constructor to implement search handling public TextSearcher (SearchCompleteHandler searchCompleteHandler) { this.searchCompleteHandler = searchCompleteHandler; } - - + + + //Setter for input to be searched for + public void setTextToSearch(String textToSearch) { + this.textToSearch = textToSearch; + } + + + //Setter for defining content to search from + public void setContent(String content) { + this.content = content; + } + + + //Method to return an ArrayList of found occurences of String @Override protected List doInBackground() { Pattern pattern = Pattern.compile(textToSearch); @@ -25,7 +45,9 @@ protected List doInBackground() { } return positions; } - + + + //Method to confirm execution @Override protected void done() { try { @@ -34,12 +56,4 @@ protected void done() { //do Nothing } } - - public void setTextToSearch(String textToSearch) { - this.textToSearch = textToSearch; - } - - public void setContent(String content) { - this.content = content; - } }