From db29bae77b5d49a6ffd918267af53a019739ed59 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 8 Mar 2016 10:48:10 -0500 Subject: [PATCH 01/15] Adding a getContent() method to UI.java This is for getting the text of the textArea so we can perform autocomplete. It takes two parameters which directly correlate to the getText() method of the TextArea class. --- src/simplejavatexteditor/UI.java | 11 +- src/simplejavatexteditor/UI.java~ | 295 ++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 src/simplejavatexteditor/UI.java~ diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index 053932e..aef9ad1 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -29,6 +29,7 @@ // Various import java.util.Scanner; import javax.swing.border.Border; +import javax.swing.text.BadLocationException; public class UI extends JFrame implements ActionListener { @@ -291,5 +292,13 @@ else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { } } - + protected String getContent(int i, int j) { + String content = ""; + try { + content = textArea.getText(i, j); + } catch(BadLocationException e) { + e.printStackTrace(); + } + return content; + } } \ No newline at end of file diff --git a/src/simplejavatexteditor/UI.java~ b/src/simplejavatexteditor/UI.java~ new file mode 100644 index 0000000..053932e --- /dev/null +++ b/src/simplejavatexteditor/UI.java~ @@ -0,0 +1,295 @@ +/** + * @name Simple Java NotePad + * @package ph.notepad + * @file UI.java + * @author SORIA Pierre-Henry + * @email pierrehs@hotmail.com + * @link http://github.com/pH-7 + * @copyright Copyright Pierre-Henry SORIA, All Rights Reserved. + * @license Apache (http://www.apache.org/licenses/LICENSE-2.0) + * @create 2012-05-04 + * @update 2015-09-4 + * + * + * @modifiedby Achintha Gunasekara + * @modweb http://www.achinthagunasekara.com + * @modemail contact@achinthagunasekara.com + */ + +package simplejavatexteditor; + +// GUI +import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Font; +import java.awt.event.*; +// Input Stream +import java.io.*; +// Various +import java.util.Scanner; +import javax.swing.border.Border; + +public class UI extends JFrame implements ActionListener { + + private static final long serialVersionUID = 1L; + private final Container container; + private final JTextArea textArea; + private final JMenuBar menuBar; + private final JMenu menuFile, menuEdit, menuFind, menuAbout; + private final JMenuItem newFile, openFile, saveFile, close, clearFile, quickFind, aboutMe, aboutSoftware; + private final JToolBar mainToolbar; + JButton newButton, openButton, saveButton, clearButton, quickButton, aboutMeButton, aboutButton, closeButton, spaceButton1, spaceButton2; + + //setup icons - File Menu + private final ImageIcon newIcon = new ImageIcon("icons/new.png"); + private final ImageIcon openIcon = new ImageIcon("icons/open.png"); + private final ImageIcon saveIcon = new ImageIcon("icons/save.png"); + private final ImageIcon closeIcon = new ImageIcon("icons/close.png"); + + //setup icons - Search Menu + private final ImageIcon clearIcon = new ImageIcon("icons/clear.png"); + + //setup icons - Search Menu + private final ImageIcon searchIcon = new ImageIcon("icons/search.png"); + + //setup icons - Help Menu + private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); + private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); + + public UI() { + container = getContentPane(); + + // Set the initial size of the window + setSize(700, 500); + + // Set the title of the window + setTitle("Undefined | " + SimpleJavaTextEditor.NAME); + + // Set the default close operation (exit when it gets closed) + setDefaultCloseOperation(EXIT_ON_CLOSE); + + // Set a default font for the TextArea + textArea = new JTextArea("", 0,0); + textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); + + // This is why we didn't have to worry about the size of the TextArea! + getContentPane().setLayout(new BorderLayout()); // the BorderLayout bit makes it fill it automatically + getContentPane().add(textArea); + + // Set the Menus + menuFile = new JMenu("File"); + menuEdit = new JMenu("Edit"); + menuFind = new JMenu("Search"); + menuAbout = new JMenu("About"); + + // Set the Items Menu + newFile = new JMenuItem("New", newIcon); + openFile = new JMenuItem("Open", openIcon); + saveFile = new JMenuItem("Save", saveIcon); + close = new JMenuItem("Close", closeIcon); + clearFile = new JMenuItem("Clear", clearIcon); + quickFind = new JMenuItem("Quick", searchIcon); + aboutMe = new JMenuItem("About Me", aboutMeIcon); + aboutSoftware = new JMenuItem("About Software", aboutIcon); + + // Set the Menu Bar into the our GUI + menuBar = new JMenuBar(); + menuBar.add(menuFile); + menuBar.add(menuEdit); + menuBar.add(menuFind); + menuBar.add(menuAbout); + + this.setJMenuBar(menuBar); + + // New File + newFile.addActionListener(this); // Adding an action listener (so we know when it's been clicked). + newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK)); // Set a keyboard shortcut + menuFile.add(newFile); // Adding the file menu + + // Open File + openFile.addActionListener(this); + openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); + menuFile.add(openFile); + + // Save File + saveFile.addActionListener(this); + saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); + menuFile.add(saveFile); + + // Close File + + /* + * Along with our "CTRL+F4" shortcut to close the window, we also have + * the default closer, as stated at the beginning of this tutorial. + * this means that we actually have TWO shortcuts to close: + * 1) the default close operation (example, Alt+F4 on Windows) + * 2) CTRL+F4, which we are about to define now: (this one will appear in the label). + */ + close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.CTRL_MASK)); + close.addActionListener(this); + menuFile.add(close); + + // Clear File (Code) + clearFile.addActionListener(this); + clearFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_MASK)); + menuEdit.add(clearFile); + + // Find Word + quickFind.addActionListener(this); + quickFind.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK)); + menuFind.add(quickFind); + + // About Me + aboutMe.addActionListener(this); + aboutMe.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)); + menuAbout.add(aboutMe); + + // About Software + aboutSoftware.addActionListener(this); + aboutSoftware.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); + menuAbout.add(aboutSoftware); + + mainToolbar = new JToolBar(); + this.add(mainToolbar, BorderLayout.NORTH); + //used to create space between button groups + Border emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 50); + + newButton = new JButton(newIcon); + newButton.setToolTipText("New"); + newButton.addActionListener(this); + mainToolbar.add(newButton); + mainToolbar.addSeparator(); + + openButton = new JButton(openIcon); + openButton.setToolTipText("Open"); + openButton.addActionListener(this); + mainToolbar.add(openButton); + mainToolbar.addSeparator(); + + saveButton = new JButton(saveIcon); + saveButton.setToolTipText("Save"); + saveButton.addActionListener(this); + mainToolbar.add(saveButton); + mainToolbar.addSeparator(); + + clearButton = new JButton(clearIcon); + clearButton.setToolTipText("Clear All"); + clearButton.addActionListener(this); + mainToolbar.add(clearButton); + mainToolbar.addSeparator(); + + quickButton = new JButton(searchIcon); + quickButton.setToolTipText("Quick Search"); + quickButton.addActionListener(this); + mainToolbar.add(quickButton); + + //create space between button groups + spaceButton1 = new JButton(); + spaceButton1.setBorder(emptyBorder); + mainToolbar.add(spaceButton1); + + aboutMeButton = new JButton(aboutMeIcon); + aboutMeButton.setToolTipText("About Me"); + aboutMeButton.addActionListener(this); + mainToolbar.add(aboutMeButton); + mainToolbar.addSeparator(); + + aboutButton = new JButton(aboutIcon); + aboutButton.setToolTipText("About NotePad PH"); + aboutButton.addActionListener(this); + mainToolbar.add(aboutButton); + + //create space between button groups + spaceButton2 = new JButton(); + spaceButton2.setBorder(emptyBorder); + mainToolbar.add(spaceButton2); + + closeButton = new JButton(closeIcon); + closeButton.setToolTipText("Close"); + closeButton.addActionListener(this); + mainToolbar.add(closeButton); + } + + public void actionPerformed (ActionEvent e) { + // If the source of the event was our "close" option + if(e.getSource() == close || e.getSource() == closeButton) + this.dispose(); // dispose all resources and close the application + + // If the source was the "new" file option + else if(e.getSource() == newFile || e.getSource() == newButton) { + FEdit.clear(textArea); + } + // If the source was the "open" option + else if(e.getSource() == openFile || e.getSource() == openButton) { + JFileChooser open = new JFileChooser(); // open up a file chooser (a dialog for the user to browse files to open) + int option = open.showOpenDialog(this); // get the option that the user selected (approve or cancel) + + /* + * NOTE: because we are OPENing a file, we call showOpenDialog~ + * if the user clicked OK, we have "APPROVE_OPTION" + * so we want to open the file + */ + if(option == JFileChooser.APPROVE_OPTION) { + FEdit.clear(textArea); // clear the TextArea before applying the file contents + try { + // create a scanner to read the file (getSelectedFile().getPath() will get the path to the file) + Scanner scan = new Scanner(new FileReader(open.getSelectedFile().getPath())); + while (scan.hasNext()) // while there's still something to read + textArea.append(scan.nextLine() + "\n"); // append the line to the TextArea + } catch (Exception ex) { // catch any exceptions, and... + // ...write to the debug console + System.out.println(ex.getMessage()); + } + } + } + // If the source of the event was the "save" option + else if(e.getSource() == saveFile || e.getSource() == saveButton) { + // Open a file chooser + JFileChooser fileChoose = new JFileChooser(); + // Open the file, only this time we call + int option = fileChoose.showSaveDialog(this); + + /* + * ShowSaveDialog instead of showOpenDialog + * if the user clicked OK (and not cancel) + */ + if(option == JFileChooser.APPROVE_OPTION) { + try { + File file = fileChoose.getSelectedFile(); + // Set the new title of the window + setTitle(file.getName() + " | " + SimpleJavaTextEditor.NAME); + // Create a buffered writer to write to a file + BufferedWriter out = new BufferedWriter(new FileWriter(file.getPath())); + // Write the contents of the TextArea to the file + out.write(textArea.getText()); + // Close the file stream + out.close(); + } catch (Exception ex) { // again, catch any exceptions and... + // ...write to the debug console + System.out.println(ex.getMessage()); + } + } + } + + // Clear File (Code) + if(e.getSource() == clearFile || e.getSource() == clearButton) { + FEdit.clear(textArea); + } + // Find + if(e.getSource() == quickFind || e.getSource() == quickButton) { + new Find(textArea); + } + + // About Me + else if(e.getSource() == aboutMe || e.getSource() == aboutMeButton) { + new About().me(); + } + // About Software + else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { + new About().software(); + } + + } + +} \ No newline at end of file From bd720b9b6c125c73922ce988ea47146e4b34f59b Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 8 Mar 2016 10:49:17 -0500 Subject: [PATCH 02/15] The Autocomplete Handler The beginnings of the autocomplete class. So far, I have a general layout of what I want to do and am entering some content. --- .../JavaAutocomplete.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/simplejavatexteditor/JavaAutocomplete.java diff --git a/src/simplejavatexteditor/JavaAutocomplete.java b/src/simplejavatexteditor/JavaAutocomplete.java new file mode 100644 index 0000000..ce1975d --- /dev/null +++ b/src/simplejavatexteditor/JavaAutocomplete.java @@ -0,0 +1,88 @@ +package simplejavatexteditor; + +import javax.swing.*; +import java.util.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.event.ActionEvent; +import javax.swing.text.BadLocationException; +import javax.swing.GroupLayout.*; +import simplejavatexteditor.UI; +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author patrickslagle + */ +public class JavaAutocomplete + implements DocumentListener { + + static final String keywords[] = {"abstract", "assert", "boolean", + "break", "byte", "case", "catch", "char", "class", "const", + "continue", "default", "do", "double", "else", "extends", "false", + "final", "finally", "float", "for", "goto", "if", "implements", + "import", "instanceof", "int", "interface", "long", "native", + "new", "null", "package", "private", "protected", "public", + "return", "short", "static", "strictfp", "super", "switch", + "synchronized", "this", "throw", "throws", "transient", "true", + "try", "void", "volatile", "while"}; + + private enum Mode { + + INSERT, COMPLETION + }; + private final Mode mode = Mode.INSERT; + private final String COMMIT_ACTION = "commit"; + UI ui; + + public JavaAutocomplete() { + } + + @Override + public void insertUpdate(DocumentEvent e) { + + int pos = e.getOffset(); + String content = null; + int start; + String prefix = ""; + int n; + + if (e.getLength() < 1) { + return; + } + + content = ui.getContent(0, pos + 1); + + for (start = pos; start >= 0; start--) { + if (!Character.isLetter(content.charAt(start))) { + break; + } + } + prefix = content.substring(start + 1); + + n = Collections.binarySearch(keywords, prefix); + } + + @Override + public void removeUpdate(DocumentEvent e) { + } + + @Override + public void changedUpdate(DocumentEvent e) { + } +} +/* +So, the way to perform autocomplete is: + +Get the position of the latest action through getOffset() +Get the text of the area thus far by a getContent() method +Get the last letter of the word the user typed by the Character.isLetter() and for loop. +Get the prefix by using substring with content and w +Store a binarySearch of prefix and keywords in and int +do a if statement to make sure the search results return a match and handle if not +Then, utilize 2 runnable classes to (1) insert the autocomplete and (2) set the cursor position of user and allow insert +*/ \ No newline at end of file From 1db0e94c9d19db6b94c4ff8d8764d7afcfd23662 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 11 Mar 2016 16:54:45 -0500 Subject: [PATCH 03/15] Autocomplete Rough Draft The code works great, but I want to clean it up. --- .../JavaAutocomplete.java | 324 +++++++++++++++--- 1 file changed, 276 insertions(+), 48 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutocomplete.java b/src/simplejavatexteditor/JavaAutocomplete.java index ce1975d..be9f737 100644 --- a/src/simplejavatexteditor/JavaAutocomplete.java +++ b/src/simplejavatexteditor/JavaAutocomplete.java @@ -1,72 +1,252 @@ package simplejavatexteditor; -import javax.swing.*; -import java.util.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.ArrayList; +import java.util.Collections; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JTextArea; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import java.awt.event.ActionEvent; import javax.swing.text.BadLocationException; -import javax.swing.GroupLayout.*; -import simplejavatexteditor.UI; -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -/** - * - * @author patrickslagle - */ + public class JavaAutocomplete implements DocumentListener { - static final String keywords[] = {"abstract", "assert", "boolean", + static final String[] keywords = {"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", - "import", "instanceof", "int", "interface", "long", "native", - "new", "null", "package", "private", "protected", "public", - "return", "short", "static", "strictfp", "super", "switch", + "import", "instanceof", "int", "System", "out", "print", "println", + "new", "null", "package", "private", "protected", "public", "interface", + "long", "native", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", - "try", "void", "volatile", "while"}; + "try", "void", "volatile", "while", "String"}; - private enum Mode { + static final String[] specialChars = {"{", "("}; + + //for getting the text area + UI ui; + + //we will need to put the array into an arraylist. + private ArrayList words = new ArrayList<>(); + private ArrayList chars = new ArrayList<>(); + //to keep track of whether we are showing + //an autocomplete to the user or not. + private enum Mode { INSERT, COMPLETION }; - private final Mode mode = Mode.INSERT; - private final String COMMIT_ACTION = "commit"; - UI ui; + + //Starting out in insert mode + private Mode mode = Mode.INSERT; + + //the text area object + private final JTextArea textArea; + + private static final String COMMIT_ACTION = "commit"; + + private boolean isKeyword; + + private int pos; + private String content; + + public JavaAutocomplete(UI ui) { + + //set the UI + this.ui = ui; + textArea = ui.getEditor(); - public JavaAutocomplete() { + + //enter key is pressed; fill in the keyword + InputMap im = textArea.getInputMap(); + ActionMap am = textArea.getActionMap(); + im.put(KeyStroke.getKeyStroke("ENTER "), COMMIT_ACTION); + am.put(COMMIT_ACTION, new CommitAction()); + + //set the keywords + for (String keyList : keywords) { + words.add(keyList); + } + for (String character : specialChars) { + chars.add(character); + } + Collections.sort(words, null); + Collections.sort(chars, null); } @Override public void insertUpdate(DocumentEvent e) { + //get the position of the last action + pos = e.getOffset(); + content = null; - int pos = e.getOffset(); - String content = null; + try { + //the text from start of typing to the end thus far + content = textArea.getText(0, pos + 1); + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + + //we need to check if the key pressed is either + //a special character or a keyword. + //we check for special characters first. + char c = content.charAt(pos); + String s = String.valueOf(c); + + //keeps us from getting errors as + //the text area contantly updates this method + if (e.getLength() != 1) { + return; + } + + //this loop begins at the last + //user event and ddecrements until it hits a + //non-letter, thus getting the index of the 1st + //letter of the word currently being typed int start; - String prefix = ""; - int n; - - if (e.getLength() < 1) { + for (start = pos; start >= 0; start--) { + + //if we hit a non-letter while decrementing, we come + //to the first letter in the word the user is typing. + //store that index in start variable. + if (!Character.isLetter(content.charAt(start))) { + break; + } + } + + if(chars.contains(s)) { + for (String str : chars) { + if (s.equals(str)) { + switch (str) { + case "{": + isKeyword = false; + SwingUtilities.invokeLater( + new CompletionTask("}", pos + 1)); + break; + case "(": + isKeyword = false; + SwingUtilities.invokeLater( + new CompletionTask(")", pos + 1)); + + break; + } + } + } + } + + //too short. make autocomplete start after 2 letters + //are typed + if (pos - start < 2) { return; } - content = ui.getContent(0, pos + 1); + //the content of the word that has been typed thus far + String prefix = content.substring(start + 1); - for (start = pos; start >= 0; start--) { - if (!Character.isLetter(content.charAt(start))) { - break; + //perform a binary search on the prefix and the word list. + int n = Collections.binarySearch(words, prefix); + + //find an absolute match on prefixes of the words. + if (n < 0 && -n < words.size()) { + isKeyword = true; + //the matching word + String match = words.get(-n - 1); + + //match the word containig prefix's contents to + //the beginning of the word. + if (match.startsWith(prefix)) { + + //perform a substring on the matching word to get + //the remainder of the word that the user is typing. + String completion = match.substring(pos - start); + + //then, perform the CompletionTask runnable on the word. + SwingUtilities.invokeLater( + new CompletionTask(completion, pos + 1)); + } else { + //nothing found. stay in insert mode. + mode = Mode.INSERT; } } - prefix = content.substring(start + 1); - - n = Collections.binarySearch(keywords, prefix); } + + private class CompletionTask + implements Runnable { + private final String completion; + private int position; + + public CompletionTask(String completion, int position) { + this.completion = completion; + this.position = position; + } + + public String getCompletion() { + return completion; + } + @Override + public void run() { + System.out.println(isKeyword); + //insert the remainder of the word after the user's + //last inserted text + textArea.insert(completion, position); + + if(isKeyword) { + //these two method calls draw the caret over the + //text completion and cause the text + //area to highlight the suggested completion + textArea.setCaretPosition(position + completion.length()); + textArea.moveCaretPosition(position); + + //enter completion mode. This + //affects the CommitAction class behavior + mode = Mode.COMPLETION; + } else { + textArea.setCaretPosition(position + completion.length()); + textArea.moveCaretPosition(position); + mode = Mode.COMPLETION; + textArea.addKeyListener(new HandleBracketEvent()); + + } + } + } + + private class CommitAction + extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + + //we are in completion mode at time of action + if (mode == Mode.COMPLETION) { + + //the end of the word + int pos = textArea.getSelectionEnd(); + + //handle if the character is a special character + if (isKeyword) { + + //it is a keyword + textArea.insert(" ", pos); + textArea.setCaretPosition(pos + 1); + mode = Mode.INSERT; + } else { + + textArea.setCaretPosition(pos); + mode = Mode.INSERT; + } + } else { + //default for pressing enter + textArea.replaceSelection("\n"); + } + } + } + @Override public void removeUpdate(DocumentEvent e) { } @@ -74,15 +254,63 @@ public void removeUpdate(DocumentEvent e) { @Override public void changedUpdate(DocumentEvent e) { } + + private class HandleBracketEvent + implements KeyListener { + + @Override + public void keyTyped(KeyEvent e) { + System.out.println("Activated"); + + switch(e.getKeyChar()) { + case '}': + textArea.replaceRange("", pos, pos); + mode = Mode.INSERT; + textArea.removeKeyListener(this); + + break; + case ')': + textArea.replaceRange("", pos, pos); + mode = Mode.INSERT; + textArea.removeKeyListener(this); + break; + case '\n': + textArea.setCaretPosition(pos); + textArea.replaceSelection("\n"); + mode = Mode.INSERT; + textArea.removeKeyListener(this); + break; + default: + textArea.setCaretPosition(pos); + mode = Mode.INSERT; + textArea.removeKeyListener(this); + break; + } + } + + + @Override + public void keyPressed(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + } } + /* -So, the way to perform autocomplete is: - -Get the position of the latest action through getOffset() -Get the text of the area thus far by a getContent() method -Get the last letter of the word the user typed by the Character.isLetter() and for loop. -Get the prefix by using substring with content and w -Store a binarySearch of prefix and keywords in and int -do a if statement to make sure the search results return a match and handle if not -Then, utilize 2 runnable classes to (1) insert the autocomplete and (2) set the cursor position of user and allow insert -*/ \ No newline at end of file +The completion is highlighted upon bracket click, +but when another button is clicked *except for* the completion itself, +fill the completion and the button within the brackets. + +We are at the place when the completion is highlighted. +We know when action is a char event. We know + +On type, I want to: + +Set the caret inside the brackets + +let user type +*/ From 79a68997648e724def24761b9df6da099b317bb5 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 11 Mar 2016 17:01:57 -0500 Subject: [PATCH 04/15] Rough Draft Without Comments Going to re-comment the code. --- .../JavaAutocomplete.java | 199 ++++++------------ 1 file changed, 70 insertions(+), 129 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutocomplete.java b/src/simplejavatexteditor/JavaAutocomplete.java index be9f737..dc48ee6 100644 --- a/src/simplejavatexteditor/JavaAutocomplete.java +++ b/src/simplejavatexteditor/JavaAutocomplete.java @@ -29,46 +29,38 @@ public class JavaAutocomplete "try", "void", "volatile", "while", "String"}; static final String[] specialChars = {"{", "("}; - - //for getting the text area + UI ui; - - //we will need to put the array into an arraylist. + private ArrayList words = new ArrayList<>(); private ArrayList chars = new ArrayList<>(); - //to keep track of whether we are showing - //an autocomplete to the user or not. private enum Mode { + INSERT, COMPLETION }; - - //Starting out in insert mode + private Mode mode = Mode.INSERT; - - //the text area object + private final JTextArea textArea; private static final String COMMIT_ACTION = "commit"; - + private boolean isKeyword; - + private int pos; private String content; - + public JavaAutocomplete(UI ui) { - - //set the UI + this.ui = ui; textArea = ui.getEditor(); - - //enter key is pressed; fill in the keyword InputMap im = textArea.getInputMap(); ActionMap am = textArea.getActionMap(); im.put(KeyStroke.getKeyStroke("ENTER "), COMMIT_ACTION); am.put(COMMIT_ACTION, new CommitAction()); - + //set the keywords for (String keyList : keywords) { words.add(keyList); @@ -82,100 +74,74 @@ public JavaAutocomplete(UI ui) { @Override public void insertUpdate(DocumentEvent e) { - //get the position of the last action pos = e.getOffset(); content = null; try { - //the text from start of typing to the end thus far content = textArea.getText(0, pos + 1); } catch (BadLocationException ex) { ex.printStackTrace(); } - - //we need to check if the key pressed is either - //a special character or a keyword. - //we check for special characters first. + char c = content.charAt(pos); String s = String.valueOf(c); - - //keeps us from getting errors as - //the text area contantly updates this method + if (e.getLength() != 1) { return; } - - //this loop begins at the last - //user event and ddecrements until it hits a - //non-letter, thus getting the index of the 1st - //letter of the word currently being typed + int start; for (start = pos; start >= 0; start--) { - - //if we hit a non-letter while decrementing, we come - //to the first letter in the word the user is typing. - //store that index in start variable. - if (!Character.isLetter(content.charAt(start))) { - break; - } + + if (!Character.isLetter(content.charAt(start))) { + break; + } } - - if(chars.contains(s)) { + + if (chars.contains(s)) { for (String str : chars) { - if (s.equals(str)) { - switch (str) { - case "{": - isKeyword = false; - SwingUtilities.invokeLater( - new CompletionTask("}", pos + 1)); - break; - case "(": - isKeyword = false; - SwingUtilities.invokeLater( - new CompletionTask(")", pos + 1)); - - break; - } - } + if (s.equals(str)) { + switch (str) { + case "{": + isKeyword = false; + SwingUtilities.invokeLater( + new CompletionTask("}", pos + 1)); + break; + case "(": + isKeyword = false; + SwingUtilities.invokeLater( + new CompletionTask(")", pos + 1)); + + break; } + } + } } - - //too short. make autocomplete start after 2 letters - //are typed + if (pos - start < 2) { return; } - //the content of the word that has been typed thus far String prefix = content.substring(start + 1); - //perform a binary search on the prefix and the word list. int n = Collections.binarySearch(words, prefix); - - //find an absolute match on prefixes of the words. + if (n < 0 && -n < words.size()) { isKeyword = true; - //the matching word String match = words.get(-n - 1); - - //match the word containig prefix's contents to - //the beginning of the word. + if (match.startsWith(prefix)) { - - //perform a substring on the matching word to get - //the remainder of the word that the user is typing. + String completion = match.substring(pos - start); - - //then, perform the CompletionTask runnable on the word. + SwingUtilities.invokeLater( new CompletionTask(completion, pos + 1)); - } else { - //nothing found. stay in insert mode. - mode = Mode.INSERT; + } else { + mode = Mode.INSERT; } } } - + private class CompletionTask implements Runnable { @@ -190,63 +156,54 @@ public CompletionTask(String completion, int position) { public String getCompletion() { return completion; } + @Override public void run() { System.out.println(isKeyword); - //insert the remainder of the word after the user's - //last inserted text + textArea.insert(completion, position); - - if(isKeyword) { - //these two method calls draw the caret over the - //text completion and cause the text - //area to highlight the suggested completion + + if (isKeyword) { + textArea.setCaretPosition(position + completion.length()); textArea.moveCaretPosition(position); - - //enter completion mode. This - //affects the CommitAction class behavior - mode = Mode.COMPLETION; + + mode = Mode.COMPLETION; } else { textArea.setCaretPosition(position + completion.length()); textArea.moveCaretPosition(position); mode = Mode.COMPLETION; textArea.addKeyListener(new HandleBracketEvent()); - } } } - + } + private class CommitAction extends AbstractAction { public void actionPerformed(ActionEvent e) { - - //we are in completion mode at time of action + if (mode == Mode.COMPLETION) { - - //the end of the word + int pos = textArea.getSelectionEnd(); - - //handle if the character is a special character - if (isKeyword) { - - //it is a keyword + + if (isKeyword) { + textArea.insert(" ", pos); textArea.setCaretPosition(pos + 1); mode = Mode.INSERT; - } else { - + } else { + textArea.setCaretPosition(pos); mode = Mode.INSERT; - } + } } else { - //default for pressing enter - textArea.replaceSelection("\n"); + textArea.replaceSelection("\n"); } } } - + @Override public void removeUpdate(DocumentEvent e) { } @@ -254,20 +211,20 @@ public void removeUpdate(DocumentEvent e) { @Override public void changedUpdate(DocumentEvent e) { } - - private class HandleBracketEvent - implements KeyListener { + + private class HandleBracketEvent + implements KeyListener { @Override public void keyTyped(KeyEvent e) { System.out.println("Activated"); - - switch(e.getKeyChar()) { - case '}': + + switch (e.getKeyChar()) { + case '}': textArea.replaceRange("", pos, pos); mode = Mode.INSERT; textArea.removeKeyListener(this); - + break; case ')': textArea.replaceRange("", pos, pos); @@ -285,9 +242,8 @@ public void keyTyped(KeyEvent e) { mode = Mode.INSERT; textArea.removeKeyListener(this); break; - } } - + } @Override public void keyPressed(KeyEvent e) { @@ -296,21 +252,6 @@ public void keyPressed(KeyEvent e) { @Override public void keyReleased(KeyEvent e) { } - + } } - -/* -The completion is highlighted upon bracket click, -but when another button is clicked *except for* the completion itself, -fill the completion and the button within the brackets. - -We are at the place when the completion is highlighted. -We know when action is a char event. We know - -On type, I want to: - -Set the caret inside the brackets - -let user type -*/ From dc67068836dfb2ad58d9cf656643dc271d45df7f Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 11 Mar 2016 22:22:47 -0500 Subject: [PATCH 05/15] Improvements/Documentaion Performed some documentation and code cleanup. --- .../JavaAutocomplete.java | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutocomplete.java b/src/simplejavatexteditor/JavaAutocomplete.java index dc48ee6..c282c47 100644 --- a/src/simplejavatexteditor/JavaAutocomplete.java +++ b/src/simplejavatexteditor/JavaAutocomplete.java @@ -15,6 +15,11 @@ import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; +/* +This class determines if the word +being typed matches the keywords that will be +suggested to the user. +*/ public class JavaAutocomplete implements DocumentListener { @@ -28,26 +33,22 @@ public class JavaAutocomplete "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while", "String"}; - static final String[] specialChars = {"{", "("}; + static final String[] bracketChars = {"{", "("}; UI ui; private ArrayList words = new ArrayList<>(); - private ArrayList chars = new ArrayList<>(); + private ArrayList brackets = new ArrayList<>(); private enum Mode { - INSERT, COMPLETION }; private Mode mode = Mode.INSERT; - private final JTextArea textArea; - private static final String COMMIT_ACTION = "commit"; - + private boolean isKeyword; - private int pos; private String content; @@ -55,21 +56,20 @@ public JavaAutocomplete(UI ui) { this.ui = ui; textArea = ui.getEditor(); - + InputMap im = textArea.getInputMap(); ActionMap am = textArea.getActionMap(); im.put(KeyStroke.getKeyStroke("ENTER "), COMMIT_ACTION); am.put(COMMIT_ACTION, new CommitAction()); - //set the keywords for (String keyList : keywords) { words.add(keyList); } - for (String character : specialChars) { - chars.add(character); + for (String bracket : bracketChars) { + brackets.add(bracket); } Collections.sort(words, null); - Collections.sort(chars, null); + Collections.sort(brackets, null); } @Override @@ -98,8 +98,8 @@ public void insertUpdate(DocumentEvent e) { } } - if (chars.contains(s)) { - for (String str : chars) { + if (brackets.contains(s)) { + for (String str : brackets) { if (s.equals(str)) { switch (str) { case "{": @@ -123,7 +123,6 @@ public void insertUpdate(DocumentEvent e) { } String prefix = content.substring(start + 1); - int n = Collections.binarySearch(words, prefix); if (n < 0 && -n < words.size()) { @@ -142,6 +141,11 @@ public void insertUpdate(DocumentEvent e) { } } + /* + This class handles the autocomplete + suggestion generated when the user + is typing a word that matches a keyword. + */ private class CompletionTask implements Runnable { @@ -159,7 +163,6 @@ public String getCompletion() { @Override public void run() { - System.out.println(isKeyword); textArea.insert(completion, position); @@ -178,7 +181,11 @@ public void run() { } } } - + + /* + Handle when the enter button is pressed, + particularly when it is in response to a keyword. + */ private class CommitAction extends AbstractAction { @@ -204,20 +211,15 @@ public void actionPerformed(ActionEvent e) { } } - @Override - public void removeUpdate(DocumentEvent e) { - } - - @Override - public void changedUpdate(DocumentEvent e) { - } - + /* + User responses to autocomplete for brackets + or parentheses will need extra attention. + */ private class HandleBracketEvent implements KeyListener { @Override public void keyTyped(KeyEvent e) { - System.out.println("Activated"); switch (e.getKeyChar()) { case '}': @@ -246,12 +248,15 @@ public void keyTyped(KeyEvent e) { } @Override - public void keyPressed(KeyEvent e) { - } + public void keyPressed(KeyEvent e) {} @Override - public void keyReleased(KeyEvent e) { - } + public void keyReleased(KeyEvent e) {} + } + @Override + public void removeUpdate(DocumentEvent e) {} + + @Override + public void changedUpdate(DocumentEvent e) {} - } } From 5d3bfd361bb5c1e276ea5db3fddf0b316fd42b18 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Sat, 12 Mar 2016 18:33:39 -0500 Subject: [PATCH 06/15] Auto Complete Rough Draft --- ...utocomplete.java => JavaAutoComplete.java} | 220 ++++++++++-------- src/simplejavatexteditor/UI.java | 26 ++- 2 files changed, 141 insertions(+), 105 deletions(-) rename src/simplejavatexteditor/{JavaAutocomplete.java => JavaAutoComplete.java} (55%) diff --git a/src/simplejavatexteditor/JavaAutocomplete.java b/src/simplejavatexteditor/JavaAutoComplete.java similarity index 55% rename from src/simplejavatexteditor/JavaAutocomplete.java rename to src/simplejavatexteditor/JavaAutoComplete.java index c282c47..c4da235 100644 --- a/src/simplejavatexteditor/JavaAutocomplete.java +++ b/src/simplejavatexteditor/JavaAutoComplete.java @@ -15,61 +15,85 @@ import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; -/* -This class determines if the word -being typed matches the keywords that will be -suggested to the user. -*/ -public class JavaAutocomplete +/** + *

