Project 1: Text Editor
In this project you and a teammate will implement an interactive text
editor that supports basic editing functions plus infinite-level undo
and multiple windows on the same file. You will use Java and the Swing
toolkit for the implementation.
Features
Here are the specific features your editor must support:
- Basic display and scrolling: the editor must display the contents
of a file in a window along with horizontal and vertical scrollbars.
The editor must work correctly when the window is
resized. The size of the thumbs in the scrollbars must properly
reflect the current height and of the window relative to the total
document height and width; this must change when the document is modified
or the window is resized.
- No rich text: all text should be displayed in a single font (like
vim, for example). The editor does not need to support rich text features
such as multiple fonts, boldface, italic, tabs, or adjustable indents.
- Lines: lines in the document are terminated by newline
characters ("\n"). Each line of the document should appear as a single
line in the display (i.e., do not wrap long lines; the user can scroll
horizontally instead).
On Windows platforms, files sometimes use a two-character sequence "\r\n" to
terminate lines; when reading in files, you should replace "\r\n" with
just "\n", and when writing out files, you should always use "\n" as
the line terminator.
- Fixed width font: you should use a fixed width font for the
editor, so that columns line up. I recommend using the Monospace font
in a 12-point size.
- Reading and writing files: the editor should require a single
command-line argument giving the name of the
file to edit. If the user types
Control-s
, the editor
should save the current contents of the document back to the file.
- Insertion cursor: when the user clicks in the window, the
editor must display a blinking vertical bar just to the left of the
closest character to the click. The bar should blink on and off:
on for 0.5 seconds, then off for 0.5 seconds, and so on. If the mouse
is dragged with the button down, the insertion cursor must follow the
mouse. If a window loses input focus (i.e., you click in a different
window) it should stop displaying the cursor; when the window regains
focus it should display the cursor again.
- Typing: when the user types printable characters such as "A"
or "%", the characters should be inserted at the cursor location and
the cursor should advance to remain just after the character that was
typed.
- Newlines: if the user types the
Enter
or
Return
key (which corresponds to
the Control-r
character, or "\r"), you should insert a newline
character ("\n") in the document and display a new line in the window.
- Backspace and delete: if the user types the
Backspace
key, the editor must delete the character
immediately before the cursor (unless there is a selection; see below).
The Delete
key should delete the character at the cursor
location.
- Selection: if the user presses the mouse button and drags
the mouse either forward or backward, the editor must create a selection
corresponding to the range of characters between the character where the
mouse was pressed and the current mouse location. The new selection
replaces any previous selection. The selection must be displayed using
some form of highlighting, such as a colored background or reverse video.
Once a selection has been made, if the user presses the mouse button while
holding down the
Shift
key, then the selection should
be modified as if the mouse button had never been released (i.e. the
current mouse position specifies one end of the selection, and the
other end of the selection is determined by the location where the
mouse was clicked without the Shift
key down). If the
mouse button is pressed and released without dragging, then any
existing selection is canceled. You do not need to implement word
selection for double-clicks.
- Selection deletion: if a printable character or newline
is typed at a time when there exists a selection, then the new
character must replace the selection. If
Backspace
or
Delete
is typed when there exists a selection,
then the editor should skip the normal behavior for these keys and
simply delete the selected characters.
- Copy and paste: if the user types
Control-c
,
the editor should copy the selected characters to the clipboard, where
they can be pasted by other applications. If the user types
Control-v
, the editor must read the contents of the clipboard
and copy it to the cursor location (deleting any selected characters
first). You must use Swing/AWT facilities for copying and pasting,
so that you can select in this window and paste in other applications,
and vice versa.
- Arrow keys: the four arrow keys must move the insertion cursor
up, down, left, and right by one character. When moving up and down,
the editor must try to maintain the same x-coordinate. For example, suppose
the cursor is currently before the 10th character on line 13, and then
the up arrow is typed twice. If line 13 only contains 5 characters,
then the first up arrow will position the cursor just before the
newline on that line. However, if line 12 contains 20 characters,
then the second up arrow will position the cursor just before
character 10 on that line. If the right arrow is typed at the end
of a line, the cursor must be moved to the first character in the next
line. If the left arrow is typed at the beginning of a line, the cursor
must be moved to just before the newline in the preceding line.
- Infinite-level undo: the editor must record all modifications
to the document. If the user types
Control-z
, the editor
must undo the most recent modification. If the user types
Control-z
repeatedly, the editor must undo successively older
changes, all the way back to the original version of the document
loaded when the editor was first invoked. After
undoing one or more modifications, the user may type
Control-y
to redo the modifications in the reverse order
they were undone. If the document is modified at a time when there
exist redoable operations, then all of the redoable operations are
discarded; future
undos and redos will behave as if those operations never occurred.
- Undo and the selection and cursor: the undo/redo mechanism
must also record information about the selection and insertion cursor.
Undo operations must restore the selection and cursor to the state they were
in just before the original execution of the modification. Redo operations
must restore the selection and cursor to the same state they had just after
the original execution of the operation.
- Undo grouping: if several characters are typed consecutively
without repositioning the cursor, they must be treated as a unit for undo
and redo: a single undo must undo all of the characters. If several
characters are deleted with
Backspace
or Delete
,
all of these deletions must also be treated as a unit for undo and redo.
- All modifications visible: if a modification is made to a
portion of the document that is offscreen, the document must be scrolled
so that the modified text is visible. This can happen during undo and
redo operations, and also during normal text inserts, if the window
is scrolled to move the cursor offscreen. If multiple windows are open
on the document, then only the window in which the modification was
invoke should be scrolled: other windows should be repainted if needed,
but they should not be scrolled.
- Multiple windows: if
Control-o
is typed, the
editor must open an additional window displaying the same file.
Different windows may have different sizes, and they can be scrolled
independently. It should
then be possible to edit the file from any of the windows. Modifications
to the file must be reflected in all of the windows, and there should be
a single undo history containing all of the modifications from all of the
windows. The "all modifications visible" requirement above applies only
to the window in which the modification was invoked; other windows
should not be scrolled automatically. Each window should have a
separate selection and insertion cursor.
The descriptions above are fairly terse, but they are intended to mimic
the basic behaviors of most existing text editors. I recommend experimenting
with a couple of different editors to a better feel for exactly how your
editor should behave.
Implementation
You must implement your editor in Java using the Swing toolkit. Java
offers a newer toolkit called JavaFX, but its features are not a good match
to this project. Here are some additional requirements for your
implementation:
- You must implement the text editor in Java. I recommend using
the Eclipse IDE, but you may use a different development environment if you
prefer.
- You must work in teams of two. This is important for three reasons:
first, by working in teams you can attack a larger project,
which leads to more interesting code structuring issues; second, the
team approach means that you have someone with whom you can discuss
your designs; and third, it reduces the number of projects that I
have to read, which permits a larger class size.
- Your most important goal is to create a clean, simple, and elegant
code structure. Although I expect your code to work, and it
must implement the features described here, I will be
judging it primarily on its structure; it's better to spend time
cleaning up the structure and documentation than fixing every last
bug.
- You must use a JPanel component for the main
editor window; you must repaint the text, insertion cursor, and selection
as needed using the Swing/AWT painting interface. You may
use basic Swing or AWT components for other components such as
the scrollbars.
- You must design and build all the mechanisms for managing the text,
undo/redo, and displaying the text yourself. You may not use Swing classes
such as UndoManager or AbstractDocument and I would prefer that you not
even look at these classes. You should design your own mechanisms from
scratch (and the existing Swing classes don't necessarily provide a
good model to follow). If you aren't sure whether it's okay to use an
existing class, please check with me; if the class simplifies your job
significantly, it's probably not okay to use it.
- Your implementation must be efficient
enough to support large files (at least 100,000 lines and 10 MBytes
total size) without significant lags either for loading the file or
for any interactive operations. For example, here is a good
test file to experiment with.
- When repainting parts of the screen after
changes, the repainting must be done in a way that does not cause
flashing on the screen or other visual unpleasantness. Swing already
has good support for this, so you may not need to worry about
this issue.
- If you have not used Swing previously,
I recommend starting with the
Swing tutorials. Start with the "Performing Custom Painting"
tutorial to see how to draw on the screen, then work through other
tutorials on topics such as "Writing Event Listeners" as you need
them. Try creating a simple scrollable JPanel that displays a
static text string for starters.
- When designing your interfaces, I ask that you do this from scratch,
without consulting any existing code that offers similar
functionality. This is important so that you can think things
through for yourself. In addition, many existing packages have
bad interfaces, so it may not be good to use them for ideas.
Development Environment
I recommend using the Eclipse development environment for the projects
in this class, but if there is some other development environment that
you prefer, that's fine too. Please configure your development
environment so that indent widths are 4 spaces, and only space
characters are stored in files, never tabs (this will make it easier for
me to review your code: tab characters and/or 8-space indents result
in very long lines in the code review tool).
Here's how you can configure Eclipse for this:
- Go to Window->Preferences->Java->Code Style->Formatter
- Select "Edit..."
- Set "Indentation size" to 4, "Tab size" to 4, and "Tab policy"
to "Spaces only", then save this (you may need to create a new
named profile to save this information).
- If you have already created some files using different
indentation, you can reformat them by selecting the files
in the Package Explorer, then right-clicking one of the
files and selecting Source->Format.
Please keep your lines no longer than 80 characters in length. Long lines
make code harder to read, and they don't work very well in the code review
tool that we will be using.
Submitting Your Project
You will submit your project by creating an issue on a Web-based code
review tool. For this class we will use the Rietveld code
review tool, which is hosted on Google App Engine (this tool has a few
features that make it more convenient for this class than the GitHub
code review facilities). Here is how to submit your project:
- Create a git tag named
project1
for the commit that
you are submitting for the project. Push this tag to GitHub.
- Download the script upload.py,
which you will use to submit issues to the code review tool.
- You will need a Google account to submit a code
review, so create one now if you don't already have one.
- Invoke the following command:
python upload.py --rev XXX..project1
where XXX is the git identifier for the very first (initial) commit
for your repo.
- When asked for "New issue subject", type "AAA/BBB Project 1", where
AAA and BBB are the last names of the team members, in alphabetical
order (use AAA if your team has only one person).
- Provide your Google account information when asked for email
and password. Note: if you have two-step authentication enabled for
your Google account, your password will be rejected; go to
this
page to generate a special app password to use for upload.py.
Once you have created the code review, check to make sure it is visible at
cs190codereview.appspot.com.
If you make changes after creating your issue and would like to replace
the issue with a new one, you can delete the existing issue by viewing it,
clicking "Edit Issue" in the upper left corner, then clicking
the "Delete Issue" button at the bottom of the resulting page.
If you are planning to use late days for this project (or any project) please
send me an email before the project deadline so that I know your plans. Send
me another email once you eventually upload your code review.
README file
I will also download your GitHub repo and try running your editor on
a large test file. Please create a README file in the top-level directory
of your project with instructions for how to run the editor. I
have Eclipse available, so if you are using Eclipse for your IDE, the
README can just indicate how to run the editor from Eclipse. If you
aren't using Eclipse, then you'll need to leave instructions for how
I can build and run the editor without an IDE (e.g., an Ant script to
build a .jar file, etc.?).