CALIFORNIA STATE UNIVERSITY, NORTHRIDGE

IMPLEMENTATION OF A CUSTOMIZED STRUCTURE EDITOR

FOR JAVA, JAVASCRIPT AND HTML

A graduate project submitted in partial fulfillment of the requirements

For the degree of Master of Science in Computer Science

By

Marian Neagoie

December 2014

The graduate project of Marian Neagoie is approved:

______Dr. Taehyung Wang Date

______Dr. Robert McIlhenny Date

______Dr. Richard Covington, Chair Date

California State University, Northridge

ii

DEDICATION

This graduate project is dedicated to my parents who have provided me with the greatest support throughout my life.

iii

ACKNOWLEDGEMENTS

I would like to express my sincere gratitude to my advisor Prof. Rick Covington for the continuous support of my study and research, for his patience, enthusiasm, and immense knowledge. His guidance helped me in all the time of research and writing of this graduate project as well as throughout the years. Besides my advisor, I would like to thank the rest of my thesis committee: Prof. Taehyung Wang and Prof. Robert McIlhenny, for their encouragement, insightful comments and invaluable help in all the courses in which they were my instructors.

iv

ABSTRACT

IMPROVED CAPABLE OF RENDERING HTML AND RUNNING JAVASCRIPT

By

Marian Neagoie

Master of Science in Computer Science

This defense presents the results of a project intended to develop a structure editor that supports source in the following formats: plaint text, HTML, JavaScript, and Java. The editor is implemented in pure Java, with an emphasis on the Swing packages. Some rendering support for some formats (HTML) is built into Swing. Other rendering support

(Java source) is provided by customized tools to generate parse trees that allow keyword highlighting and indentation levels. JavaScript is interpreted and converted to HTML by the built-in eval(). Java source is compiled and interpreted by built-in compile() and exec() methods.

The project is compared to existing tools for feature comparison. The Swing

GroupLayout feature was chosen as the foundation of the UI, which has been used by code generators in the past. The Nimbus look-and-feel was used. The relationships between

Swing and JavaFX was considered but not used in the implementation.

v

Table of Contents

Signature Page ii

Dedication iii

Acknowledgements iv

Abstract v

Chapter 1: Introduction 1

1.1 Summary 1

Chapter 2: Current Similar Applications 3

2.1 Text Editors 3

2.1.1 TextMate 3

2.1.2 Notepad++ 4

2.1.3 TextPad 4

2.1.4 Coda 5

2.1.5 gedit 6

2.1.6 PSPad 6

2.2 Integrated Development Environments with Text Editing Features 7

2.2.1 Dreamweaver 7

2.2.2 8

2.3 Content Management Systems 9

Chapter 3: Requirement Analysis and Prototyping 10

Chapter 4: Overview and Technology Used 12

vi

4.1 UI Architecture 12

4.2 Java Swing Library 12

4.3 Implementation 13

Chapter 5: Functional Details 17

5.1 General Look and Feel 17

5.2 Getting Started with a New Document 19

5.3 Opening an existing file 20

5.4 Saving a File 23

5.5 Undo Editing 25

5.6 Redo Editing 26

5.7 Cut Text 28

5.8 Copy Text 29

5.9 Paste Text 31

5.10 Delete Text 32

5.11 Select All Text 34

5.12 Bold, Italic, Underline 36

5.13 Font Color 37

5.14 Font Style 38

5.15 Font Size 40

5.16 Rendering HTML 41

5.17 Running JavaScript 45

5.18 Running Java 49

5.19 Help 53

vii

5.20 About 54

5.21 Printing 56

5.22 Quit 57

Conclusion 58

Future Enhancements 59

Bibliography 60

Appendix A: 61

viii

CHAPTER 1

INTRODUCTION

1.1 SUMMARY

This application is a Java-based desktop application that is an example of a structure editor. Text editing is defined as the process of taking some input, changing it, and producing some output. Today there are many different editors available capable of satisfying the necessities of different types of users. Most of these products allow users to manage collections of files. Professionals such as Web developers or software engineers as a broader category need more advanced tools to perform tasks which simple text editors cannot achieve. Advanced editors are capable of handling more complex tasks, such as parsing different programming languages, editing files of very large sizes, and/or of different encodings, etc. Another important feature of generic structure editors is the fact that they are cognizant of the document’s underlying structure making them ery useful in editing hierarchical or marked up text, or any other type of content with clear and well- defined structure. In parallel to the advancements of these applications, the processing capabilities of the computers are improving exponentially, according to Moore’s Law which states that the number of transistors on integrated circuits doubles approximately every two years. This allows completing larger tasks much faster.

This project describes the implementation of a specific structure editor and the lessons learned. The features include rendering and editing of HTML, JavaScript, and Java,

1 plus the ability to compile and execute Java source. Implementation uses pure Java, with an emphasis on Swing. Rendering of HTML is provided as a built-in feature of the

JTextPane component. JavaScript interpretation is provided by the built-in eval() mthod.

Structured rendering of HTML, JavaScript and Java source is provided by a specialized text component called RSyntaxTextArea, which extends

JtextComponent, so it integrates completely with the standard javax.swing.text package.

In the remainder of this thesis, Chapter 2 is presenting a review of the literature, discussing some current similar applications, such as TextPad, which is a tool capable of handling HTML and “lightly” parsing Java, such as highlighting comments or matching . In Chapter 3, the requirement analysis is described and the specifications of the application are listed. Chapter 4 is discussing the Java Programming

Language and Java technologies used in the development of the application. Also, a brief comparison between Eclipse and NetBeans is conveyed. In Chapter 5, the functional details are provided with screenshots and description for each task that a user can perform. Chapter

6 is the conclusion of the thesis and the application, its purpose and results. Chapter 7 explains and lists some future enhancements that I would like to include in the application.

The Appendix contains the full Java implementation code of the application.

2

CHAPTER 2

CURRENT SIMILAR APPLICATIONS

2.1 TEXT EDITORS

This section discusses current similar text editing applications and their competitive advantages are analyzed. A total of six subsections are presenting in order the following popular applications: TextMate, Notepad++, TextPad, Coda, gedit, and PSPad.

2.1.1 TextMate

TextMate is a popular Macintosh editor for programmers and designers. It allows the users to theme the interface to their preference. It performs auto completing character pairs like parenthesis and brackets, and allows users to run shell commands from within a document. It was developed by a UNIX geek who was lured to the Mac platform by its ease of use and elegance. TextMate has been considered to be the culmination of Emacs and OS X and has resulted in countless requests for both a Windows and Linux port, but

TextMate has remained exclusive for Mac. TextMate is not an IDE but by using its unique scoping , macros, and powerful snippets it can often provide features that even a language specific IDE is lacking. Even though it has been kept fairly lightweight with a clean and minimalistic GUI, TextMate has enough project management features to keep most users happy. As positive capabilities we can list the following: - Customizable themes; - Capability of running shell commands within a document. The most important weakness is that it is not available for Windows platforms.

3

2.1.2 Notepad++

Notepad ++ is amongst the most popular text editors for a wide range of users.

Notepad++ is a simple and open-source application that is available for Windows under the GPL license. Notepad++ is written in C++ and it is focused towards obtaining higher execution speeds and smaller program sizes by using pure Win32 API and STL. Notepad++ is also trying to reduce the world carbon dioxide emissions by using less CPU power. This is achieved by optimizing as many routines as possible without losing user friendliness.

Notepad++ supports many languages and it is very easy to download and install. The download is about 7MB and the installation requires less than 23MB of disk space. Because it is so lightweight, Notepad++ can be run from iPods, thumb drives, or any portable device that accepts applications, making it one of the most portable in its class. One of the most notable strengths of Notepad++ is the powerful search and replace functionality. As an important weakness we can note that there is no version available for

Linux.

2.1.3 TextPad

TextPad is a general purpose text editor for Operating System created by Helios Software Solutions in England. It contains a variety of features including a macro recorder which allows users to define margins, a powerful spell checker for several languages, withdrawal and line alignment of the content, and a feature named “Warm

Start”, allowing users to start the application from where it was aborted. TextPad is a versatile text editor which runs on most versions of Microsoft Windows. Many developers use TextPad for things like creating XML files but also for editing Pearl or Java source

4 code. It is also very often utilized as an HTML editor and a free copy is available for evaluation. TextPad is shareware software, so if the users like it after testing it they have to buy the license, which is fairly reasonable (about $21 for a single license and down to

$10-15 each for bulk). As a notable pro of this tool we can mention the Macro Recording

Feature. As cons we can list the following: - it is only available for Windows; - the

Find/Replace feature is very limited.

2.1.4 Coda

Coda is a web development environment created for the Mac Operating System.

Some of its features include auto-completion, line numbers, and syntax highlighting. It is very user friendly and effective in editing scripting languages. In recent years, Coda has grown to be a critical tool for a high number of web developers around the world. It unites all the different web development tools under one beautifully designed user interface. Coda includes all the tools needed to write up, review and upload the web pages: text editor, previewer, CSS editor, , etc. It is an extremely flexible application: projects are considered as sites, which sync perfectly with the server and maintain all the changes. The user can easily connect to any server and with the help of Transmit Turbo Engine he/she is able to quickly upload changes remotely. Coda also includes many time-saving features, including Open Quickly window (for fast access to specific files), integrated subversion, and Clips (for frequently used code snippets). It has the downside of being available for

Mac only as well as being somewhat overwhelming for first time users.

5

2.1.5 gedit

gedit is an open source text editor created exclusively for Unix platforms. It is the default text editor of the GNOME desktop environment and an integral part of the GNOME

Core Applications. gedit has a variety of useful features including syntax highlighting. It supports a multitude of languages and offers remote file editing and back-up features. gedit was designed as a general purpose text editor and it emphasizes simplicity and ease of use.

It offers tools for editing source code and structured text like markup languages. The graphical user interface has a clean and simple design according to the philosophy of the

GNOME project. gedit contains GUI tabs for editing multiple files which can be moved between various windows by the user. It supports a full undo and redo system, search and replace, as well as syntax highlighting via GtkSourceView for various program code and text markup formats. Some other common code oriented features include bracket matching, line numbering, current line highlighting, automatic file backup, text wrapping and automatic indentation. It is available for both Microsoft Windows and Mac OS X.

