Bankviewer

Java (11), Swing (Single document interface)

My friend gets bank statements as text files, with data shown as key-value pairs. He puts these files into a system, but sometimes there are issues. The payment date might be strange, the wrong code might be used, or a required field might be missing. Checking the file in a text editor is hard. It would be much better if he could open the file in a program and see the statement as a clear table, with each payment on a separate row. This would easily show all payments, who they're from, who they're to, and all the details.

This is exactly what this program does. But it also allows you to understand how to create a menu, toolbar, status bar, context menu, file open dialog, file table display, search, drag & drop, and L&F using a bit of Java and Swing, and put it all together as an SDI.

Eclipse was used for development. The project is located here: https://github.com/weekend-game/bankviewer/ (EN) and here: https://gitflic.ru/project/weekend-game/bankviewer/ (RU).

How to run the program

Download the repository to your computer. Everything you need for the program is located in the app folder. Navigate to the app folder and run the program by double-clicking the BankViewer.jar file or, if the program doesn't start, double-click the BankViewer.bat file. If the program doesn't start, download and install Java 11 or later and repeat the steps above.

How to open a project in Eclipse

In Eclipse, select "Import..." from the "File" menu. In the window that opens, select "Existing projects into workspace." Navigate to the folder with the downloaded repository and click "Finish." The project will open in Eclipse. In the Package Explorer (on the left side of the screen), double-click the BankViewer.java file. The file will open for editing (in the center of the screen). Run the program by pressing Ctrl+F11 or using your preferred method for running programs in Eclipse.

The project includes a separate program called TestGenerator. It is located in the game.weekend.bankviewer.util package. The program allows you to specify the file name and number of bank statement lines, and it will generate a test file for you. The BankStatement1.txt file was generated using TestGenerator.

How to use the program

The program uses a single document interface. This means that upon launch, you'll see the familiar menu, toolbar, empty space in the center of the window for displaying the document, and a status bar at the very bottom.

There are three ways to open a bank statement for viewing.

The first method is to select "File" - "Open..." from the menu or use the button on the toolbar. This will open a dialog box where you can select a bank statement file, for example, the BankStatement1.txt file available in the repository.

The second method is to use the Drag and Drop feature, specifically dragging the bank statement file to the center of the application window.

The third method is good for previously opened files. Paths to recently opened files are displayed in the "File" menu. Simply select the desired file, and it will be displayed.

To find text on a bank statement, press Ctrl+F, button with the image of binoculars on the toolbar, or select "Find..." from the Edit menu. In the dialog box that opens, enter your search string, select case sensitivity, specify the search direction, and click "Find Next." You can continue searching from the open search window using the toolbar buttons or keyboard shortcuts (Ctrl+G or Ctrl+Shift+G).

Some operations can be performed by right-clicking to open the context menu.

The application's appearance can be customized using the View menu.

First, you can choose your preferred design style. Second, you can hide the toolbar and status bar. You can view your bank statement using only keyboard shortcuts and menu items, but the toolbar and status bar take up space. Third, you can select the interface language: Russian or English.

All settings, even the search string, are saved between sessions.

How the program is written

The main class of the application is the BankViewer class. It contains the static main() method for launching the program. Its constructor creates everything necessary for operation.

First, the Proper.read() method is called. The Proper is a class that allows the application to save data between sessions. This saves the location and size of the main window, the preferred interface language, the paths to several recently opened files, whether to display the toolbar and status bar, the last entered search string, and some other data. The read() method reads a file with previously saved data. The save() method does the opposite: it writes everything saved in the object to a file. The setProperty(name, value) method saves the value named "name." The getProperty(name, def) method reads the value named "name." If it hasn't been saved, the value "def" will be returned. The saveBounds() and setBounds() methods are used to save and restore the location and size of the application window.