Auto complete functionality for java keywords, brackets and + * parentheses

+ * + *

+ * An ArrayList is created for the keywords and the brackets. If the word + * currently being typed matches a word in the list, a Runnable inner class is + * implemented to handle the word completion. + * + * Two other inner classes are also used. The second one handles when the enter + * key is pressed in response to an auto complete suggestion. The third one + * performs additional logic on brackets. + *

+ * + * + * @author Patrick Slagle + * @since 2016-12-03 + */ +public class JavaAutoComplete implements DocumentListener { - static final String[] keywords = {"abstract", "assert", "boolean", + private static String[] keywords = {"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", - "import", "instanceof", "int", "System", "out", "print", "println", + "import", "instanceof", "int", "System", "out", "print()", "println()", "new", "null", "package", "private", "protected", "public", "interface", "long", "native", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while", "String"}; - static final String[] bracketChars = {"{", "("}; - + private static String[] bracketChars = {"{", "("}; + private static String[] bCompletions = {"}", ")"}; UI ui; private ArrayList words = new ArrayList<>(); private ArrayList brackets = new ArrayList<>(); + private ArrayList bracketCompletions = new ArrayList<>(); + //Signal if we are in completion mode or not private enum Mode { + INSERT, COMPLETION }; private Mode mode = Mode.INSERT; private final JTextArea textArea; private static final String COMMIT_ACTION = "commit"; - + + //To determine if the the type + //of autocomplete is a keyword or bracket private boolean isKeyword; + //index of the last action private int pos; + //The text entered so far private String content; - public JavaAutocomplete(UI ui) { - + public JavaAutoComplete(UI ui) { + //Access the editor this.ui = ui; textArea = ui.getEditor(); - + + //Set the handler for the enter key InputMap im = textArea.getInputMap(); ActionMap am = textArea.getActionMap(); im.put(KeyStroke.getKeyStroke("ENTER "), COMMIT_ACTION); am.put(COMMIT_ACTION, new CommitAction()); + //Set up the keywords for (String keyList : keywords) { words.add(keyList); } for (String bracket : bracketChars) { brackets.add(bracket); } + for (String comp : bCompletions) { + bracketCompletions.add(comp); + } Collections.sort(words, null); - Collections.sort(brackets, null); } @Override @@ -83,56 +107,38 @@ public void insertUpdate(DocumentEvent e) { ex.printStackTrace(); } - char c = content.charAt(pos); - String s = String.valueOf(c); - if (e.getLength() != 1) { return; } + //Before checking for a keyword + checkForBracket(); + + //Get the beginning of the word being typed int start; for (start = pos; start >= 0; start--) { - if (!Character.isLetter(content.charAt(start))) { break; } } - if (brackets.contains(s)) { - for (String str : brackets) { - if (s.equals(str)) { - switch (str) { - case "{": - isKeyword = false; - SwingUtilities.invokeLater( - new CompletionTask("}", pos + 1)); - break; - case "(": - isKeyword = false; - SwingUtilities.invokeLater( - new CompletionTask(")", pos + 1)); - - break; - } - } - } - } - + //Auto complete will start + //after two characters are typed if (pos - start < 2) { return; } + //Search for a match on the word being typed + //in the keywords ArrayList String prefix = content.substring(start + 1); int n = Collections.binarySearch(words, prefix); if (n < 0 && -n < words.size()) { - isKeyword = true; String match = words.get(-n - 1); if (match.startsWith(prefix)) { - String completion = match.substring(pos - start); - + isKeyword = true; SwingUtilities.invokeLater( new CompletionTask(completion, pos + 1)); } else { @@ -141,68 +147,88 @@ public void insertUpdate(DocumentEvent e) { } } + /** + * Performs a check to see if the last key typed was one of the supported + * bracket characters + */ + private void checkForBracket() { + //String of the last typed character + char c = content.charAt(pos); + String s = String.valueOf(c); + + for (int i = 0; i < brackets.size(); i++) { + if (brackets.get(i).equals(s)) { + isKeyword = false; + SwingUtilities.invokeLater( + new CompletionTask(bracketCompletions.get(i), pos + 1)); + } + } + } + + /** + * So that future classes can view the keyword list in the future. + * + * @return the keywords + */ + protected ArrayList getKeywords() { + return words; + } + + /** + * So that these keywords can be modified or added to in the future. + * + * @param keyword the keyword to set + */ + protected void setKeywords(String keyword) { + words.add(keyword); + } + /* - This class handles the autocomplete - suggestion generated when the user - is typing a word that matches a keyword. - */ + * Handles the auto complete suggestion generated when the user is typing a + * word that matches a keyword. + */ private class CompletionTask implements Runnable { private final String completion; - private int position; + private final int position; public CompletionTask(String completion, int position) { this.completion = completion; this.position = position; } - public String getCompletion() { - return completion; - } - @Override public void run() { - textArea.insert(completion, position); - if (isKeyword) { - - textArea.setCaretPosition(position + completion.length()); - textArea.moveCaretPosition(position); - - mode = Mode.COMPLETION; - } else { - textArea.setCaretPosition(position + completion.length()); - textArea.moveCaretPosition(position); - mode = Mode.COMPLETION; + textArea.setCaretPosition(position + completion.length()); + textArea.moveCaretPosition(position); + mode = Mode.COMPLETION; + if (!isKeyword) { textArea.addKeyListener(new HandleBracketEvent()); - } } } - - /* - Handle when the enter button is pressed, - particularly when it is in response to a keyword. - */ + + /** + * Enter key is pressed in response to an auto complete suggestion. Respond + * appropriately. + */ private class CommitAction extends AbstractAction { + @Override public void actionPerformed(ActionEvent e) { if (mode == Mode.COMPLETION) { - int pos = textArea.getSelectionEnd(); if (isKeyword) { - textArea.insert(" ", pos); textArea.setCaretPosition(pos + 1); mode = Mode.INSERT; } else { - - textArea.setCaretPosition(pos); mode = Mode.INSERT; } } else { @@ -211,31 +237,32 @@ public void actionPerformed(ActionEvent e) { } } - /* - User responses to autocomplete for brackets - or parentheses will need extra attention. - */ + /** + * Additional logic for bracket auto complete + * + */ private class HandleBracketEvent implements KeyListener { @Override public void keyTyped(KeyEvent e) { - - switch (e.getKeyChar()) { - case '}': - textArea.replaceRange("", pos, pos); + //Bracket auto complete needs special attention. + //Multiple possible responses are needed. + String keyEvent = String.valueOf(e.getKeyChar()); + for (int i = 0; i < bracketCompletions.size(); i++) { + System.out.println(bracketCompletions.get(i)); + if (keyEvent.equals(bracketCompletions.get(i))) { + System.out.println("Activated"); + textArea.replaceRange("", pos, pos + 1); mode = Mode.INSERT; textArea.removeKeyListener(this); - - break; - case ')': - textArea.replaceRange("", pos, pos); - mode = Mode.INSERT; - textArea.removeKeyListener(this); - break; + } + } + int currentPosition = textArea.getCaretPosition(); + switch (e.getKeyChar()) { case '\n': - textArea.setCaretPosition(pos); - textArea.replaceSelection("\n"); + textArea.insert("\n\n", currentPosition); + textArea.setCaretPosition(currentPosition + 1); mode = Mode.INSERT; textArea.removeKeyListener(this); break; @@ -248,15 +275,20 @@ public void keyTyped(KeyEvent e) { } @Override - public void keyPressed(KeyEvent e) {} + public void keyPressed(KeyEvent e) { + } @Override - public void keyReleased(KeyEvent e) {} - } + public void keyReleased(KeyEvent e) { + } + } + @Override - public void removeUpdate(DocumentEvent e) {} + public void removeUpdate(DocumentEvent e) { + } @Override - public void changedUpdate(DocumentEvent e) {} + public void changedUpdate(DocumentEvent e) { + } } diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index aef9ad1..3f7bb07 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -29,7 +29,6 @@ // Various import java.util.Scanner; import javax.swing.border.Border; -import javax.swing.text.BadLocationException; public class UI extends JFrame implements ActionListener { @@ -58,6 +57,9 @@ public class UI extends JFrame implements ActionListener { private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); + //setup Autocomplete for Java keywords + private final JavaAutoComplete autocomplete; + public UI() { container = getContentPane(); @@ -73,6 +75,8 @@ public UI() { // Set a default font for the TextArea textArea = new JTextArea("", 0,0); textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); + textArea.setTabSize(2); + // This is why we didn't have to worry about the size of the TextArea! getContentPane().setLayout(new BorderLayout()); // the BorderLayout bit makes it fill it automatically @@ -210,7 +214,16 @@ public UI() { closeButton.setToolTipText("Close"); closeButton.addActionListener(this); mainToolbar.add(closeButton); + + //auto complete startup + autocomplete = new JavaAutoComplete(this); + textArea.getDocument().addDocumentListener(autocomplete); } + + //make the TextArea available to the autocomplete handler + protected JTextArea getEditor() { + return textArea; + } public void actionPerformed (ActionEvent e) { // If the source of the event was our "close" option @@ -291,14 +304,5 @@ else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { new About().software(); } - } - protected String getContent(int i, int j) { - String content = ""; - try { - content = textArea.getText(i, j); - } catch(BadLocationException e) { - e.printStackTrace(); - } - return content; - } + } } \ No newline at end of file From 7a2a5e9b6bc9b8ed4d8c97744c09d42f63db13e0 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Sat, 12 Mar 2016 19:08:22 -0500 Subject: [PATCH 07/15] Final Draft --- .../JavaAutoComplete.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutoComplete.java b/src/simplejavatexteditor/JavaAutoComplete.java index c4da235..1e91549 100644 --- a/src/simplejavatexteditor/JavaAutoComplete.java +++ b/src/simplejavatexteditor/JavaAutoComplete.java @@ -48,28 +48,23 @@ public class JavaAutoComplete private static String[] bracketChars = {"{", "("}; private static String[] bCompletions = {"}", ")"}; - UI ui; - private ArrayList words = new ArrayList<>(); private ArrayList brackets = new ArrayList<>(); private ArrayList bracketCompletions = new ArrayList<>(); - //Signal if we are in completion mode or not + //Keep track of when code completion + //has been activated private enum Mode { INSERT, COMPLETION }; + private final UI ui; private Mode mode = Mode.INSERT; private final JTextArea textArea; private static final String COMMIT_ACTION = "commit"; - - //To determine if the the type - //of autocomplete is a keyword or bracket private boolean isKeyword; - //index of the last action private int pos; - //The text entered so far private String content; public JavaAutoComplete(UI ui) { @@ -148,7 +143,8 @@ public void insertUpdate(DocumentEvent e) { } /** - * Performs a check to see if the last key typed was one of the supported + * Performs a check to see if the last + * key typed was one of the supported * bracket characters */ private void checkForBracket() { @@ -170,7 +166,7 @@ private void checkForBracket() { * * @return the keywords */ - protected ArrayList getKeywords() { + private ArrayList getKeywords() { return words; } @@ -179,12 +175,13 @@ protected ArrayList getKeywords() { * * @param keyword the keyword to set */ - protected void setKeywords(String keyword) { + private void setKeywords(String keyword) { words.add(keyword); } - /* - * Handles the auto complete suggestion generated when the user is typing a + /** + * Handles the auto complete suggestion + * generated when the user is typing a * word that matches a keyword. */ private class CompletionTask @@ -239,7 +236,6 @@ public void actionPerformed(ActionEvent e) { /** * Additional logic for bracket auto complete - * */ private class HandleBracketEvent implements KeyListener { @@ -249,10 +245,8 @@ public void keyTyped(KeyEvent e) { //Bracket auto complete needs special attention. //Multiple possible responses are needed. String keyEvent = String.valueOf(e.getKeyChar()); - for (int i = 0; i < bracketCompletions.size(); i++) { - System.out.println(bracketCompletions.get(i)); - if (keyEvent.equals(bracketCompletions.get(i))) { - System.out.println("Activated"); + for (String bracketCompletion : bracketCompletions) { + if (keyEvent.equals(bracketCompletion)) { textArea.replaceRange("", pos, pos + 1); mode = Mode.INSERT; textArea.removeKeyListener(this); From c838c3a50c0643f93ae4e29df3cb2b91697b763f Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Sun, 13 Mar 2016 03:28:45 -0400 Subject: [PATCH 08/15] Clean up Unnecessary Else Statement Removed unnecessary else statement from inner class CommitAction. --- src/simplejavatexteditor/JavaAutoComplete.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutoComplete.java b/src/simplejavatexteditor/JavaAutoComplete.java index 1e91549..c03b586 100644 --- a/src/simplejavatexteditor/JavaAutoComplete.java +++ b/src/simplejavatexteditor/JavaAutoComplete.java @@ -225,10 +225,9 @@ public void actionPerformed(ActionEvent e) { textArea.insert(" ", pos); textArea.setCaretPosition(pos + 1); mode = Mode.INSERT; - } else { - mode = Mode.INSERT; } } else { + mode = Mode.INSERT; textArea.replaceSelection("\n"); } } From 68e33318233527da2b5544ca8a854d3ea506887d Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 15 Mar 2016 20:09:04 -0400 Subject: [PATCH 09/15] Java code completion activated only on ".java" files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users won’t be bothered with java keywords if they are not editing a java file. --- src/simplejavatexteditor/UI.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index 3f7bb07..d55b154 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -57,9 +57,6 @@ public class UI extends JFrame implements ActionListener { private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); - //setup Autocomplete for Java keywords - private final JavaAutoComplete autocomplete; - public UI() { container = getContentPane(); @@ -214,10 +211,6 @@ public UI() { closeButton.setToolTipText("Close"); closeButton.addActionListener(this); mainToolbar.add(closeButton); - - //auto complete startup - autocomplete = new JavaAutoComplete(this); - textArea.getDocument().addDocumentListener(autocomplete); } //make the TextArea available to the autocomplete handler @@ -279,6 +272,13 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { out.write(textArea.getText()); // Close the file stream out.close(); + + if(file.getName().endsWith(".java")) { + //setup Autocomplete for Java keywords + JavaAutoComplete autocomplete = new JavaAutoComplete(this); + textArea.getDocument().addDocumentListener(autocomplete); + } + } catch (Exception ex) { // again, catch any exceptions and... // ...write to the debug console System.out.println(ex.getMessage()); From 2a5d78c4ae5d06fae42ffc90fa061062c38451cf Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 18 Mar 2016 19:02:43 -0400 Subject: [PATCH 10/15] Fixed Indent Problem --- src/simplejavatexteditor/UI.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index d55b154..7b259db 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -273,11 +273,11 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { // Close the file stream out.close(); - if(file.getName().endsWith(".java")) { - //setup Autocomplete for Java keywords - JavaAutoComplete autocomplete = new JavaAutoComplete(this); - textArea.getDocument().addDocumentListener(autocomplete); - } + if(file.getName().endsWith(".java")) { + //setup Autocomplete for Java keywords + JavaAutoComplete autocomplete = new JavaAutoComplete(this); + textArea.getDocument().addDocumentListener(autocomplete); + } } catch (Exception ex) { // again, catch any exceptions and... // ...write to the debug console @@ -305,4 +305,4 @@ else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { } } -} \ No newline at end of file +} From cce658a53143dec1d3cef3a6764ccab66ab59d0e Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 18 Mar 2016 19:17:17 -0400 Subject: [PATCH 11/15] Deleting Duplicate File --- src/simplejavatexteditor/UI.java~ | 295 ------------------------------ 1 file changed, 295 deletions(-) delete mode 100644 src/simplejavatexteditor/UI.java~ diff --git a/src/simplejavatexteditor/UI.java~ b/src/simplejavatexteditor/UI.java~ deleted file mode 100644 index 053932e..0000000 --- a/src/simplejavatexteditor/UI.java~ +++ /dev/null @@ -1,295 +0,0 @@ -/** - * @name Simple Java NotePad - * @package ph.notepad - * @file UI.java - * @author SORIA Pierre-Henry - * @email pierrehs@hotmail.com - * @link http://github.com/pH-7 - * @copyright Copyright Pierre-Henry SORIA, All Rights Reserved. - * @license Apache (http://www.apache.org/licenses/LICENSE-2.0) - * @create 2012-05-04 - * @update 2015-09-4 - * - * - * @modifiedby Achintha Gunasekara - * @modweb http://www.achinthagunasekara.com - * @modemail contact@achinthagunasekara.com - */ - -package simplejavatexteditor; - -// GUI -import javax.swing.*; -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Font; -import java.awt.event.*; -// Input Stream -import java.io.*; -// Various -import java.util.Scanner; -import javax.swing.border.Border; - -public class UI extends JFrame implements ActionListener { - - private static final long serialVersionUID = 1L; - private final Container container; - private final JTextArea textArea; - private final JMenuBar menuBar; - private final JMenu menuFile, menuEdit, menuFind, menuAbout; - private final JMenuItem newFile, openFile, saveFile, close, clearFile, quickFind, aboutMe, aboutSoftware; - private final JToolBar mainToolbar; - JButton newButton, openButton, saveButton, clearButton, quickButton, aboutMeButton, aboutButton, closeButton, spaceButton1, spaceButton2; - - //setup icons - File Menu - private final ImageIcon newIcon = new ImageIcon("icons/new.png"); - private final ImageIcon openIcon = new ImageIcon("icons/open.png"); - private final ImageIcon saveIcon = new ImageIcon("icons/save.png"); - private final ImageIcon closeIcon = new ImageIcon("icons/close.png"); - - //setup icons - Search Menu - private final ImageIcon clearIcon = new ImageIcon("icons/clear.png"); - - //setup icons - Search Menu - private final ImageIcon searchIcon = new ImageIcon("icons/search.png"); - - //setup icons - Help Menu - private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); - private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); - - public UI() { - container = getContentPane(); - - // Set the initial size of the window - setSize(700, 500); - - // Set the title of the window - setTitle("Undefined | " + SimpleJavaTextEditor.NAME); - - // Set the default close operation (exit when it gets closed) - setDefaultCloseOperation(EXIT_ON_CLOSE); - - // Set a default font for the TextArea - textArea = new JTextArea("", 0,0); - textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); - - // This is why we didn't have to worry about the size of the TextArea! - getContentPane().setLayout(new BorderLayout()); // the BorderLayout bit makes it fill it automatically - getContentPane().add(textArea); - - // Set the Menus - menuFile = new JMenu("File"); - menuEdit = new JMenu("Edit"); - menuFind = new JMenu("Search"); - menuAbout = new JMenu("About"); - - // Set the Items Menu - newFile = new JMenuItem("New", newIcon); - openFile = new JMenuItem("Open", openIcon); - saveFile = new JMenuItem("Save", saveIcon); - close = new JMenuItem("Close", closeIcon); - clearFile = new JMenuItem("Clear", clearIcon); - quickFind = new JMenuItem("Quick", searchIcon); - aboutMe = new JMenuItem("About Me", aboutMeIcon); - aboutSoftware = new JMenuItem("About Software", aboutIcon); - - // Set the Menu Bar into the our GUI - menuBar = new JMenuBar(); - menuBar.add(menuFile); - menuBar.add(menuEdit); - menuBar.add(menuFind); - menuBar.add(menuAbout); - - this.setJMenuBar(menuBar); - - // New File - newFile.addActionListener(this); // Adding an action listener (so we know when it's been clicked). - newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK)); // Set a keyboard shortcut - menuFile.add(newFile); // Adding the file menu - - // Open File - openFile.addActionListener(this); - openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); - menuFile.add(openFile); - - // Save File - saveFile.addActionListener(this); - saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); - menuFile.add(saveFile); - - // Close File - - /* - * Along with our "CTRL+F4" shortcut to close the window, we also have - * the default closer, as stated at the beginning of this tutorial. - * this means that we actually have TWO shortcuts to close: - * 1) the default close operation (example, Alt+F4 on Windows) - * 2) CTRL+F4, which we are about to define now: (this one will appear in the label). - */ - close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.CTRL_MASK)); - close.addActionListener(this); - menuFile.add(close); - - // Clear File (Code) - clearFile.addActionListener(this); - clearFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_MASK)); - menuEdit.add(clearFile); - - // Find Word - quickFind.addActionListener(this); - quickFind.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK)); - menuFind.add(quickFind); - - // About Me - aboutMe.addActionListener(this); - aboutMe.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)); - menuAbout.add(aboutMe); - - // About Software - aboutSoftware.addActionListener(this); - aboutSoftware.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); - menuAbout.add(aboutSoftware); - - mainToolbar = new JToolBar(); - this.add(mainToolbar, BorderLayout.NORTH); - //used to create space between button groups - Border emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 50); - - newButton = new JButton(newIcon); - newButton.setToolTipText("New"); - newButton.addActionListener(this); - mainToolbar.add(newButton); - mainToolbar.addSeparator(); - - openButton = new JButton(openIcon); - openButton.setToolTipText("Open"); - openButton.addActionListener(this); - mainToolbar.add(openButton); - mainToolbar.addSeparator(); - - saveButton = new JButton(saveIcon); - saveButton.setToolTipText("Save"); - saveButton.addActionListener(this); - mainToolbar.add(saveButton); - mainToolbar.addSeparator(); - - clearButton = new JButton(clearIcon); - clearButton.setToolTipText("Clear All"); - clearButton.addActionListener(this); - mainToolbar.add(clearButton); - mainToolbar.addSeparator(); - - quickButton = new JButton(searchIcon); - quickButton.setToolTipText("Quick Search"); - quickButton.addActionListener(this); - mainToolbar.add(quickButton); - - //create space between button groups - spaceButton1 = new JButton(); - spaceButton1.setBorder(emptyBorder); - mainToolbar.add(spaceButton1); - - aboutMeButton = new JButton(aboutMeIcon); - aboutMeButton.setToolTipText("About Me"); - aboutMeButton.addActionListener(this); - mainToolbar.add(aboutMeButton); - mainToolbar.addSeparator(); - - aboutButton = new JButton(aboutIcon); - aboutButton.setToolTipText("About NotePad PH"); - aboutButton.addActionListener(this); - mainToolbar.add(aboutButton); - - //create space between button groups - spaceButton2 = new JButton(); - spaceButton2.setBorder(emptyBorder); - mainToolbar.add(spaceButton2); - - closeButton = new JButton(closeIcon); - closeButton.setToolTipText("Close"); - closeButton.addActionListener(this); - mainToolbar.add(closeButton); - } - - public void actionPerformed (ActionEvent e) { - // If the source of the event was our "close" option - if(e.getSource() == close || e.getSource() == closeButton) - this.dispose(); // dispose all resources and close the application - - // If the source was the "new" file option - else if(e.getSource() == newFile || e.getSource() == newButton) { - FEdit.clear(textArea); - } - // If the source was the "open" option - else if(e.getSource() == openFile || e.getSource() == openButton) { - JFileChooser open = new JFileChooser(); // open up a file chooser (a dialog for the user to browse files to open) - int option = open.showOpenDialog(this); // get the option that the user selected (approve or cancel) - - /* - * NOTE: because we are OPENing a file, we call showOpenDialog~ - * if the user clicked OK, we have "APPROVE_OPTION" - * so we want to open the file - */ - if(option == JFileChooser.APPROVE_OPTION) { - FEdit.clear(textArea); // clear the TextArea before applying the file contents - try { - // create a scanner to read the file (getSelectedFile().getPath() will get the path to the file) - Scanner scan = new Scanner(new FileReader(open.getSelectedFile().getPath())); - while (scan.hasNext()) // while there's still something to read - textArea.append(scan.nextLine() + "\n"); // append the line to the TextArea - } catch (Exception ex) { // catch any exceptions, and... - // ...write to the debug console - System.out.println(ex.getMessage()); - } - } - } - // If the source of the event was the "save" option - else if(e.getSource() == saveFile || e.getSource() == saveButton) { - // Open a file chooser - JFileChooser fileChoose = new JFileChooser(); - // Open the file, only this time we call - int option = fileChoose.showSaveDialog(this); - - /* - * ShowSaveDialog instead of showOpenDialog - * if the user clicked OK (and not cancel) - */ - if(option == JFileChooser.APPROVE_OPTION) { - try { - File file = fileChoose.getSelectedFile(); - // Set the new title of the window - setTitle(file.getName() + " | " + SimpleJavaTextEditor.NAME); - // Create a buffered writer to write to a file - BufferedWriter out = new BufferedWriter(new FileWriter(file.getPath())); - // Write the contents of the TextArea to the file - out.write(textArea.getText()); - // Close the file stream - out.close(); - } catch (Exception ex) { // again, catch any exceptions and... - // ...write to the debug console - System.out.println(ex.getMessage()); - } - } - } - - // Clear File (Code) - if(e.getSource() == clearFile || e.getSource() == clearButton) { - FEdit.clear(textArea); - } - // Find - if(e.getSource() == quickFind || e.getSource() == quickButton) { - new Find(textArea); - } - - // About Me - else if(e.getSource() == aboutMe || e.getSource() == aboutMeButton) { - new About().me(); - } - // About Software - else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { - new About().software(); - } - - } - -} \ No newline at end of file From 25aa5b2ab106b6844f7ee2dc6968d9ec83c4e27a Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Fri, 18 Mar 2016 19:18:34 -0400 Subject: [PATCH 12/15] Update UI.java --- src/simplejavatexteditor/UI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index 7b259db..42bf9b0 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -72,7 +72,7 @@ public UI() { // Set a default font for the TextArea textArea = new JTextArea("", 0,0); textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); - textArea.setTabSize(2); + textArea.setTabSize(2); // This is why we didn't have to worry about the size of the TextArea! From 6a1ed7825e06634c93475cbfab4619f54cb02021 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 22 Mar 2016 20:16:17 -0400 Subject: [PATCH 13/15] Code Completion Improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I want to make the editor supportive of multiple languages. Putting the keywords in a separate class and going to add more languages. Code to handle the different languages added to UI.java. I’m not finished yet, need to do some clean up/documenting. This works though. --- .../JavaAutoComplete.java | 53 +++--- .../SupportedKeywords.java | 54 ++++++ src/simplejavatexteditor/UI.java | 159 ++++++++++++------ 3 files changed, 184 insertions(+), 82 deletions(-) create mode 100644 src/simplejavatexteditor/SupportedKeywords.java diff --git a/src/simplejavatexteditor/JavaAutoComplete.java b/src/simplejavatexteditor/JavaAutoComplete.java index c03b586..40da064 100644 --- a/src/simplejavatexteditor/JavaAutoComplete.java +++ b/src/simplejavatexteditor/JavaAutoComplete.java @@ -36,22 +36,12 @@ public class JavaAutoComplete implements DocumentListener { - private static String[] keywords = {"abstract", "assert", "boolean", - "break", "byte", "case", "catch", "char", "class", "const", - "continue", "default", "do", "double", "else", "extends", "false", - "final", "finally", "float", "for", "goto", "if", "implements", - "import", "instanceof", "int", "System", "out", "print()", "println()", - "new", "null", "package", "private", "protected", "public", "interface", - "long", "native", "return", "short", "static", "strictfp", "super", "switch", - "synchronized", "this", "throw", "throws", "transient", "true", - "try", "void", "volatile", "while", "String"}; - - private static String[] bracketChars = {"{", "("}; - private static String[] bCompletions = {"}", ")"}; - private ArrayList words = new ArrayList<>(); private ArrayList brackets = new ArrayList<>(); private ArrayList bracketCompletions = new ArrayList<>(); + private ArrayList words = new ArrayList<>(); + + SupportedKeywords kw; //Keep track of when code completion //has been activated private enum Mode { @@ -68,6 +58,16 @@ private enum Mode { private String content; public JavaAutoComplete(UI ui) { + this.ui = ui; + textArea = ui.getEditor(); + } + + public JavaAutoComplete(UI ui, ArrayList al) { + words = al; + kw = new SupportedKeywords(); + brackets = kw.getbrackets(); + bracketCompletions = kw.getbracketCompletions(); + //Access the editor this.ui = ui; textArea = ui.getEditor(); @@ -78,19 +78,16 @@ public JavaAutoComplete(UI ui) { im.put(KeyStroke.getKeyStroke("ENTER "), COMMIT_ACTION); am.put(COMMIT_ACTION, new CommitAction()); - //Set up the keywords - for (String keyList : keywords) { - words.add(keyList); - } - for (String bracket : bracketChars) { - brackets.add(bracket); - } - for (String comp : bCompletions) { - bracketCompletions.add(comp); - } - Collections.sort(words, null); + Collections.sort(words); } + /** + * A character has been typed into the document. + * This method performs the primary + * check to find a keyword completion. + * + * @param e + */ @Override public void insertUpdate(DocumentEvent e) { pos = e.getOffset(); @@ -209,7 +206,8 @@ public void run() { } /** - * Enter key is pressed in response to an auto complete suggestion. Respond + * Enter key is pressed in response to an + * auto complete suggestion. Respond * appropriately. */ private class CommitAction @@ -284,4 +282,7 @@ public void removeUpdate(DocumentEvent e) { public void changedUpdate(DocumentEvent e) { } -} + public void removeListener() { + textArea.getDocument().removeDocumentListener(this); + } +} \ No newline at end of file diff --git a/src/simplejavatexteditor/SupportedKeywords.java b/src/simplejavatexteditor/SupportedKeywords.java new file mode 100644 index 0000000..821467c --- /dev/null +++ b/src/simplejavatexteditor/SupportedKeywords.java @@ -0,0 +1,54 @@ +package simplejavatexteditor; + +import java.util.ArrayList; + +public class SupportedKeywords { + private String[] java = {"abstract", "assert", "boolean", + "break", "byte", "case", "catch", "char", "class", "const", + "continue", "default", "do", "double", "else", "extends", "false", + "final", "finally", "float", "for", "goto", "if", "implements", + "import", "instanceof", "int", "System", "out", "print()", "println()", + "new", "null", "package", "private", "protected", "public", "interface", + "long", "native", "return", "short", "static", "strictfp", "super", "switch", + "synchronized", "this", "throw", "throws", "transient", "true", + "try", "void", "volatile", "while", "String"}; + + private String[] cpp = { "auto", "const", "double", "float", "int", "short", + "struct", "unsigned", "break", "continue", "else", "for", "long", "signed", + "switch", "void", "case", "default", "enum", "goto", "register", "sizeof", + "typedef", "volatile", "char", "do", "extern", "if", "return", "static", + "union", "while", "asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", + "bool", "explicit", "new", "static_cast", "typeid", "catch", "false", "operator", + "template", "typename", "class", "friend", "private", "this", "using", "const_cast", "inline", + "public", "throw", "virtual", "delete", "mutable", "protected", "true", "wchar_t", }; + + private String[] brackets = { "{", "(" }; + private String[] bCompletions = { "}", ")" }; + public String[] getJavaKeywords() { + return java; + } + public String[] getCppKeywords() { + return cpp; + } + public ArrayList getbracketCompletions() { + ArrayList alist = new ArrayList<>(); + for(String completion : bCompletions) { + alist.add(completion); + } + return alist; + } + public ArrayList getbrackets() { + ArrayList alist = new ArrayList<>(); + for(String completion : brackets) { + alist.add(completion); + } + return alist; + } + public ArrayList setKeywords(String[] arr) { + ArrayList al = new ArrayList<>(); + for(String words : arr) { + al.add(words); + } + return al; + } +} \ No newline at end of file diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index 42bf9b0..512173d 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -27,11 +27,15 @@ // Input Stream import java.io.*; // Various +import java.util.ArrayList; +import java.util.EventListener; import java.util.Scanner; import javax.swing.border.Border; +import javax.swing.event.DocumentListener; +import javax.xml.bind.Marshaller; public class UI extends JFrame implements ActionListener { - + private static final long serialVersionUID = 1L; private final Container container; private final JTextArea textArea; @@ -40,41 +44,49 @@ public class UI extends JFrame implements ActionListener { private final JMenuItem newFile, openFile, saveFile, close, clearFile, quickFind, aboutMe, aboutSoftware; private final JToolBar mainToolbar; JButton newButton, openButton, saveButton, clearButton, quickButton, aboutMeButton, aboutButton, closeButton, spaceButton1, spaceButton2; - + //setup icons - File Menu private final ImageIcon newIcon = new ImageIcon("icons/new.png"); private final ImageIcon openIcon = new ImageIcon("icons/open.png"); private final ImageIcon saveIcon = new ImageIcon("icons/save.png"); private final ImageIcon closeIcon = new ImageIcon("icons/close.png"); - + //setup icons - Search Menu private final ImageIcon clearIcon = new ImageIcon("icons/clear.png"); - + //setup icons - Search Menu private final ImageIcon searchIcon = new ImageIcon("icons/search.png"); - + //setup icons - Help Menu private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); - - public UI() { + + private boolean hasListener = false; + JavaAutoComplete autocomplete; + + public UI() { container = getContentPane(); - + // Set the initial size of the window - setSize(700, 500); - + setSize(700, 500); + // Set the title of the window setTitle("Undefined | " + SimpleJavaTextEditor.NAME); - + // Set the default close operation (exit when it gets closed) - setDefaultCloseOperation(EXIT_ON_CLOSE); - + setDefaultCloseOperation(EXIT_ON_CLOSE); + // Set a default font for the TextArea textArea = new JTextArea("", 0,0); +<<<<<<< Updated upstream textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); textArea.setTabSize(2); +======= + textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); + textArea.setTabSize(2); + +>>>>>>> Stashed changes - // This is why we didn't have to worry about the size of the TextArea! getContentPane().setLayout(new BorderLayout()); // the BorderLayout bit makes it fill it automatically getContentPane().add(textArea); @@ -84,7 +96,7 @@ public UI() { menuEdit = new JMenu("Edit"); menuFind = new JMenu("Search"); menuAbout = new JMenu("About"); - + // Set the Items Menu newFile = new JMenuItem("New", newIcon); openFile = new JMenuItem("Open", openIcon); @@ -94,31 +106,31 @@ public UI() { quickFind = new JMenuItem("Quick", searchIcon); aboutMe = new JMenuItem("About Me", aboutMeIcon); aboutSoftware = new JMenuItem("About Software", aboutIcon); - + // Set the Menu Bar into the our GUI menuBar = new JMenuBar(); - menuBar.add(menuFile); + menuBar.add(menuFile); menuBar.add(menuEdit); menuBar.add(menuFind); - menuBar.add(menuAbout); + menuBar.add(menuAbout); this.setJMenuBar(menuBar); - + // New File newFile.addActionListener(this); // Adding an action listener (so we know when it's been clicked). newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK)); // Set a keyboard shortcut menuFile.add(newFile); // Adding the file menu - + // Open File openFile.addActionListener(this); - openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); - menuFile.add(openFile); - + openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); + menuFile.add(openFile); + // Save File saveFile.addActionListener(this); saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); menuFile.add(saveFile); - + // Close File /* @@ -134,95 +146,95 @@ public UI() { // Clear File (Code) clearFile.addActionListener(this); - clearFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_MASK)); + clearFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_MASK)); menuEdit.add(clearFile); - + // Find Word quickFind.addActionListener(this); quickFind.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK)); menuFind.add(quickFind); - + // About Me aboutMe.addActionListener(this); aboutMe.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)); menuAbout.add(aboutMe); - + // About Software aboutSoftware.addActionListener(this); aboutSoftware.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); menuAbout.add(aboutSoftware); - + mainToolbar = new JToolBar(); this.add(mainToolbar, BorderLayout.NORTH); //used to create space between button groups Border emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 50); - + newButton = new JButton(newIcon); newButton.setToolTipText("New"); newButton.addActionListener(this); mainToolbar.add(newButton); mainToolbar.addSeparator(); - + openButton = new JButton(openIcon); openButton.setToolTipText("Open"); openButton.addActionListener(this); mainToolbar.add(openButton); mainToolbar.addSeparator(); - + saveButton = new JButton(saveIcon); saveButton.setToolTipText("Save"); saveButton.addActionListener(this); mainToolbar.add(saveButton); mainToolbar.addSeparator(); - + clearButton = new JButton(clearIcon); clearButton.setToolTipText("Clear All"); clearButton.addActionListener(this); mainToolbar.add(clearButton); mainToolbar.addSeparator(); - + quickButton = new JButton(searchIcon); quickButton.setToolTipText("Quick Search"); quickButton.addActionListener(this); mainToolbar.add(quickButton); - + //create space between button groups spaceButton1 = new JButton(); spaceButton1.setBorder(emptyBorder); mainToolbar.add(spaceButton1); - + aboutMeButton = new JButton(aboutMeIcon); aboutMeButton.setToolTipText("About Me"); aboutMeButton.addActionListener(this); mainToolbar.add(aboutMeButton); mainToolbar.addSeparator(); - + aboutButton = new JButton(aboutIcon); aboutButton.setToolTipText("About NotePad PH"); aboutButton.addActionListener(this); mainToolbar.add(aboutButton); - + //create space between button groups spaceButton2 = new JButton(); spaceButton2.setBorder(emptyBorder); mainToolbar.add(spaceButton2); - + closeButton = new JButton(closeIcon); closeButton.setToolTipText("Close"); closeButton.addActionListener(this); mainToolbar.add(closeButton); } - + //make the TextArea available to the autocomplete handler protected JTextArea getEditor() { return textArea; } - + public void actionPerformed (ActionEvent e) { // If the source of the event was our "close" option if(e.getSource() == close || e.getSource() == closeButton) this.dispose(); // dispose all resources and close the application - + // If the source was the "new" file option else if(e.getSource() == newFile || e.getSource() == newButton) { FEdit.clear(textArea); @@ -253,7 +265,7 @@ else if(e.getSource() == openFile || e.getSource() == openButton) { // If the source of the event was the "save" option else if(e.getSource() == saveFile || e.getSource() == saveButton) { // Open a file chooser - JFileChooser fileChoose = new JFileChooser(); + JFileChooser fileChoose = new JFileChooser(); // Open the file, only this time we call int option = fileChoose.showSaveDialog(this); @@ -269,23 +281,46 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { // Create a buffered writer to write to a file BufferedWriter out = new BufferedWriter(new FileWriter(file.getPath())); // Write the contents of the TextArea to the file - out.write(textArea.getText()); + out.write(textArea.getText()); // Close the file stream - out.close(); - - if(file.getName().endsWith(".java")) { - //setup Autocomplete for Java keywords - JavaAutoComplete autocomplete = new JavaAutoComplete(this); - textArea.getDocument().addDocumentListener(autocomplete); - } + out.close(); + + if(hasListener) { + textArea.getDocument().removeDocumentListener(autocomplete); + hasListener = false; + } + + SupportedKeywords kw = new SupportedKeywords(); + ArrayList arrayList; + String[] list = { ".java", ".cpp" }; + for(int i = 0; i < list.length; i++) { + if(file.getName().endsWith(list[i])) { + switch(i) { + case 0: + String[] jk = kw.getJavaKeywords(); + arrayList = kw.setKeywords(jk); + autocomplete = new JavaAutoComplete(this, arrayList); + textArea.getDocument().addDocumentListener(autocomplete); + hasListener = true; + break; + case 1: + String[] ck = kw.getCppKeywords(); + arrayList = kw.setKeywords(ck); + autocomplete = new JavaAutoComplete(this, arrayList); + textArea.getDocument().addDocumentListener(autocomplete); + hasListener = true; + break; + } + } + } } catch (Exception ex) { // again, catch any exceptions and... // ...write to the debug console System.out.println(ex.getMessage()); } } } - + // Clear File (Code) if(e.getSource() == clearFile || e.getSource() == clearButton) { FEdit.clear(textArea); @@ -293,8 +328,8 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { // Find if(e.getSource() == quickFind || e.getSource() == quickButton) { new Find(textArea); - } - + } + // About Me else if(e.getSource() == aboutMe || e.getSource() == aboutMeButton) { new About().me(); @@ -303,6 +338,18 @@ else if(e.getSource() == aboutMe || e.getSource() == aboutMeButton) { else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { new About().software(); } - - } + + } + + /* + bool hasListener = false + + for.. + if.. + if(hasListener) { + removeListener + } + switch.. +//It has a + */ } From 922294736f7cffd3ca244fa6713aebe64c523a15 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 22 Mar 2016 22:53:38 -0400 Subject: [PATCH 14/15] Final Commit This is the completed enhancement. I have found this useful so I might expand on it in the future, but for now I think I am finished with it. --- .../JavaAutoComplete.java | 19 ++---- .../SupportedKeywords.java | 24 ++++--- src/simplejavatexteditor/UI.java | 64 +++++++++---------- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/simplejavatexteditor/JavaAutoComplete.java b/src/simplejavatexteditor/JavaAutoComplete.java index 40da064..0005dd5 100644 --- a/src/simplejavatexteditor/JavaAutoComplete.java +++ b/src/simplejavatexteditor/JavaAutoComplete.java @@ -16,12 +16,14 @@ import javax.swing.text.BadLocationException; /** - *

Auto complete functionality for java keywords, brackets and + *

Auto complete functionality multiple programming languages, including brackets and * parentheses

* *

- * An ArrayList is created for the keywords and the brackets. If the word - * currently being typed matches a word in the list, a Runnable inner class is + * An ArrayList is created for the keywords and the brackets. + * Logic for setting the content of the ArrayList is + * found in UI.java. If the word currently being typed + * matches a word in the list, a Runnable inner class is * implemented to handle the word completion. * * Two other inner classes are also used. The second one handles when the enter @@ -42,6 +44,7 @@ public class JavaAutoComplete private ArrayList words = new ArrayList<>(); SupportedKeywords kw; + //Keep track of when code completion //has been activated private enum Mode { @@ -57,12 +60,8 @@ private enum Mode { private int pos; private String content; - public JavaAutoComplete(UI ui) { - this.ui = ui; - textArea = ui.getEditor(); - } - public JavaAutoComplete(UI ui, ArrayList al) { + //Set the keywords words = al; kw = new SupportedKeywords(); brackets = kw.getbrackets(); @@ -281,8 +280,4 @@ public void removeUpdate(DocumentEvent e) { @Override public void changedUpdate(DocumentEvent e) { } - - public void removeListener() { - textArea.getDocument().removeDocumentListener(this); - } } \ No newline at end of file diff --git a/src/simplejavatexteditor/SupportedKeywords.java b/src/simplejavatexteditor/SupportedKeywords.java index 821467c..ef4e590 100644 --- a/src/simplejavatexteditor/SupportedKeywords.java +++ b/src/simplejavatexteditor/SupportedKeywords.java @@ -2,6 +2,14 @@ import java.util.ArrayList; +/** + *

A class to store the programming language keywords and + * provide access to them.

+ * + *

Makes multiple language support possible and makes adding new language + * support convenient. To add more keywords, add a string array and getters + * to this class. Then, update the switch statement in UI.java.

+ */ public class SupportedKeywords { private String[] java = {"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", @@ -19,8 +27,8 @@ public class SupportedKeywords { "typedef", "volatile", "char", "do", "extern", "if", "return", "static", "union", "while", "asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", "bool", "explicit", "new", "static_cast", "typeid", "catch", "false", "operator", - "template", "typename", "class", "friend", "private", "this", "using", "const_cast", "inline", - "public", "throw", "virtual", "delete", "mutable", "protected", "true", "wchar_t", }; + "template", "typename", "class", "friend", "private", "this", "using", "const_cast", + "inline", "public", "throw", "virtual", "delete", "mutable", "protected", "true", "wchar_t" }; private String[] brackets = { "{", "(" }; private String[] bCompletions = { "}", ")" }; @@ -31,18 +39,18 @@ public String[] getCppKeywords() { return cpp; } public ArrayList getbracketCompletions() { - ArrayList alist = new ArrayList<>(); + ArrayList al = new ArrayList<>(); for(String completion : bCompletions) { - alist.add(completion); + al.add(completion); } - return alist; + return al; } public ArrayList getbrackets() { - ArrayList alist = new ArrayList<>(); + ArrayList al = new ArrayList<>(); for(String completion : brackets) { - alist.add(completion); + al.add(completion); } - return alist; + return al; } public ArrayList setKeywords(String[] arr) { ArrayList al = new ArrayList<>(); diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index 512173d..a61e240 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -19,20 +19,23 @@ package simplejavatexteditor; // GUI + import javax.swing.*; -import java.awt.BorderLayout; -import java.awt.Container; -import java.awt.Font; -import java.awt.event.*; -// Input Stream -import java.io.*; -// Various +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; import java.util.ArrayList; -import java.util.EventListener; import java.util.Scanner; -import javax.swing.border.Border; -import javax.swing.event.DocumentListener; -import javax.xml.bind.Marshaller; + +// Input Stream +// Various public class UI extends JFrame implements ActionListener { @@ -43,7 +46,11 @@ public class UI extends JFrame implements ActionListener { private final JMenu menuFile, menuEdit, menuFind, menuAbout; private final JMenuItem newFile, openFile, saveFile, close, clearFile, quickFind, aboutMe, aboutSoftware; private final JToolBar mainToolbar; - JButton newButton, openButton, saveButton, clearButton, quickButton, aboutMeButton, aboutButton, closeButton, spaceButton1, spaceButton2; + JButton newButton, openButton, + saveButton, clearButton, + quickButton, aboutMeButton, + aboutButton, closeButton, + spaceButton1, spaceButton2; //setup icons - File Menu private final ImageIcon newIcon = new ImageIcon("icons/new.png"); @@ -61,8 +68,8 @@ public class UI extends JFrame implements ActionListener { private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); - private boolean hasListener = false; - JavaAutoComplete autocomplete; + JavaAutoComplete autocomplete; + private boolean hasListener = false; public UI() { container = getContentPane(); @@ -78,14 +85,10 @@ public UI() { // Set a default font for the TextArea textArea = new JTextArea("", 0,0); -<<<<<<< Updated upstream - textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); - textArea.setTabSize(2); -======= textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); textArea.setTabSize(2); - ->>>>>>> Stashed changes + textArea.setFont(new Font("Century Gothic", Font.BOLD, 12)); + textArea.setTabSize(2); // This is why we didn't have to worry about the size of the TextArea! getContentPane().setLayout(new BorderLayout()); // the BorderLayout bit makes it fill it automatically @@ -285,15 +288,24 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { // Close the file stream out.close(); + //If the user saves files with supported + //file types more than once, we need to remove + //previous listeners to avoid bugs. if(hasListener) { textArea.getDocument().removeDocumentListener(autocomplete); hasListener = false; } + //With the keywords located in a separate class, + //we can support multiple languages and not have to do + //much to add new ones. SupportedKeywords kw = new SupportedKeywords(); ArrayList arrayList; String[] list = { ".java", ".cpp" }; + //Iterate through the list, find the supported + //file extension, apply the appropriate getter method from + //the keyword class for(int i = 0; i < list.length; i++) { if(file.getName().endsWith(list[i])) { switch(i) { @@ -340,16 +352,4 @@ else if(e.getSource() == aboutSoftware || e.getSource() == aboutButton) { } } - - /* - bool hasListener = false - - for.. - if.. - if(hasListener) { - removeListener - } - switch.. -//It has a - */ } From fd532981f69956566d2511a6e6968f6540eec187 Mon Sep 17 00:00:00 2001 From: patrick-slagle Date: Tue, 22 Mar 2016 23:04:48 -0400 Subject: [PATCH 15/15] Taking the word "Java" out of the auto complete class --- .../{JavaAutoComplete.java => AutoComplete.java} | 4 ++-- src/simplejavatexteditor/UI.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/simplejavatexteditor/{JavaAutoComplete.java => AutoComplete.java} (98%) diff --git a/src/simplejavatexteditor/JavaAutoComplete.java b/src/simplejavatexteditor/AutoComplete.java similarity index 98% rename from src/simplejavatexteditor/JavaAutoComplete.java rename to src/simplejavatexteditor/AutoComplete.java index 0005dd5..0f9c88b 100644 --- a/src/simplejavatexteditor/JavaAutoComplete.java +++ b/src/simplejavatexteditor/AutoComplete.java @@ -35,7 +35,7 @@ * @author Patrick Slagle * @since 2016-12-03 */ -public class JavaAutoComplete +public class AutoComplete implements DocumentListener { private ArrayList brackets = new ArrayList<>(); @@ -60,7 +60,7 @@ private enum Mode { private int pos; private String content; - public JavaAutoComplete(UI ui, ArrayList al) { + public AutoComplete(UI ui, ArrayList al) { //Set the keywords words = al; kw = new SupportedKeywords(); diff --git a/src/simplejavatexteditor/UI.java b/src/simplejavatexteditor/UI.java index a61e240..8e6d343 100644 --- a/src/simplejavatexteditor/UI.java +++ b/src/simplejavatexteditor/UI.java @@ -68,7 +68,7 @@ public class UI extends JFrame implements ActionListener { private final ImageIcon aboutMeIcon = new ImageIcon("icons/about_me.png"); private final ImageIcon aboutIcon = new ImageIcon("icons/about.png"); - JavaAutoComplete autocomplete; + AutoComplete autocomplete; private boolean hasListener = false; public UI() { @@ -312,14 +312,14 @@ else if(e.getSource() == saveFile || e.getSource() == saveButton) { case 0: String[] jk = kw.getJavaKeywords(); arrayList = kw.setKeywords(jk); - autocomplete = new JavaAutoComplete(this, arrayList); + autocomplete = new AutoComplete(this, arrayList); textArea.getDocument().addDocumentListener(autocomplete); hasListener = true; break; case 1: String[] ck = kw.getCppKeywords(); arrayList = kw.setKeywords(ck); - autocomplete = new JavaAutoComplete(this, arrayList); + autocomplete = new AutoComplete(this, arrayList); textArea.getDocument().addDocumentListener(autocomplete); hasListener = true; break;