2.1.6 PSPad

PSPad is an open-source editor created for Windows. It offers the capability of saving sessions, and it has a built-in FTP client which is very time efficient. It also has a text difference feature capable of comparing differences between files. It also has a hex editor, CP conversion, text differences, templates, macros, spellcheck option, auto- completion, and code explorer. PSPad is a universal freeware editor, used most frequently

6 by people who: -work with plain text; -create web pages; -want to use a good IDE for their compiler. The editor has a wealth of formatting functions, and as a web authoring editor, it contains many unique tools capable of saving a lot of development time. PSPad catches and parses compiler output, compares versions, integrates external help files, and it does not require a complex installation process. It is ready to work immediately without requiring customization. The most notable strengths are its FTP Client and the text difference feature. An important downside is that it is only available for Microsoft

Windows.

2.2 INTEGRATED DEVELOPMENT ENVIRONMENTS WITH TEXT EDITING

FEATURES

In this section, a brief discussion about integrated development environments is presented. The following popular IDEs are discussed along with their most notable text editing features.

2.2.1 Dreamweaver

Dreamweaver is a fully featured IDE with millions of users. It was developed by

Adobe and it was specifically targeted for Web developers. Dreamweaver offers many features including auto completion features, syntax highlighting and built-in code view. It was first developed in 1997 by Macromedia, and was maintained by them until

Macromedia was bought by Adobe Systems in 2005. Following this acquisition, releases of Dreamweaver subsequent to the 8.0 version have been more compliant with W3C

7 standards. Recent versions offer improved support for Web technologies like JavaScript,

CSS, and a multitude of server-side scripting languages and frameworks including ASP.

Dreamweaver provides a visual WYSIWYG editor referred to as the Design view and a code editor with sophisticated features such as real-time syntax checking and code introspection. The Design view provides rapid layout design and code generation as it helps users in creating and manipulating the layout of HTML elements. Dreamweaver features an integrated browser which allows users to preview developed pages in the program’s own preview page. is a proprietary application for which its users must pay a license fee.

2.2.2 Aptana

Aptana is an open-source web development tool that is available to all developers free of charge. Aptana Studio is an application tailored for building Ajax applications which also supports other web languages. Additional plugins allow Aptana Studio to support languages like Pearl, Python, PHP, and Ruby on Rails. Aptana Studio 3 provides improved support for PHP application development. In the 2.0 version, Aptana did not provide a PHP plugin, and it was merely transferring development efforts to the PDT project. In version 1.5, developing PHP applications was only possible via the add-on PHP plugin. Aptana Studio also offers Ruby on Rails development support using RadRails, an open source plugin for the Ruby on Rails framework. PyDev plugin is also available which provides support for Python development. Aptana IDE provides significant assistance for

Adobe AIR as well. The current version is Aptana Studio 3 which also supports HTML5.

8

2.3 CONTENT MANAGEMENT SYSTEMS

A content management system (CMS) is a computer application used for editing and modifying content, organizing, deleting, publishing as well as maintaining from a central interface. CMSs have been available on the market since late 1990s. There is a variety of content management systems available for a wide range of developers. A few popular content management systems are the following: Wordpress, Joomla, Drupal,

MODx, SilverStripe. Such systems of content management provide a multitude of procedures which help manage workflow in a collaborative environment. These procedures can be manual or automated. CMSs are usually utilized in running websites containing news, shopping, and blogs. They are used by many marketing and corporate websites.

Content management systems are typically aiming to avoid the necessity for hand coding, but do sometimes support it for entire pages or specific elements. Every good content management system needs to have the ability to work as a file editor and allow users to easily manage HTML contents of web pages.

9

CHAPTER 3

REQUIREMENT ANALYSIS AND PROTOTYPING

The main requirement of this graduate project is to have functionality and design similar to the popular tools presented in the previous section. This application allows users to view and edit files with a very simple and easy to handle user interface design. Following below a list of the features that this application is presented:

 The application allows users to locate and select files in directories. This can be

done by selecting the path of a directory and all its subdirectories. The files

belonging to the search directory and any subdirectory of that directory are

identified.

 The users can display files by their contents. This can be achieved by specifying

the directories to be searched in the ‘Open File’ menu. The files belonging to any

one of the directories in the search path will be listed.

 The application allows users to save the current document to a file and open a new

document.

 The application allows users to print the current document via a very complex print

wizard.

 Undo/Redo capabilities are defined for the user’s editing convenience.

 Copy/Paste/Cut capabilities are built in.

 The application allows user to ‘Select All’ and ‘Delete’.

10

 Bold, Italic and Underline buttons allow users to easily and conveniently apply

these commonly used styles to their documents.

 The application allows users to view and edit HTML files. The application also

allows the user to visually test HTML in rendered view. The user has also the option

of displaying the output directly to the default browser.

 The application allows users to debug and run JavaScript files. The output will be

displayed in a JFrame pop-up window. The user also has the option of seeing the

output displayed directly to the default browser.

 The application allows users to easily select font color from a drop down box

conveniently positioned on the tools bar.

 The application allows users to decrease and increase the font size of the displayed

file contents.

 The users can change the font of the displayed file. The application uses the system

fonts.

 The application allows users to edit, compile and run JAVA files.

11

CHAPTER 4

OVERVIEW AND TECHNOLOGY USED

4.1 UI ARCHITECTURE

For the creation of the UI and the design part of the application, the programming language used was Java, and its Swing library. Swing is part of Java Foundation Classes

(JFC). The Java Foundation Classes consist of major parts including Swing, Java 2D,

AWT, and Drag/Drop. Swing was built on top of AWT, Java 2D has become an integral part of AWT, and Accessibility support is built into Swing. There are five parts to JFC which are not mutually exclusive, and the Swing library is most likely to merge more deeply with AWT in future releases of Java. Presently, AWT is part of the core of JFC, and therefore it is one of the most important libraries in Java.

4.2 JAVA SWING LIBRARY

The Swing library was designed to deliver a multitude of features for large applications with complex user interface. Its capabilities are designed to benefit both the developers and the users. Swing is able to emulate several look and feel components and it supports the most popular operating systems including UNIX, Mac OS, and Windows. Mac

OS delivers full support for its own look and feel based on Apple's Aqua Human Interface

Guidelines. In addition, Swing gives the user the possibility to switch to different look and

12 feel flavors at runtime while the application is still running. In this way, the users are able to see which UI best suits their preferences and needs. Also, the developers can also create their own custom look and feel for each one of the Swing components.

4.3 IMPLEMENTATION

For the development, testing and deployment of this application, I have used Eclipse, which is one of the most popular Java development IDE’s. As any intricate application on the market Eclipse comes with a series of advantages and disadvantages for the developers.

Eclipse is considered to be not as fast and reliable as NetBeans but it provides better plug- ins and deployment features. There are many plug-ins available for the Eclipse IDE.

Eclipse began as a Smart Canada project. In 2001 a consortium was formed to further the development of Eclipse as open-source software.

The application is implemented as one large .java file comprising sixty six import statements, one main class called ImporvedTextEditor, eight helper classes and more than twenty event handling methods that provide the expected functionality. The user interface is constructed on top of a classic Swing library JFrame and it uses the Nimbus UI Manager which provides a significantly improved look and feel as shown in the following code snippet.

UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

13

Without using the Nimbus UI Manager, the application would have the classical

Swing look and feel which is less visually appealing as depicted in the figure bellow.

Figure 4.1. Classical look and feel.

Nimbus is a polished cross-platform look and feel introduced in the Java SE 6 Update

10 release. It uses Java 2D vector graphics to draw the user interface (UI), rather than static bitmaps, so the UI can be crisply rendered at any resolution. Nimbus is highly customizable. You can use the Nimbus look and feel as is, or you can skin (customize) the look with your own brand.

The layout manager used for this application is called GroupLayout. It hierarchically groups components in order to position them in a Container. GroupLayout was at first

14 intended for use by automatic code generators, but in recent years it has been adapted for hard-coding as well. The process of grouping can be attained by using instances of the

Group class. GroupLayout supports two types of groups. A sequential group positions its child elements sequentially, one after another. A parallel group aligns its child elements in one of four ways. Each group may contain any number of elements, where an element is a Group, Component, or gap. A gap can be thought of as an invisible component with a minimum, preferred and maximum size. In addition GroupLayout supports a preferred gap, whose value comes from LayoutStyle. Elements are similar to a spring. Each element has a range as specified by a minimum, preferred and maximum. The following code snippet shows how the exact Java implementation of GroupLAyout works.

GroupLayout PanelLayout = new GroupLayout(Panel);

Panel.setLayout(PanelLayout); PanelLayout.setHorizontalGroup( PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(GroupLayout.Alignment.TRAILING, PanelLayout.createSequentialGroup().addContainerGap()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false)

.addGroup(PanelLayout.createSequentialGroup().addComponent(FontStyleLabel).addGa p(108, 108, 108).addComponent(FontSizeLabel))

.addGroup(PanelLayout.createSequentialGroup().addComponent(FontStyleComboBox, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)

.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(Fo ntSizeComboBox, 0, 0, Short.MAX_VALUE))) .addGap(100, 100, 100)

15

The following figure is presenting the application’s class diagram which describes the overall structure of the project by showing the application’s classes, their attributes, operations, and the relationships among them.

Figure 4.2. Class diagram.

16

CHAPTER 5

FUNCTIONAL DETAILS

5.1 GENERAL LOOK AND FEEL

The general look and feel of this application was intended to be a very simple, intuitive and easy to use one as depicted by Figure 5.1 below. The theme used is called

Nimbus and is a professional theme that is getting a lot of popularity, especially after

Solaris 10 adopted it. As a comparison of look and feel quality, the classical Swing look and feel of the application is presented in the Figure 4.1 of the previous chapter.

Figure 5.1. General look and feel.

17

As mentioned in the previous section this application uses a custom look and feel UI

Manager called Nimbus. The following code snipped demonstrates the Java declaration and invocation of this polished cross-platform look and feel. It must be surrounded by a try-catch block since it can throw four different exceptions: ClassNotFoundException,

InstantiationException, IllegalAccessException and UnsupportedLookAndFeelException.

try { UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); }

The user interface was built with simplicity in mind containing only a menu bar and a tool bar as shown in Figure 5.1 above. The menu bar contains three menus, namely File,

Edit, and Run. The tool bar contains Font Style, Font Size, and Font Color in the form of drop down boxes, as well Bold, Italic, and Underline buttons for basic text formatting. The most important functionality of the application is provided via the three buttons (HTML,

Jscript, and JAVA) located on the right side of the tool bar. Informational buttons like

About and Help were also added.

18

5.2 GETTING STARTED WITH A NEW DOCUMENT

In this section, getting started with editing a new document is presented. It is achieved by simply accessing the ‘New’ submenu located in the ‘File’ menu as depicted in

Figure 5.2 below. ‘File’ menu is a classic Swing JMenu which sits on top of a JMenuBar.

private JMenu File;

File.setMnemonic('F');

File.setText("File ");

Figure 5.2. Getting started with a new document.

19

By selecting ‘New’ submenu under the ‘File’ menu, the user is ready to start editing a new document. The document could contain plain text or syntax code. The application is capable of rendering HTML markup either in its own window or directly in a browser. The users can also use this application to run JavaScript code and also to create and run JAVA programs.

New.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK)); New.setMnemonic('N'); New.setText("New"); New.setToolTipText("Create a new file"); New.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { NewActionPerformed(e); } }); File.add(New);

The code snippet above shows the Swing implementation of the ‘New’ submeniu.

It sets the accelerator to Ctrl+N, it adds the ‘N’ mnemonic and sets the text to ‘New’. A

‘Create a new file’ tool tip is added as well. The NewActionPerformed() event handler simply clears the editing area after the user has finished running code or has saved his/her text document.

5.3 OPENING AN EXISTING FILE

In this section, opening an existing file in a new document is presented. It is achieved by simply accessing the ‘Open File…’ submenu located in the ‘File’ menu as depicted in

20 the following three figures below. ‘Open File…’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘File’ as shown in the following code snippet.

private JMenuItem Open; Open = new JMenuItem(); Open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); Open.setText("Open File..."); Open.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { OpenActionPerformed(e);}});

The code snippet above shows the Swing implementation of the ‘Open File…’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+O, and sets the text to ‘Open File…’. The OpenActionPerformed() event handler simply creates a JFileChooser which provides a simple and easy way of accessing any file residing on disk. The implementation of OpenActionPerformed() event handler is depicted below.

JFileChooser fileChooser = new JFileChooser(); int returnValue = fileChooser.showOpenDialog(null); if (returnValue == JFileChooser.APPROVE_OPTION) { TextPane.setText(""); File file = fileChooser.getSelectedFile(); FileInputStream f_input = new FileInputStream(file); TextPane.setPage(file.toURI().toURL()); }

21

Figure 5.3.1 Opening an existing file.

Figure 5.3.2 Opening an existing file.

22

Figure 5.3.3 Opening an existing file.

5.4 SAVING A FILE

In this section, saving the current document to a file is presented. It is achieved by simply accessing the ‘Save File’ submenu located in the ‘File’ menu as depicted in the following two figures below. ‘Save File’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘File’ as shown in the following code snippet. private JMenuItem Save; Save = new JMenuItem(); Save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); Save.setMnemonic('S'); Save.setText("Save File"); Save.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SaveActionPerformed(e);}});

23

The code snippet above shows the Swing implementation of the ‘Save File’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+S, and sets the text to ‘Saven File’. The mnemonic is also set to ‘S’. The SaveActionPerformed() event handler simply creates a JFileChooser which provides a simple and easy way of accessing any file residing on disk. The implementation of SaveActionPerformed() event handler is depicted below.

JFileChooser fileChooser = new JFileChooser(); int returnValue = fileChooser.showSaveDialog(null); if( returnValue == JFileChooser.APPROVE_OPTION ){ File file = fileChooser.getSelectedFile(); FileOutputStream f_out=new FileOutputStream(file);}

Figure 5.4.1 Saving a file.

24

Figure 5.4.2 Saving a file.

5.5 UNDO EDITING

In this section, undoing the current editing state to the previous editing state of a document is presented. It is achieved by simply accessing the ‘Undo’ submenu located in the ‘Edit’ menu as depicted in the following figure. ‘Edit’ menu is a classic Swing JMenu which sits on top of a JMenuBar. ‘Undo’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘Edit’ as shown in the following code snippet. private JMenuItem Undo; Undo = new JMenuItem(); Undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK)); Undo.setText("Undo"); Undo.addActionListener(new ActionListener() {

25

public void actionPerformed(ActionEvent e) { UndoActionPerformed(e);}});

The code snippet above shows the Swing implementation of the ‘Undo’ submeniu.

It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+Z, and sets the text to ‘Undo’.

Figure 5.5 Undo editing.

5.6 REDO EDITING

In this section, redoing the current editing state to the previous editing state of a document is presented. It is achieved by simply accessing the ‘Redo’ submenu located in the ‘Edit’ menu as depicted in the following figure. ‘Edit’ menu is a classic Swing JMenu

26 which sits on top of a JMenuBar. ‘Redo’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘Edit’ as shown in the following code snippet. private JMenuItem Redo; Redo = new JMenuItem(); Redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK)); Redo.setText("Redo"); Edit.add(Redo);

The code snippet above shows the Swing implementation of the ‘Redo’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+Y, and sets the text to ‘Redo’.

Figure 5.6 Redo editing.

27

5.7 CUT TEXT

In this section, cutting all or only the selected portion of text in the current document is presented. It is achieved by simply accessing the ‘Cut’ submenu located in the ‘Edit’ menu as depicted in the following figure. ‘Edit’ menu is a classic Swing JMenu which sits on top of a JMenuBar. ‘Cut’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘Edit’ as shown in the following code snippet.

private JMenuItem Cut; Cut = new JMenuItem(); Cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK)); Cut.setText("Cut"); Cut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CutActionPerformed(e);}});

The code snippet above shows the Swing implementation of the ‘Cut’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+X, and sets the text to ‘Cut’. The CutActionPerformed() event handler simply makes a call to the TextPane method cut(). The implementation of CutActionPerformed() event handler is shown below.

private void CutActionPerformed(ActionEvent e) { TextPane.cut(); }

28

Figure 5.7 Cut text.

5.8 COPY TEXT

In this section, copying all or only the selected portion of text in the current document is presented. It is achieved by simply accessing the ‘Copy’ submenu located in the ‘Edit’ menu as depicted in the following figure. ‘Edit’ menu is a classic Swing JMenu which sits on top of a JMenuBar. ‘Copy’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘Edit’ as shown in the following code snippet.

Copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); Copy.setText("Copy"); Copy.addActionListener(new ActionListener() { 29

public void actionPerformed(ActionEvent e) { CopyActionPerformed(e);}}); Edit.add(Copy);

The code snippet above shows the Swing implementation of the ‘Copy’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+C, and sets the text to ‘Copy’. The CopyActionPerformed() event handler simply makes a call to the TextPane method copy(). The implementation of CopyActionPerformed() event handler is shown below.

private void CopyActionPerformed(ActionEvent e) { TextPane.copy(); }

Figure 5.8 Copy text.

30

5.9 PASTE TEXT

In this section, pasting copied text in the current document is presented. It is achieved by simply accessing the ‘Paste’ submenu located in the ‘Edit’ menu as depicted in the following figure. ‘Edit’ menu is a classic Swing JMenu which sits on top of a

JMenuBar. ‘Paste’ is a standard Swing library JMenuItem which sits on top of the JMenu

‘Edit’ as shown in the following code snippet.

private JMenuItem Paste; Paste = new JMenuItem(); Paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK)); Paste.setText("Paste"); Paste.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PasteActionPerformed(e);}});Edit.add(Paste);

The code snippet above shows the Swing implementation of the ‘Paste’ submeniu. It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+V, and sets the text to ‘Paste’. The PasteActionPerformed() event handler simply makes a call to the TextPane method paste(). The implementation of PasteActionPerformed() event handler is shown below.

private void PasteActionPerformed(ActionEvent e) { TextPane.paste(); }

31

Figure 5.9 Paste text.

5.10 DELETE TEXT

In this section, deleting text from the current document is presented. It is achieved by simply accessing the ‘Delete’ submenu located in the ‘Edit’ menu as depicted in the following two figures. ‘Edit’ menu is a classic Swing JMenu which sits on top of a

JMenuBar. ‘Delete’ is a standard Swing library JMenuItem which sits on top of the

JMenu ‘Edit’ as shown in the following code snippet. private JMenuItem Delete; Delete = new JMenuItem(); Delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK)); Delete.setText("Delete"); Delete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

32

DeleteActionPerformed(e);}}); Edit.add(Delete);

The code snippet above shows the Swing implementation of the ‘Delete’ submeniu.

It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+D, and sets the text to ‘Delete’. The DeleteActionPerformed() event handler simply makes a call to the

TextPane method replaceSelection(). The implementation of DeleteActionPerformed() event handler is shown below.

private void DeleteActionPerformed(ActionEvent e) { TextPane.replaceSelection(“”); }

Figure 5.10.1 Delete text.

33

Figure 5.10.2 Delete text.

5.11 SELECT ALL TEXT

In this section, selecting all text in the current document is presented. It is achieved by simply accessing the ‘Select All’ submenu located in the ‘Edit’ menu as depicted in the following figure. . ‘Edit’ menu is a classic Swing JMenu which sits on top of a JMenuBar.

‘Select All’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘Edit’ as shown in the following code snippet. private JMenuItem SelectAll; SelectAll = new JMenuItem(); SelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK)); SelectAll.setText("Select All"); SelectAll.addActionListener(new ActionListener() { 34 public void actionPerformed(ActionEvent e) { SelectAllActionPerformed(e);}}); Edit.add(SelectAll);

The code snippet above shows the Swing implementation of the ‘Select All’ submeniu.

It declares and instantiates the JMenuItem, it sets the accelerator to Ctrl+A, and sets the text to ‘Select All’. The SelectAllActionPerformed() event handler simply makes a call to the TextPane method selectAll(). The implementation of SelectAllActionPerformed() event handler is shown below.

private void SelectAllActionPerformed(ActionEvent e) { TextPane.selectAll(); }