The interface language is then set using the static Loc.setLanguage() method. The Loc class is responsible for I18n. It works like this: all strings intended for display are written in English, using underscores instead of spaces. The Loc.get(string) method will return strings in the previously set language, provided, of course, the messages_xx.properties localization file is found, where xx is the language convention. Otherwise, underscores in the English phrase will be replaced with spaces, and the first letter will be capitalized. The resulting string will be used for display. For the purposes of this program, this is sufficient.

The application window is created – an object of the JFrame class. The makeJFrame() method is immediately called, creating everything necessary. The main thing is the BorderLayout() layout manager. This will help implement SDI. A JEditorPane will be located in the center section, displaying the bank statement as a table. The toolbar will be located at the top, and the status bar at the bottom.

A JEditorPane class panel is created to display a bank statement as a table. The makeJEditorPane() method is immediately called. In this method, the panel is wrapped in a JScrollPane, positioned in the central part of the application window, monitors the selection/deselection of text on the displayed statement, and implements drag-and-drop file opening.

The program opens files to display them like a table. Swing provides a ready-made dialog for specifying the file to open: the javax.swing.JFileChooser class. The Filer class is just a wrapper around it, allowing you to slightly customize its appearance and behavior.

The Filer requires a LastFiles class object. LastFiles, using the Proper class, stores and can read several special strings at program startup—the paths to the most recently opened files. It's very convenient to see them in the File menu and quickly select the desired one instead of using the Open File dialog. Each time a file is successfully opened, Filer stores the path in a LastFiles object. If the file is opened unsuccessfully, it removes the path from the saved list, if any. LastFiles provides the put() and remove() methods for these actions. It also has a getList() method, which Act uses to create a File menu fragment with a list of recently opened files from a list of paths.

Many Java programs allow the user to customize Look & Fill. This program is no exception. In the "View" menu, the user can select any Look & Fill available in their system. The LaF class helps with this.

The application contains a menu, a toolbar, and a context menu connected to the JEditorPane. All three of these objects are created by methods of the Act class. Each menu item or toolbar button is an object of the Action class. All necessary Actions are created by methods of the Act class. This is why this is probably the largest class in this program by number of lines. But it is also probably the simplest class in this program, because all Actions are created in the same way, and the menu and toolbar are simply a list of the required Actions in the required order. However, there are some minor nuances that are easy to understand by reading the class text.

The status bar is an object of the StatusBar class. The status bar is actually a JPanel containing three JTextFields. The class has three methods for displaying a string message in the corresponding JTextField. The field on the far right is a bit special: the message displayed in it will be visible for 5 seconds, and then it disappears. Of course, the status bar can be endlessly complicated and improved, but for this program, this status bar is quite sufficient.

Swing provides the JTable class for displaying information in a table. But there's another option: a JEditorPane, passed the URL of an HTML file containing a table formed by the <table> ... </table> tags via the setPage(URL u) method. I use the second option. So, the main point of the program is to convert the original key-value text file into an HTML file. The HTML file is then passed to display the JEditorPane, which is located in the center of the application's main window. Everything else is just SDI implementation and ensuring the program's usability.

If the user specifies a file, Filer will call the Convertor class's only public method, convert(), in its open() method. This method converts the source file, which contains key-value pairs, into an HTML file containing the same data, presented in a table. This HTML file is then passed to JEditorPane, which parses and displays it without any intervention from the programmer.

To implement searching in the displayed file, the Finder class was created. FinderFrame is a window for specifying a search string, representing a set of javax.swing components. The search algorithm is implemented in the Finder class. When creating FinderFrame, the problem of component placement arose, and the GBL class was created to solve this problem. GBL is a simplification of the GridBagLayout layout manager, adapted to the needs of the application.

You can learn more about the program's operation by downloading the project, opening it in Eclipse, reading the class code, making changes, running the program, and watching the results.

Results

The program turned out to be surprisingly simple and useful.

It would be nice...

It would be nice to be able to change the font size of the displayed bank statement.