Figure 5.11 Select all text.

35

5.12 BOLD, ITALIC, UDERLINE

In this section, the very popular Bold, Italic and Underline buttons are presented.

Just like in any popular text editor on the market they are conveniently located on the tool bar for easy access as depicted by the following figure. Every one of the three buttons are implemented as a Swing JToggleButton as shown in the following code snippet.

private JToggleButton Bold; private JToggleButton Italic; private JToggleButton Underline; Bold = new JToggleButton(); Italic = new JToggleButton(); Underline = new JToggleButton();

Figure 5.12 Bold, Italic, Underline.

36

5.13 FONT COLOR

In this section, the ‘Font Color’ drop-down box is presented. Just like in any popular text editor on the market it is conveniently located on the tool bar for easy access as depicted by the Figure 5.13 below. It includes the following available colors: black, blue, cyan, dark gray, gray, light gray, green, orange, magenta, pink, red, yellow, white.

FontColorComboBox.setModel(new DefaultComboBoxModel(new String[] { "black","blue","cyan","dark gray","gray","light gray", "green","orange","magenta","pink","red","yellow","white"})); FontColorComboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FontColorActionPerformed(e);}});

Figure 5.13 Font Color.

37

5.14 FONT STYLE

In this section, the ‘Font Style’ drop-down box is presented. Just like in any popular text editor on the market it is conveniently located on the tool bar for easy access as depicted by the Figure 5.14 below. It includes the following available font styles:

"", "Andalus", "Angsana New", "AngsanaUPC", "Aparajita", "Arabic

Typesetting", "", "Arial Black", "Arial Narrow", "Arial Unicode MS", "Batang",

"BatangChe", "Book Antiqua", "Bookman Old Style", "Bookshelf 7", "Browallia

New", "BrowalliaUPC", "", "", "Cambria Math", "", "Century",

"", " MS", "", "", "", "Cordia New",

"CordiaUPC", " New", "DaunPenh", "David", "DFKai-SB", "Dialog",

"DialogInput", "DilleniaUPC", "DokChampa", "", "DotumChe", "",

"Estrangelo Edessa", "EucrosiaUPC", "", "FangSong", "Franklin Gothic

Medium", "FrankRuehl", "FreesiaUPC", "", "Garamond", "", "",

"Gisha", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "", "IrisUPC",

"Iskoola Pota", "JasmineUPC", "KaiTi", "Kalinga", "Kartika", "Khmer UI",

"KodchiangUPC", "Kokila", "Lao UI", "Latha", "Leelawadee", "Levenim MT",

"LilyUPC", " Bright", "Lucida Console", "Lucida Sans", "Lucida Sans Typewriter",

"", "", "Mangal", "", "", "Meiryo UI",

"Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft

PhagsPa", "", "Microsoft Tai Le", "Microsoft Uighur", "Microsoft

YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU-ExtB", "MingLiU_HKSCS",

"MingLiU_HKSCS-ExtB", "Miriam", "Miriam Fixed", "Mongolian Baiti",

"Monospaced", "Monotype Corsiva", "MoolBoran", "MS Gothic", "MS Mincho", "MS

38

PGothic", "MS PMincho", "MS Reference Sans Serif", "MS Reference Specialty", "MS UI

Gothic", "MT Extra", "MV Boli", "Narkisim", "NSimSun", "", " Linotype",

"Plantagenet Cherokee", "PMingLiU", "PMingLiU-ExtB", "Raavi", "Rod", "Sakkal

Majalla", "SansSerif", " Print", "Segoe Script", "Segoe UI", "Segoe UI Light",

"Segoe UI Semibold", "Segoe UI Symbol", "Serif", "Shonar Bangla", "Shruti", "SimHei",

"Simplified Arabic", "Simplified Arabic Fixed", "SimSun", "SimSun-ExtB", "",

"Symbol", "", "", "Traditional Arabic", "Trebuchet MS",

"Tunga", "Utsaah", "Vani", "", "Vijaya", "Vrinda", "", "",

"Wingdings 2", "Wingdings 3".

Figure 5.14 Font Style.

39

5.15 FONT SIZE

In this section, the “Font Size” drop-down box is presented. Just like in any popular text editor on the market it is conveniently located on the tool bar for easy access as depicted by the Figure 5.15 below. It includes the following available sizes: 8, 9, 10, 11,

12, 14, 16, 18, 20, 24, 30, 36, 48, 54, 72.

FontSizeComboBox.setModel(new DefaultComboBoxModel(new String[] { "8", "9", "10", "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "54", "72" })); FontSizeComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { FontSizeActionPerformed(e); } });

Figure 5.15 Font Size.

40

5.16 RENDERING HTML

Another feature of this tool is to render html documents as shown in the five figures below. The JEditorPane component of the Swing library supports this feature. There are two Swing classes that support styled text: JEditorPane and its subclass JTextPane. The

JEditorPane class is the foundation for Swing's styled text components and provides a mechanism which allows for custom text formats.

As depicted by the figures below the tool works in a very simple and intuitive way.

Firstly the user needs to write the HTML that needs to be rendered. Next the user has two options: render the HTML in a pop-up window or directly to the default browser.

Figure 5.16.1 Rendering HTML.

41

If the user chooses to press the “HTML” button on the tool bar of the application a separate pop-up window will appear as shown in the picture bellow. Code is automatically transferred from the main window to the child window where the user is still able to perform changes if needed. When ready to render the user will press the “RenderHTML” button and the HTML will be displayed by the JEditorPane on the right.

Figure 5.16.2 Rendering HTML. public class HtmlRenderer extends JPanel implements ActionListener{ JEditorPane theLabel; JTextArea htmlTextArea; public HtmlRenderer() { setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); TextPane.selectAll(); String initialText = TextPane.getSelectedText(); htmlTextArea = new JTextArea(20, 32); htmlTextArea.setText(initialText); JScrollPane scrollPane = new JScrollPane(htmlTextArea); JButton runHTML = new JButton("RenderHTML");

42

Figure 5.16.3 Rendering HTML.

If the user decides to display the HTML directly in the default browser he/she can do so by choosing the “HTML in Browser” menu item found under the “Run” menu as shown in the following two figures below. The default browser set for the particular system will automatically launch and render the HTML code edited by the user as shown in the following picture.

private void HtmlInBrowserActionPerformed(ActionEvent e) { FileWriter fw = null; TextPane.selectAll(); String str = TextPane.getSelectedText(); if(str != null){ try { file = new File("C:\\Users\\Marian\\Desktop\\Test.html"); fw = new FileWriter(file); fw.write(str); fw.close(); }catch (IOException iox) {iox.printStackTrace(); } 43

Figure 5.16.4 Rendering HTML.

Figure 5.16.5 Rendering HTML.

44

5.17 RUNNING JAVASCRIPT

The application also allows users to run JavaScript files as depicted in the following five figures below. Firstly the user needs to write the JavaScript code that needs to be run.

Next the user has two options: run the JavaScript in a pop-up window or directly in the default browser.

Figure 5.17.1 Running JavaScript.

If the user chooses to press the “JScript” button on the tool bar of the application a separate pop-up window will appear as shown in the figure bellow. Code is automatically transferred from the main window to the child window where the user is still able to perform changes if needed. When ready to run the user will press the “RunJS” button and the JavaScript will be displayed by the JEditorPane on the right.

45

Figure 5.17.2 Running JavaScript.

Figure 5.17.3 Running JavaScript.

46

If the user decides to display the JavaScript directly in the default browser he/she can do so by choosing the “JScript in Browser” menu item found under the “Run” menu as shown in the following two figures below. The default browser set for the particular system will automatically launch and render the JavaScript code edited by the user as shown in the figure below.

public class JavaScriptRunWindow extends JPanel implements ActionListener { JEditorPane theLabel; JTextArea javaScriptTextArea;

public JavaScriptRunWindow() { // TODO Auto-generated constructor stub setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

TextPane.selectAll(); String initialText = TextPane.getSelectedText();

javaScriptTextArea = new JTextArea(20, 32); javaScriptTextArea.setText(initialText); JScrollPane scrollPane = new JScrollPane(javaScriptTextArea);

JButton runJS = new JButton("RunJS"); //runJS.setMnemonic(KeyEvent.VK_R); runJS.setAlignmentX(Component.CENTER_ALIGNMENT); runJS.addActionListener(this);

theLabel = new JEditorPane(); theLabel.setPreferredSize(new Dimension(400, 300)); theLabel.setContentType("text/plain");

47

Figure 5.17.4 Running JavaScript.

Figure 5.17.5 Running JavaScript.

48

5.18 RUNNING JAVA

The application is also capable of compiling and running JAVA code as depicted in the following five snapshots. Firstly the user needs to write the JAVA code that needs to be compiled and run. Next the user has two options: run the JAVA code by pressing the

‘JAVA’ button conveniently located on the tool bar, or by selecting the ‘Run JAVA code’ submenu under the ‘Run’ menu. Next a pop-up window will appear which is composed of two sides. On the left the code is copied over automatically and on the right all the console output gets displayed.

Figure 5.18.1 Running JAVA code.

49

Figure 5.18.2 Running JAVA code.

In order for the application to work the user needs to type the name of the main class in the JTextField located at the top of the left window. The compilation part is performed via a JavaCompiler compiler which performs similar functions as the ‘javac’ command in

MS-DOS. The code snippet bellow demonstrated how the compiler is invoked and instantiated.

JavaCompiler compiler; if (compiler==null) {

compiler = ToolProvider.getSystemJavaCompiler();

}

50

Figure 5.18.3 Running JAVA code.

Running the compiled classes is achieved by the void method called ‘runIt()’. It instantiates a process which in turn simulates the MS-DOS ‘java’ command. The structure of the above mentioned method is shown in the code snippet that follows.

public void runIt() throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec("java.exe " + name.getText()); p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = ""; while ((line = reader.readLine())!= null){ printStream.append(line + "\n");} }

51

Figure 5.18.4 Running JAVA code.

Upon compilation the output is displayed in the window on the right side for programs that yield console type output or a new window will appear for GUI programs as demonstrated by the figure below. The figure shows the output of a graphical JAVA program.

setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); TextPane.selectAll(); String initialText = TextPane.getSelectedText(); name = new JTextField(15); name.setToolTipText("Name of the public class"); javaTextArea = new JTextArea(20, 32); javaTextArea.setText(initialText);

JScrollPane scrollPane = new JScrollPane(javaTextArea); runJAVAbutton = new JButton("RunJAVA");

52

runJAVAbutton.addActionListener(this); theOutput = new JTextArea(20,33); theOutput.setEditable(false);

Figure 5.18.5 Running JAVA code.

5.19 HELP

In this section, the very popular Help button is presented. Just like in any popular text editor on the market it is conveniently located on the tool bar for easy access as depicted by the following figure. The ‘Help’ button is implemented as a standard Swing

JButton as shown in the following code snippet.

53

private JButton Help; Help = new JButton(); Help.setText(" Help "); Help.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { HelpButtonActionPerformed(e);}});

Figure 5.19 Help.

5.20 ABOUT

In this section, the very commonly encountered ‘About’ button is presented. Just

like in any popular text editor on the market it is conveniently located on the tool bar for

54 easy access as depicted by the following figure. The ‘About’ button is implemented as a standard Swing JButton as shown in the following code snippet.

private JButton About; About = new JButton(); About.setText(" About "); About.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { AboutButtonActionPerformed(e);}});

Figure 5.20 About.

55

5.21 PRINTING

In this section, printing the current document is presented. It is achieved by simply accessing the ‘Print’ submenu located in the ‘File’ menu as depicted in the following figure.

‘Print’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘File’ as shown in the following code snippet. private JMenuItem Print; Print = new JMenuItem(); Print.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK)); Print.setText("Print"); Print.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PrintActionPerformed(e); }}); File.add(Print); File.addSeparator();

Figure 5.21 Printing.

56

5.22 QUIT

In this section, quitting the application is presented. It is achieved by simply accessing the ‘Quit’ submenu located in the ‘File’ menu as depicted in the following figure.

‘Quit’ is a standard Swing library JMenuItem which sits on top of the JMenu ‘File’ as shown in the following code snippet. private JMenuItem Quit; Quit = new JMenuItem(); Quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK)); Quit.setMnemonic('Q'); Quit.setText("Quit"); Quit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { QuitActionPerformed(e);}}); File.add(Quit);

Figure 5.22 Quit.

57

CONCLUSION

The work presented in this project is to enhance the accessibility, functionality and the user experience of file editing tools. The integrated user interface that combines simplicity with user friendliness creates a better user experience while specific file editing functionalities allow users to work on different types of files. On the other hand, using Java and its Java Web Start Framework allows users to launch the application without going through complicated downloading steps. This project consists of two parts; this part of the thesis mainly provides a description of the improved user interface of the tool that allows users to display and edit multiple files and folders. The second part is represented by the physical Java implementation of the application.

58

FUTURE ENHANCEMENTS

There are many future enhancements that can be done for every software product available today. This graduate project takes advantage of many existing Java technologies.

The integrated development environment (IDE) I have used is Eclipse. Future works may include using new Java technologies, plug-ins or other useful tools. Some future works may include the following:

 File difference functionality: This feature allows users to make comparisons

of two files. The differences will be highlighted.

 Tabbed window for displaying multiple files: It allows the user to open

multiple text files at once in tabs and edit accordingly.

 Support for other file formats: The application currently supports JavaScript

and Html. One future goal is to add support for additional file formats,

including PDF and other scripting languages.

 Clipboard feature: Each time the user copies or cuts text, the text is copied

into the buffer. In a list of all previous clippings users can pick the one they

want to use.

 Internationalization: Globalizing the application by adapting different

languages and technical requirements to reach more users. Providing support

to new users in their language and cultural conventions will simply increase

the popularity of the application.

59

BIBLIOGRAPHY

[1] C. A. FINSETH, The Craft of Text Editing -or- A Cookbook for an Emacs, Springer- Verlag & Co, Berlin, 1991.

[2] M. DUBASH, Moore's Law is dead, says Gordon Moore. Techworld, http://news.techworld.com/operating-systems/3477/moores-law-is-dead-says-gordon- moore/, accessed April 2013, 2005.

[3] A. REDD, SourceForge.net: Project statistics for notepad++. SourceForge, http://www.sourceforge.net, accessed March 2013, 2011.

[4] D. HANSON, TextMate 1.0 is finally here! TextMate Blog, http://blog.macromates.com/, accessed March 2013, 2004.

[5] C. ROGER, One-window web development. Softonic International S. L., http://coda.en.softonic.com/mac, accessed March 2013, 2013.

[6] J. FIALA, PSPad editor, publisher’s description. CNET, http://www.cnet.com, accessed March 2013, 2011.

[7] J. DEAN, Getting started with textpad. Park University, http://www.park.edu/ics/tutorialsAndGuidelines/textPadTutorial.doc, accessed March 2013, 2011.

[8] M. ROBINSON and P. VOROBIEV, Swing Second Edition, Manning Publications, Shelter Island, New York, 2003.

[9] Y. M. KIM, Java web start (jnlp) tutorial. Oracle, http://www.oracle.com/technetwork/java/index-140688.html, accessed March 2013, 2010.

[10] UNIVERSITY OF CALIFORNIA BERKELEY, Recommended eclipse plug-ins. IST UC Berkeley, http://ist.berkeley.edu/as-ag/tools/howto/eclipse-plugins.html, accessed March 2013, 2007.

[11] Y. M. KIM, How to use editor panes and text panes. The Java Tutorials, http://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html, accessed March 2013, 2008.

[12] ORACLE, Oracle Java SE documentation. Oracle, http://docs.oracle.com/javase/, accessed March 2013, 2011.

[13] IBM, Globalize your business. IBM Globalization, http://www- 01.ibm.com/software/globalization/, accessed March 2013, 2012.

60

APPENDIX A

IMPLEMENTATION CODE

/****************************** * Improved Text Editor * * MARIAN NEAGOIE * * California State University * * Northridge * * Final Thesis/Project * *******************************/

import java.awt.Color; import java.awt.Component; import java.awt.Desktop; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultComboBoxModel; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComboBox;

61 import javax.swing.JEditorPane; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextPane; import javax.swing.JToggleButton; import javax.swing.KeyStroke; import javax.swing.LayoutStyle; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.WindowConstants; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.StyledEditorKit; import javax.swing.text.rtf.RTFEditorKit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager;

public class ImprovedTextEditor extends JFrame { RTFEditorKit rtf_kit = new RTFEditorKit(); UndoManager undo = new UndoManager(); UndoAction undoAction = new UndoAction(); RedoAction redoAction = new RedoAction();

String[] _fontSize = {"8","9","10","11","12","14","16","18","20","24","30","36","48","54","72"}; String[] _fontColor = {"black", "blue", "cyan", "dark gray", "gray", "light gray", "green", "orange", "magenta", "pink", "red", "yellow", "white" }; String[] _fontStyle = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

static File file; private JPanel Panel; private JLabel FontSizeLabel; private JLabel FontColorLabel; private JLabel FontStyleLabel;

62

private JButton Html; private JButton Jscript; private JButton Help; private JButton About; private JToggleButton Bold; private JToggleButton Italic; private JToggleButton Underline; private JComboBox FontSizeComboBox; private JComboBox FontColorComboBox; private JComboBox FontStyleComboBox; private JTextPane TextPane; private JScrollPane ScrollPane; private JMenuBar MenuBar; private JMenu File; private JMenuItem New; private JMenuItem Open; private JMenuItem Save; private JMenuItem Print; private JMenuItem Quit; private JMenu Edit; private JMenuItem Undo; private JMenuItem Redo; private JMenuItem Cut; private JMenuItem Copy; private JMenuItem Paste; private JMenuItem Delete; private JMenuItem SelectAll; private JMenu Run; private JMenuItem HtmlInBrowser; private JMenuItem JavaScriptInBrowser;

public ImprovedTextEditor() { initialize_components(); TextPane.setEditorKit(rtf_kit); set_Bold_Italic_Underline_Actions(); Undo.setAction(undoAction); Undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK)); Undo.setText("Undo"); Redo.setAction(redoAction); Redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK)); Redo.setText("Redo"); //this.setLocation(200,50);

63

//this.setSize(700, 500); this.setLocationRelativeTo(null); TextPane.getDocument().addUndoableEditListener(undo); } private void initialize_components() {

Panel = new JPanel(); FontSizeLabel = new JLabel(); FontColorLabel = new JLabel(); FontStyleLabel = new JLabel(); Html = new JButton(); Jscript = new JButton(); Help = new JButton(); About = new JButton(); Bold = new JToggleButton(); Italic = new JToggleButton(); Underline = new JToggleButton(); FontSizeComboBox = new JComboBox(); FontColorComboBox = new JComboBox(); FontStyleComboBox = new JComboBox(); TextPane = new JTextPane(); ScrollPane = new JScrollPane(); MenuBar = new JMenuBar(); File = new JMenu(); New = new JMenuItem(); Open = new JMenuItem(); Save = new JMenuItem(); Print = new JMenuItem(); Quit = new JMenuItem(); Edit = new JMenu(); Undo = new JMenuItem(); Redo = new JMenuItem(); Cut = new JMenuItem(); Copy = new JMenuItem(); Paste = new JMenuItem(); Delete = new JMenuItem(); SelectAll = new JMenuItem(); Run = new JMenu(); HtmlInBrowser = new JMenuItem(); JavaScriptInBrowser = new JMenuItem();

setTitle("Marian's Improved Text Editor"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

64

Html.setText(" HTML "); Html.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) {

HtmlActionPerformed(e);

}

});

Jscript.setText("JScript"); Jscript.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { JscriptActionPerformed(e);

}

});

Bold.setText("B"); //Bold.setFont(new Font("", Font.BOLD, 13)); Bold.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { BoldActionPerformed(e);

}

});

Italic.setText("I"); //Italic.setFont(new Font("", Font.ITALIC, 13)); Italic.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { ItalicActionPerformed(e);

}});

65

Underline.setText("U"); Underline.setMnemonic(KeyEvent.VK_U); //Underline.setFont(new Font("", Font.TRUETYPE_FONT, 13)); Underline.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { UnderlineActionPerformed(e);

}

});

FontStyleComboBox.setModel(new DefaultComboBoxModel(new String[] {

"Aharoni", "Andalus", "Angsana New", "AngsanaUPC", "Aparajita", "Arabic Typesetting", "Arial", "Arial Black", "Arial Narrow", "Arial Unicode MS", "Batang", "BatangChe", "Book Antiqua", "Bookman Old Style", "Bookshelf Symbol 7", "Browallia New", "BrowalliaUPC", "Calibri", "Cambria", "Cambria Math", "Candara", "Century", "Century Gothic", "Comic Sans MS", "Consolas", "Constantia", "Corbel", "Cordia New", "CordiaUPC", "Courier New", "DaunPenh", "David", "DFKai-SB", "Dialog", "DialogInput", "DilleniaUPC", "DokChampa", "Dotum", "DotumChe", "Ebrima", "Estrangelo Edessa", "EucrosiaUPC", "Euphemia", "FangSong", "Franklin Gothic Medium", "FrankRuehl", "FreesiaUPC", "Gabriola", "Garamond", "Gautami", "Georgia", "Gisha", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "Impact", "IrisUPC", "Iskoola Pota", "JasmineUPC", "KaiTi", "Kalinga", "Kartika", "Khmer UI", "KodchiangUPC", "Kokila", "Lao UI", "Latha", "Leelawadee", "Levenim MT", "LilyUPC", "Lucida Bright", "Lucida Console", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode", "Malgun Gothic", "Mangal", "Marlett", "Meiryo", "Meiryo UI", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Sans Serif", "Microsoft Tai Le", "Microsoft Uighur", "Microsoft YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU-ExtB", "MingLiU_HKSCS", "MingLiU_HKSCS-ExtB", "Miriam", "Miriam Fixed", "Mongolian Baiti", "Monospaced", "Monotype Corsiva", "MoolBoran", "MS Gothic", "MS Mincho", "MS PGothic", "MS PMincho", "MS Reference Sans Serif", "MS Reference Specialty",

66

"MS UI Gothic", "MT Extra", "MV Boli", "Narkisim", "NSimSun", "Nyala", "Palatino Linotype", "Plantagenet Cherokee", "PMingLiU", "PMingLiU-ExtB", "Raavi", "Rod", "Sakkal Majalla", "SansSerif", "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Symbol", "Serif", "Shonar Bangla", "Shruti", "SimHei", "Simplified Arabic", "Simplified Arabic Fixed", "SimSun", "SimSun-ExtB", "Sylfaen", "Symbol", "Tahoma", "Times New Roman", "Traditional Arabic", "Trebuchet MS", "Tunga", "Utsaah", "Vani", "Verdana", "Vijaya", "Vrinda", "Webdings", "Wingdings", "Wingdings 2", "Wingdings 3" }));

FontStyleComboBox.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { FontStyleActionPerformed(e);

} });

FontSizeComboBox.setModel(new DefaultComboBoxModel(new String[] {

"8", "9", "10", "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "54", "72"

}));

FontSizeComboBox.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { FontSizeActionPerformed(e);

} });

FontColorComboBox.setModel(new DefaultComboBoxModel(new String[] {

"black","blue","cyan","dark gray","gray","light gray", "green","orange","magenta","pink","red","yellow","white"

}));

67

FontColorComboBox.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { FontColorActionPerformed(e);

} });

FontSizeLabel.setText("Font Size"); FontStyleLabel.setText(" Font Style"); FontColorLabel.setText("Font Color");

Help.setText(" Help "); Help.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { HelpButtonActionPerformed(e);

} });

About.setText(" About "); About.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) { AboutButtonActionPerformed(e);

} });

GroupLayout PanelLayout = new GroupLayout(Panel);

Panel.setLayout(PanelLayout); PanelLayout.setHorizontalGroup( PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(GroupLayout.Alignment.TRAILING, PanelLayout.createSequentialGroup().addContainerGap()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false)

.addGroup(PanelLayout.createSequentialGroup().addComponent(FontStyleLabel).addGa p(108, 108, 108).addComponent(FontSizeLabel))

68

.addGroup(PanelLayout.createSequentialGroup().addComponent(FontStyleComboBox, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)

.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(Fo ntSizeComboBox, 0, 0, Short.MAX_VALUE))) .addGap(100, 100, 100) .addGroup(PanelLayout.createSequentialGroup()

.addComponent(Bold).addPreferredGap(LayoutStyle.ComponentPlacement.REL ATED)

.addComponent(Italic).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(Underline).addGap(100, 100, 100))

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addC omponent(FontColorLabel) .addComponent(FontColorComboBox, GroupLayout.PREFERRED_SIZE, 93, GroupLayout.PREFERRED_SIZE)).addGap(236, 236, 236)

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addC omponent(Html).addComponent(Jscript)).addGap(36, 36, 36)

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addC omponent(About).addComponent(Help)).addGap(16, 16, 16)) ); PanelLayout.setVerticalGroup( PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(PanelLayout.createSequentialGroup()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addGroup(PanelLayout.createSequentialGroup().addContainerGap().addComponent(Hel p).addGap(6, 6, 6).addComponent(About)) .addGroup(PanelLayout.createSequentialGroup().addContainerGap()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addGroup(PanelLayout.createSequentialGroup().addComponent(Html).addGap(6, 6, 6).addComponent(Jscript)) .addGroup(PanelLayout.createSequentialGroup().addContainerGap()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)

.addGroup(PanelLayout.createSequentialGroup().addComponent(FontColorLabel)

69

.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(FontColorComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addGroup(PanelLayout.createSequentialGroup()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).add Component(FontSizeLabel).addComponent(FontStyleLabel)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(FontStyleComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(FontSizeComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(Bold, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE) .addComponent(Italic, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE) .addComponent(Underline, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE) )))) .addGroup(PanelLayout.createSequentialGroup().addContainerGap()

.addGroup(PanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)))) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))));

ScrollPane.setViewportView(TextPane);

File.setMnemonic('F'); File.setText("File ");

New.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK)); New.setMnemonic('N'); New.setText("New"); New.setToolTipText("Create a new file"); New.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { NewActionPerformed(e); } });

70

File.add(New); File.addSeparator();

Open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); Open.setText("Open File..."); Open.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { OpenActionPerformed(e); } }); File.add(Open); File.addSeparator();

Save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); Save.setMnemonic('S'); Save.setText("Save File"); Save.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SaveActionPerformed(e); } }); File.add(Save); File.addSeparator();

Print.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_MASK)); Print.setText("Print"); Print.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PrintActionPerformed(e); } }); File.add(Print); File.addSeparator();

Quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK)); Quit.setMnemonic('Q'); Quit.setText("Quit"); Quit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { QuitActionPerformed(e); } });

71

File.add(Quit);

MenuBar.add(File);

Edit.setMnemonic('E'); Edit.setText("Edit ");

Undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK)); Undo.setText("Undo"); Undo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { UndoActionPerformed(e); } }); Edit.add(Undo); Edit.addSeparator();

Redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK)); Redo.setText("Redo"); Edit.add(Redo); Edit.addSeparator();

Cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK)); Cut.setText("Cut"); Cut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CutActionPerformed(e); } }); Edit.add(Cut); Edit.addSeparator();

Copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); Copy.setText("Copy"); Copy.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CopyActionPerformed(e); } }); Edit.add(Copy); Edit.addSeparator();

72

Paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK)); Paste.setText("Paste"); Paste.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PasteActionPerformed(e); } }); Edit.add(Paste); Edit.addSeparator();

Delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK)); Delete.setText("Delete"); Delete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DeleteActionPerformed(e); } }); Edit.add(Delete); Edit.addSeparator();

SelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK)); SelectAll.setText("Select All"); SelectAll.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SelectAllActionPerformed(e); } }); Edit.add(SelectAll); MenuBar.add(Edit);

Run.setMnemonic('R'); Run.setText("Run ");

HtmlInBrowser.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_MASK)); HtmlInBrowser.setText("HTML in Browser"); HtmlInBrowser.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub HtmlInBrowserActionPerformed(e); } });

73

Run.add(HtmlInBrowser); Run.addSeparator(); //MenuBar.add(Run);

JavaScriptInBrowser.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J, InputEvent.CTRL_MASK)); JavaScriptInBrowser.setText("JScript in Browser"); JavaScriptInBrowser.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub JavaScriptInBrowserActionPerformed(e); } }); Run.add(JavaScriptInBrowser); //Run.addSeparator(); MenuBar.add(Run);

setJMenuBar(MenuBar);

GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout);

layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(Panel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup().addGap(10, 10, 10) .addComponent(ScrollPane, GroupLayout.DEFAULT_SIZE, 938, Short.MAX_VALUE).addGap(15, 15, 15)) );

layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(Panel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(ScrollPane, GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE).addContainerGap()) );

pack(); }

private void set_Bold_Italic_Underline_Actions(){

74

Action boldAction = new StyledEditorKit.BoldAction(); Bold.setAction(boldAction); Bold.setText("B"); Bold.setFont(new Font("", Font.BOLD, 14));

Action underlineAction=new StyledEditorKit.UnderlineAction(); Underline.setAction(underlineAction); Underline.setText("U"); Underline.setFont(new Font("", Font.TRUETYPE_FONT, 14)); Underline.setMnemonic(KeyEvent.VK_U);

Action italicAction = new StyledEditorKit.ItalicAction(); Italic.setAction(italicAction); Italic.setText("I "); Italic.setFont(new Font("Serif", Font.ITALIC, 15)); }

private void SaveActionPerformed(ActionEvent e) { try{ JFileChooser fileChooser = new JFileChooser(); int returnValue = fileChooser.showSaveDialog(null); if( returnValue == JFileChooser.APPROVE_OPTION ) { File file = fileChooser.getSelectedFile(); //OutputStream out = new FileOutputStream(file); FileOutputStream f_out=new FileOutputStream(file); rtf_kit.write(f_out,TextPane.getDocument(),0,TextPane.getDocument().getLength()); }

}catch(Exception e2){ System.out.println(e); }}

private void OpenActionPerformed(ActionEvent e) { try{ JFileChooser fileChooser = new JFileChooser(); int returnValue = fileChooser.showOpenDialog(null); if (returnValue == JFileChooser.APPROVE_OPTION) { TextPane.setText(""); File file = fileChooser.getSelectedFile(); FileInputStream f_input = new FileInputStream(file);

75

//rtf_kit.read(f_input,TextPane.getDocument(),0); //this.setTitle(file.getName() + "Marian's Improved Text Editor"); TextPane.setPage(file.toURI().toURL()); }

}catch(Exception e2){ System.out.println(e); } } private void CutActionPerformed(ActionEvent e) { TextPane.cut(); }

private void CopyActionPerformed(ActionEvent e) { TextPane.copy(); }

private void PasteActionPerformed(ActionEvent e) { TextPane.paste(); }

private void SelectAllActionPerformed(ActionEvent e) { TextPane.selectAll(); }

private void PrintActionPerformed(ActionEvent e) { try{ TextPane.print();

}catch(Exception e2){ System.out.println(); } }

private void DeleteActionPerformed(ActionEvent e) { TextPane.replaceSelection("");

//TextPane.setText(TextPane.getText().replace(TextPane.getSelectedText(),""));}

76

private void QuitActionPerformed(ActionEvent e) { this.setVisible(false); this.dispose(); //System.exit(0); }

private void NewActionPerformed(ActionEvent e) { TextPane.setText(null);

//new ImprovedTextEditor().setVisible(true); //this.setVisible(false); //this.dispose(); }

private void FontStyleActionPerformed(ActionEvent e) { for(int i = 0; i <_fontStyle.length; i++) { if(_fontStyle[FontStyleComboBox.getSelectedIndex()].equals(_fontStyle[i])) { //System.out.println("Done"); Action action = new StyledEditorKit.FontFamilyAction(_fontStyle[i], _fontStyle[i]); action.actionPerformed(null); //FontSize.setAction(new StyledEditorKit.FontSizeAction(size,value)); break; } } }

private void FontSizeActionPerformed(ActionEvent e) { for(int i = 0; i < _fontSize.length; i++) { if(_fontSize[FontSizeComboBox.getSelectedIndex()].equals(_fontSize[i])) { //System.out.println("Done"); String size = _fontSize[i]; int value = Integer.valueOf(_fontSize[i]); Action action = new StyledEditorKit.FontSizeAction(size,value); action.actionPerformed(null); //FontSize.setAction(new StyledEditorKit.FontSizeAction(size,value)); break;

77

}}}

private void FontColorActionPerformed(ActionEvent e) { if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("back")) { Action action = new StyledEditorKit.ForegroundAction("black", Color.black); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("blue")) { Action action = new StyledEditorKit.ForegroundAction("blue", Color.blue); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("cyan")) { Action action = new StyledEditorKit.ForegroundAction("cyan", Color.cyan); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("dark gray")) { Action action = new StyledEditorKit.ForegroundAction("dark gray", Color.darkGray); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("gray")) { Action action = new StyledEditorKit.ForegroundAction("gray", Color.gray); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("light gray")) { Action action = new StyledEditorKit.ForegroundAction("light gray", Color.lightGray); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("green")) { Action action = new StyledEditorKit.ForegroundAction("green", Color.green);

78

action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("orange")) { Action action = new StyledEditorKit.ForegroundAction("orange", Color.orange); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("magenta")) { Action action = new StyledEditorKit.ForegroundAction("magenta", Color.magenta); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("pink")) { Action action = new StyledEditorKit.ForegroundAction("pink", Color.pink); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("red")) { Action action = new StyledEditorKit.ForegroundAction("red",Color.red); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("yellow")) { Action action = new StyledEditorKit.ForegroundAction("yellow", Color.yellow); action.actionPerformed(null); } else if(_fontColor[FontColorComboBox.getSelectedIndex()].equals("white")) { Action action = new StyledEditorKit.ForegroundAction("white", Color.white); action.actionPerformed(null); } }

private void UndoActionPerformed(ActionEvent e) { }

//********************************************************************

79

class UndoAction extends AbstractAction { public UndoAction() { super("Undo"); setEnabled(true); }

public void actionPerformed(ActionEvent e) { try{ undo.undo();

}catch(CannotUndoException exc){ System.out.println("Unable to Undo"+ exc); exc.printStackTrace(); } updateUndoState(); redoAction.updateRedoState();

}

protected void updateUndoState() { putValue(Action.NAME,undo.getUndoPresentationName()); } }

//********************************************************************

class RedoAction extends AbstractAction { public RedoAction() { super("Redo"); setEnabled(true); }

public void actionPerformed(ActionEvent e) { try{ undo.redo(); }catch(CannotRedoException exc) { System.out.println("Unable to Redo"+ exc); exc.printStackTrace();

80

}

undoAction.updateUndoState(); updateRedoState(); }

protected void updateRedoState() { putValue(Action.NAME,undo.getRedoPresentationName()); } }

//********************************************************************

protected class UndoListener implements UndoableEditListener { public void undoableEditHappened(UndoableEditEvent e) { undo.addEdit(e.getEdit()); undoAction.updateUndoState(); redoAction.updateRedoState(); } }

//********************************************************************

public static void main(String args[]) { EventQueue.invokeLater(new Runnable() { public void run() { try {

UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); } new ImprovedTextEditor().setVisible(true);

} });}

//*********************************************************************

private void HtmlActionPerformed(ActionEvent e)

81

{ new HtmlRenderer().createGUI(); } private void HtmlInBrowserActionPerformed(ActionEvent e) { FileWriter fw = null; TextPane.selectAll(); String str = TextPane.getSelectedText(); if(str != null) { try { //System.out.println(str); file = new File("C:\\Users\\Marian\\Desktop\\Test.html"); fw = new FileWriter(file); //System.out.print(file.getPath()); fw.write(str); fw.close(); }catch (IOException iox) { //do stuff with exception iox.printStackTrace(); }

if(Desktop.isDesktopSupported()) { try{ if(file.exists()) Desktop.getDesktop().browse(file.toURI()); }catch (IOException exc) { // TODO Auto-generated catch block exc.printStackTrace(); }}}} private void JscriptActionPerformed(ActionEvent e) {new JavaScriptRunWindow().createGUI();} private void JavaScriptInBrowserActionPerformed(ActionEvent e){ FileWriter fw = null; TextPane.selectAll(); String str = TextPane.getSelectedText(); if(str != null) { try { //System.out.println(str); file = new File("C:\\Users\\Marian\\Desktop\\Test.html"); fw = new FileWriter(file);

82

//System.out.print(file.getPath()); fw.write(str); fw.close(); }catch (IOException iox) { //do stuff with exception iox.printStackTrace(); }

if(Desktop.isDesktopSupported()) { try{ if(file.exists()) Desktop.getDesktop().browse(file.toURI()); }catch (IOException exc) { // TODO Auto-generated catch block exc.printStackTrace(); }}}}

private void BoldActionPerformed(ActionEvent e){}

private void ItalicActionPerformed(ActionEvent e) {}

private void UnderlineActionPerformed(ActionEvent e) {}

private void HelpButtonActionPerformed(ActionEvent e) {}

private void AboutButtonActionPerformed(ActionEvent e) {}

//**********************************************************************

public class HtmlRenderer extends JPanel implements ActionListener{ JEditorPane theLabel; JTextArea htmlTextArea;

public HtmlRenderer() { setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

TextPane.selectAll(); String initialText = TextPane.getSelectedText();

htmlTextArea = new JTextArea(20, 32); htmlTextArea.setText(initialText); JScrollPane scrollPane = new JScrollPane(htmlTextArea);

JButton runHTML = new JButton("RenderHTML");

83

//runHTML.setMnemonic(KeyEvent.VK_R); runHTML.setAlignmentX(Component.CENTER_ALIGNMENT); runHTML.addActionListener(this);

theLabel = new JEditorPane();

theLabel.setPreferredSize(new Dimension(400, 300)); //theLabel.setSize(200, 320); theLabel.setContentType("text/html");

JPanel leftPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); leftPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder( "HTML Edit"), BorderFactory.createEmptyBorder(10,10,10,10))); leftPanel.add(scrollPane); leftPanel.add(Box.createRigidArea(new Dimension(0,10))); leftPanel.add(runHTML);

JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); rightPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("HTML Render"), BorderFactory.createEmptyBorder(10,10,10,10))); rightPanel.add(theLabel);

setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); add(leftPanel); add(Box.createRigidArea(new Dimension(10,0))); add(rightPanel); }

public void actionPerformed(ActionEvent e) { theLabel.setText(htmlTextArea.getText()); }

private void createGUI() { JFrame frame = new JFrame("Marian's HTML Renderer"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.add(new HtmlRenderer()); frame.pack(); frame.setVisible(true); }} //**********************************************************************

84 public class JavaScriptRunWindow extends JPanel implements ActionListener { JEditorPane theLabel; JTextArea javaScriptTextArea;

public JavaScriptRunWindow() { // TODO Auto-generated constructor stub setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

TextPane.selectAll(); String initialText = TextPane.getSelectedText();

javaScriptTextArea = new JTextArea(20, 32); javaScriptTextArea.setText(initialText); JScrollPane scrollPane = new JScrollPane(javaScriptTextArea);

JButton runJS = new JButton("RunJS"); //runJS.setMnemonic(KeyEvent.VK_R); runJS.setAlignmentX(Component.CENTER_ALIGNMENT); runJS.addActionListener(this);

theLabel = new JEditorPane(); theLabel.setPreferredSize(new Dimension(400, 300)); theLabel.setContentType("text/plain");

JPanel leftPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); leftPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder( "JS Edit"), BorderFactory.createEmptyBorder(10,10,10,10))); leftPanel.add(scrollPane); leftPanel.add(Box.createRigidArea(new Dimension(0,10))); leftPanel.add(runJS);

JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); rightPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("JS in Action"), BorderFactory.createEmptyBorder(10,10,10,10))); rightPanel.add(theLabel);

setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); add(leftPanel); add(Box.createRigidArea(new Dimension(10,0)));

85

add(rightPanel); }

public void actionPerformed(ActionEvent e) { ScriptEngineManager factory = new ScriptEngineManager(); factory.getBindings(); ScriptEngine engine = factory.getEngineByName("JS"); //TextPane.selectAll(); //theLabel.setText(javaScriptTextArea.getText());

try { Object o = engine.eval(javaScriptTextArea.getText()); if(o != null) { theLabel.setText(o.toString()); }else { theLabel.setText(""); } } catch (ScriptException e1) { // TODO Auto-generated catch block Font font = new Font("Serif", Font.ITALIC, 20); theLabel.setFont(font); theLabel.setForeground(Color.RED); theLabel.setText("Code too complex !!\nPlease run in browser (Ctrl + J) !!");}}

private void createGUI(){ JFrame frame = new JFrame("Marian's JS in Action"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.add(new JavaScriptRunWindow()); frame.pack(); frame.setVisible(true);}}

//**********************************************************

public class RunJAVA extends JPanel implements ActionListener { JTextArea theOutput; JTextArea javaTextArea; JTextField name; JButton runJAVAbutton; PrintStream printStream;

public class CustomOutputStream extends OutputStream {

86

private JTextArea textPane;

public CustomOutputStream(JTextArea textArea) { this.textPane = textArea; }

@Override public void write(int b) throws IOException { // redirects data to the text area textPane.append(String.valueOf((char)b)); // scrolls the text area to the end of data textPane.setCaretPosition(textPane.getDocument().getLength()); } } public RunJAVA() { setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); TextPane.selectAll(); String initialText = TextPane.getSelectedText(); name = new JTextField(15); name.setToolTipText("Name of the public class"); javaTextArea = new JTextArea(20, 32); javaTextArea.setText(initialText);

JScrollPane scrollPane = new JScrollPane(javaTextArea); runJAVAbutton = new JButton("RunJAVA"); runJAVAbutton.addActionListener(this); theOutput = new JTextArea(20,33); theOutput.setEditable(false);

printStream = new PrintStream(new CustomOutputStream(theOutput)); System.setOut(printStream); System.setErr(printStream); JScrollPane scrollPane2 = new JScrollPane(theOutput);

JPanel leftPanel = new JPanel(new BorderLayout(5,5)); leftPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder( "JAVA Edit"), BorderFactory.createEmptyBorder(10,10,10,10))); leftPanel.add(scrollPane,BorderLayout.CENTER ); JPanel namePanel = new JPanel(new BorderLayout(5,5)); name = new JTextField(15); name.setToolTipText("Name of the public class"); namePanel.add( name, BorderLayout.CENTER );

87

namePanel.add( new JLabel("Main class name"), BorderLayout.WEST ); leftPanel.add( namePanel, BorderLayout.NORTH ); leftPanel.add(runJAVAbutton, BorderLayout.SOUTH);

JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); rightPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder("JAVA Output"), BorderFactory.createEmptyBorder(10,10,10,10))); rightPanel.add(scrollPane2);

setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); add(leftPanel); add(Box.createRigidArea(new Dimension(10,0))); add(rightPanel); } public void actionPerformed(ActionEvent e) { try{ (new SourceCompilation()).execute();

}catch (Exception e1){ // TODO Auto-generated catch block e1.printStackTrace(); } } private void createGUI() throws Exception { JFrame frame = new JFrame("Marian's JAVA Compiler"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.add(new RunJAVA()); frame.pack(); frame.setVisible(true);

} class SourceCompilation extends SwingWorker { @Override public String doInBackground() throws IOException { return new DynamicCompiler().compileCode(); }

88

@Override protected void done() { try{ (new DynamicCompiler()).runIt(); enableComponents(true); } catch (Exception ignore){ } } }

public void enableComponents(boolean enable) { runJAVAbutton.setEnabled(enable); name.setEnabled(enable); javaTextArea.setEnabled(enable); }

public class DynamicCompiler { JavaCompiler compiler;

public String compileCode() { theOutput.setText( "Compiling..." ); enableComponents(false); String compResult = null; if (compiler==null) { compiler = ToolProvider.getSystemJavaCompiler(); } if ( compiler!=null ) { String code = javaTextArea.getText(); String sourceName = name.getText().trim(); if ( sourceName.toLowerCase().endsWith(".java") ) { sourceName = sourceName.substring(0,sourceName.length()-5 ); }

JavaSourceFromString javaString = new JavaSourceFromString(sourceName, code); ArrayList al = new ArrayList(); al.add( javaString );

ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter( baos );

JavaCompiler.CompilationTask task = compiler.getTask(osw, null, null, null, null, al);

89

boolean success = task.call(); theOutput.setText( baos.toString().replaceAll("\t", " ") ); compResult = "Compiled without errors: " + success +"\n"; theOutput.append( compResult ); theOutput.setCaretPosition(0); } else { theOutput.setText( "No compilation possible - sorry!" ); JOptionPane.showMessageDialog(new ImprovedTextEditor(), "No compiler is available to this runtime!", "Compiler not found", JOptionPane.ERROR_MESSAGE); System.exit(-1); } return compResult; }

public void runIt() throws IOException, InterruptedException { Process p = Runtime.getRuntime().exec("java.exe " + name.getText()); p.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

String line = ""; while ((line = reader.readLine())!= null) { printStream.append(line + "\n"); } }

class JavaSourceFromString extends SimpleJavaFileObject { final String code; JavaSourceFromString(String name, String code) { super(URI.create( "string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; }

@Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } }

public DynamicCompiler() throws IOException{}}}

90

//**********************************************************************

public class Help extends JFrame { private JButton jButton1; //private JButton jButton2; private JLabel jLabel1; private JScrollPane jScrollPane1; private JTextPane jTextPane1;

public Help() { initComponentsHelp(); jTextPane1.setEditable(Boolean.FALSE); this.setLocation(400, 160); } private void initComponentsHelp() { jScrollPane1 = new JScrollPane(); jTextPane1 = new JTextPane(); jLabel1 = new JLabel(); jButton1 = new JButton(); //jButton2 = new JButton(); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); jTextPane1.setFont(new java.awt.Font("Comic Sans MS", 0, 12)); jTextPane1.setText("Hello!! Welcome to Marian's Text Editor.\n"+ "You can do almost anything that you can do in any popular text editor available and more.\n"+ "Some of the features are:\n"+ "- duplicating or deleting lines or blocks of lines \n"+ "- moving sections of text \n"+ "- command retrieval and repetition \n"+ "- retrieval of other files into the current document \n"+ "- undoing/redoing changes \n"+ "- allowing more than one file to be edited at the same time \n"+ "- writing to, appending to, or clearing the clipboard \n"+ "- filling or overlaying areas with numbers or text \n"+ "- splitting and joining lines either manually or at/after some text \n"+ "- allowing split screens on the same or different files \n"+ "- allowing invocation of external code/applications \n"+ "- rendering HTML \n"+ "- running JavaScript code \n"+ "- running JAVA code \n\n"+ "There's More coming! Enjoy your text editing!!");

91

jScrollPane1.setViewportView(jTextPane1);

jLabel1.setFont(new Font("Tahoma", 1, 14)); jLabel1.setForeground(new Color(0, 0, 153)); jLabel1.setText("Help"); jButton1.setFont(new Font("Tahoma", 0, 14)); jButton1.setText("OK"); jButton1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButton1ActionPerformed(evt);}}); GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap()

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 443, Short.MAX_VALUE) .addContainerGap()) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1, GroupLayout.PREFERRED_SIZE, 41, GroupLayout.PREFERRED_SIZE) .addGap(214, 214, 214)))) .addGroup(layout.createSequentialGroup() .addGap(46, 46, 46) //.addComponent(jButton2) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 243, Short.MAX_VALUE) .addComponent(jButton1) .addGap(54, 54, 54)) ); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel1) .addGap(21, 21, 21) .addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 269, GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18)

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)

92

//.addComponent(jButton2) .addComponent(jButton1)) .addContainerGap(37, Short.MAX_VALUE)) ); pack(); } private void jButton1ActionPerformed(ActionEvent evt) { this.setVisible(false); } private void createGUI() { this.initComponentsHelp(); this.setVisible(true); }}

//**********************************************************************

public class About extends JFrame { private JButton jButton1; private JButton jButton2; private JLabel jLabel1;

public About() { initComponentsAbout(); this.setLocation(420, 250); } private void initComponentsAbout() { JLabel appTitleLabel = new JLabel(); JLabel appDescLabel = new JLabel(); JLabel versionLabel = new JLabel(); JLabel appVersionLabel = new JLabel(); jButton1 = new JButton(); jButton2 = new JButton(); jLabel1 = new JLabel();

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

appTitleLabel.setFont(appTitleLabel.getFont().deriveFont(appTitleLabel.getFont().getSt yle() | Font.BOLD, appTitleLabel.getFont().getSize()+4)); appTitleLabel.setText("Marian's Text Editor");

93

versionLabel.setFont(versionLabel.getFont().deriveFont(versionLabel.getFont().getStyle( ) | java.awt.Font.BOLD)); versionLabel.setText("Product Version:"); appVersionLabel.setText("1.0"); jButton1.setFont(new Font("Tahoma", 0, 14)); jButton1.setText("Back"); jButton1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButton1ActionPerformed(evt);}});

jButton2.setFont(new Font("Tahoma", 0, 14)); jButton2.setText("Exit"); jButton2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButton2ActionPerformed(evt);}});

GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap()

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) .addGap(18, 18, 18)

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addGroup(GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(versionLabel)

.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(appVersionLabel) .addGap(144, 144, 144)) .addComponent(appTitleLabel, GroupLayout.Alignment.LEADING) .addComponent(appDescLabel, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE))) .addGroup(layout.createSequentialGroup() .addComponent(jButton1) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 285, Short.MAX_VALUE)

94

.addComponent(jButton2))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap()

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(jLabel1) .addGroup(layout.createSequentialGroup() .addComponent(appTitleLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(appDescLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(versionLabel) .addComponent(appVersionLabel)))) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(jButton1) .addComponent(jButton2)) .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) );

pack();} private void jButton2ActionPerformed(ActionEvent evt) { System.exit(1); } private void jButton1ActionPerformed(ActionEvent evt) { String[] args={"Hello"}; this.setVisible(false); } private void createGUI() { this.initComponentsAbout(); this.setVisible(true); }} }

95