140
•••••••••• Java- DACTL: A Tool for Teaching Novice Programmers to Design and Write Java Programs with UML A Masters Thesis Submitted to the Faculty of the School of Computer Science and Information Systems in Partial Requirement for the Degree of Master of Science By Anna S. Armentrout Advisor Dr. Joseph Bergin Pace University Department of Computer Science New York, NY August 31, 1999

Java- DACTL: A Tool for Teaching Novice Programmers to Design and

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

••••••••••

Java- DACTL: A Tool for Teaching Novice Programmers

to Design and Write Java Programs with UML

A Masters Thesis Submitted to the Faculty of the School of

Computer Science and Information Systems in Partial Requirement

for the Degree of Master of Science

By Anna S. Armentrout Advisor Dr. Joseph Bergin

Pace University

Department of Computer Science

New York, NY August 31, 1999

Page 2: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

Contents

Introduction...................................................................................................................................4 Difficulties of Teaching Students Object-Oriented Design and Programming ............................6

The Overall View is More Important than the Details .....................................................7 Use Realistic Examples to Explore Design ......................................................................9 Relate the Design to the Implementation..........................................................................9 Show Students Many Examples of Design.....................................................................10

The Importance of UML.............................................................................................................11 Why Java?...................................................................................................................................12 A Description of Java-DACTL...................................................................................................13

General Description of Java-DACTL.............................................................................13 Technical Description of Java-DACTL Design ............................................................16

Conclusion and Future Work......................................................................................................18 Works Cited ................................................................................................................................21 Illustrations .................................................................................................................................23

Figure 1. Whole Screen View of Project................................................................23 Figure 2. Open/Save Document Interface ..............................................................24 Figure 3. Use Case Form........................................................................................25 Figure 4. Use Case Diagram ..................................................................................26 Figure 5. CRC Form...............................................................................................27 Figure 6. Class Diagram.........................................................................................28 Figure 7. Code Generation Window ......................................................................29 Figure 8. Code Files ...............................................................................................30

Code ............................................................................................................................................31

ActorButton.java ............................................................................................................31 ActorFigure.java .............................................................................................................31 BaseFrame.java...............................................................................................................32 BaseInternalFrame.java ..................................................................................................32 ClassDiagramCanvas.java ..............................................................................................33 ClassDiagramWindow.java ............................................................................................40 ClassForm.java ...............................................................................................................40 ClassObject.java .............................................................................................................57 ClassToolBar.java...........................................................................................................58 CodeGenerator.java ........................................................................................................59 CodeWindow.java...........................................................................................................62 ConnectButton.java ........................................................................................................63

Page 3: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

Connection.java ..............................................................................................................63 ControlWindow.java.......................................................................................................64 DiagramCanvas.java .......................................................................................................74 DiagramToolBar.java .....................................................................................................78 DiagramWindow.java .....................................................................................................78 Figure.java ......................................................................................................................80 LabelChange.java ...........................................................................................................82 LifelineButton.java .........................................................................................................82 MoveButton.java ............................................................................................................83 OvalButton.java ..............................................................................................................83 OvalFigure.java ..............................................................................................................83 ProjectModel.java...........................................................................................................84 ProjectMutableTreeNode.java ........................................................................................85 ProjectTree.java ..............................................................................................................86 ProjectTreeModelListener.java ......................................................................................94 RectangleFigure.java ......................................................................................................94 ResizeButton.java ...........................................................................................................95 SequenceDiagramCanvas.java........................................................................................95 SequenceDiagramWindow.java....................................................................................102 SequenceToolBar.java ..................................................................................................102 SquareButton.java.........................................................................................................103 SystemRectangleFigure.java ........................................................................................103 TextButton.java ............................................................................................................104 ToolButton.java ............................................................................................................104 Update.java ...................................................................................................................105 UseCase.java.................................................................................................................106 UseCaseDiagramCanvas.java .......................................................................................107 UseCaseDiagramWindow.java .....................................................................................122 UseCaseForm.java ........................................................................................................122 UseCaseToolBar.java ...................................................................................................132

Page 4: Java- DACTL: A Tool for Teaching Novice Programmers to Design and
Page 5: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

5

Introduction

It is a matter of some recent controversy among teachers of CS1 courses whether objects can

or should be taught early–before implementation principles. My project supports the view that

objects and object-oriented design should be taught early, that is, in the student’s first

programming class. The result of this project is a tool called Java-DACTL (Java Design,

Analysis and Coding Tool). Java-DACTL is a simple program which allows beginners–

students learning object-oriented design and programming for the first time–to use a modified

(i.e., simplified) version of Unified Modeling Language (UML) to design and begin coding

programs.

This tool is meant to be used by students who are participating in a class with an instructor. As

beginners, these students lack an understanding of the peculiarities of objects, design, and

possibly even programming. With a little guidance from the instructor, the students could

begin using Java-DACTL to make simple program designs. A little later in the course, Java-

DACTL helps the instructor to graphically illustrate the connection between design and

implementation by generating skeleton code based on students’ designs. Java-DACTL helps

introduce the student to the subtleties of object-oriented programming (OOP) while enforcing

the importance of good design.

Java-DACTL allows programs to be designed using UML. UML is a recently developed

modeling language intended to be the standard for designing object-oriented systems. UML is

a powerful modeling language that, in its actual form, is much more complex than the

Page 6: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

6

simplified version that is used in Java-DACTL. It makes sense, however, to use UML as a

basis for Java-DACTL so that students are introduced to the very modeling language that they

will probably be using in their future work. UML allows the student to approach designing a

program from the top down, first specifying use cases, then finding objects, and eventually

defining details like object interactions and member variables. In addition to UML, Java-

DACTL also uses the Class-Responsibility-Collaboration (CRC) card model. CRC cards are

useful because they remind the student what needs to be defined for each class, and they act as

a repository for this information. CRC cards also allow more information to be provided about

each class, resulting in more detailed skeleton code produced by the tool.

Java-DACTL was written in Java and produces skeleton code in Java. Java is a good language

for learning object-oriented design. Java is a simple language that is authentically object-

oriented and handles a number of important things (checking, pointers, garbage collection)

automatically that are difficult to implement and often the source of bugs in C++. In theory,

however, this tool can easily be modified to produce skeleton code for any object-oriented

language, by substituting a code generator for that language.

This tool designed to be simple to use and easy to navigate. My goal was to produce a tool

that could be used right away by the students, so that the time spent learning design and

programming would be maximized. Java-DACTL includes several project views, menu

keyboard shortcuts, and an intuitive interface. One advantage of this tool over a Computer

Assisted Software Engineering (CASE) tool for use in teaching is that it is very simple and

Page 7: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

7

quickly learned.

There are some additions and improvements that would need to be made to Java-DACTL to

make it a really complete tool for teaching first year programming students. A more complex

class diagraming ability and the ability to make sequence diagrams, which would show

messages being passed between objects in the program being designed, would allow better

skeleton code to be produced. Moreover, the code-generation process would be improved so

that it could be performed in reverse. This way a large, complex program, what Dr. Bergin

calls a Larger Than Life (TJOE, 4), could be given to the students to study, improve or revise.

The student would be able to use Java-DACTL to generate diagrams from the Larger Than

Life code to see its structure. As it exists now, the tool is fairly simple yet powerful and robust.

I hope Java-DACTL will prove useful for teaching novice programmers.

Difficulties of Teaching Students Object-Oriented Design and Programming

The problem of teaching object-oriented design has been discussed and debated frequently in

recent years. A workshop at the OOPSLA ‘96 Conference, “Teaching and Learning Object

Design in the First Academic Year”(Mercer), addressed this issue in detail. During this

workshop Alistair Cockburn did an experiment which involved “coaching” six first year

computer science students in design for a couple of hours, then having the students present

their designs to the workshop participants. This experiment proved surprisingly successful,

with the students producing “the best design [Cockburn] had yet seen, one that none of his

industry groups had managed to reach,” according to the workshop report (Mercer, 4).

Page 8: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

8

Clearly the success of Cockburn’s experiment indicates that object-oriented design (OOD) can

be taught early. Those who are against early teaching stress (or at least feel strongly about) the

student’s lack of readiness. The student, they argue, will be confused by the peculiarities of

OOD without a background in implementation, and this initial confusion would become a

hindrance to her subsequent computer education. The students in Cockburn’s experiment,

however, claimed to find “what they knew about programming to be a hindrance,” mentioning

“being distracted by thinking about parameter passing” as one example (Mercer, 5). Lack of

readiness in the student doesn’t seem to be the issue. Rather the pedagogical question should

not rest with the possible status of the student but with the form of the CS1 course itself. In

other words, what is at issue is the readiness of the class, its structure and tools, and not of the

student. So again: OOD can be taught early and effectively once the existing style of the CS1

course is revised to accommodate the peculiarities of object technology.

There are at least four basic ideas about how to change the CS1 course to effectively teach

OOD to beginners. These ideas are (1) emphasize that the overall view is more important than

the details; (2) use realistic, real world contexts to address design; (3) relate the structure or

design of a program to the implementation in a way the student can understand; and (4) show

students many examples of design. In what follows I will describe these ideas and show how

my project works with these ideas.

Page 9: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

9

The Overall View is More Important than the Details

It is important that beginning students understand the importance of the design over the details

of the implementation. Any attempt at teaching objects “should proceed from the top down–

from overall design to low-level detail” (Bergin, TJOE, 5). This concept becomes particularly

important later, when the student is designing and programming large systems. As M.E. Evans

puts it in his paper to the OOPSLA ‘96 workshop: “...in real-world design, issues of a macro-

perspective which emphasize the architectural organization and structural connections between

and among identified components are of significantly more importance than those of the

micro-design perspective” (Evans, 1). These ideas are easily demonstrated to students. When

one student participating in Cockburn’s experiment complained of the difficulty of making

design decisions, “[t]his question was ... posed: ‘Do you think it is better to make these

decisions now rather than after 30,000 coffee machines were distributed around the country?’

The students nodded yes” (Mercer, 5). In other words, isn’t it more important to work through

the difficulties of a particular problem at the beginning, rather than jump into an

implementation that could be problematic?

Java-DACTL helps to emphasize the importance of design over implementation. It makes

designing and design revisions easier for the student. It also allows a more extended focus on

design, by providing a skeleton code generator, so that the student can go straight from her

design to her implementation. In addition, Java-DACTL dramatically illustrates the secondary

nature of implementation, as the implementation is automatically generated from a student’s

Page 10: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

10

design, whereas the creative problem solving really occurs in the design phase.

Use Realistic Examples to Explore Design

It is fairly obvious that students will grasp design concepts much faster if the concepts are

explained and experienced in the context of a real world example that the students can

understand. At OOPSLA, “[t]here was strong agreement that design should be addressed in

realistic contexts.” (Mercer, 7). The scale of this example must be sufficiently complex, so

that the design solution is not immediately obvious. M.E. Evans states that “the identification

of qualities of good design, and an understanding of applicable design tools can only be

appreciated by studying “large, meaningful” problems” (2). It is not useful to choose an

example that would involve only one or two objects, as this is not realistic. Such a small scale

problem only demonstrates to the students that attempting to design a solution to a problem

when the implementation of the solution is so apparent is a waste of time.

The only difficulty with introducing such a realistic and meaningfully complex problem to a

class of OOD beginners is the risk of intimidating the students. Java-DACTL helps to ease

this intimidation by allowing the student to approach the problem gradually, from the top

down. The tool is also helpful in that it saves all of the student’s classes and use cases in one

place, allowing the student to revise and improve her design over time. The experience of

grappling with a realistic problem in this manner gives the student confidence as well as

understanding of OOD.

Page 11: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

11

Relate the Design to the Implementation

In order to gain a sense of purpose while executing a design, the student must understand the

relationship between the design and the implementation. Students need to understand “how

the details are derived from the principles” (Mercer, 6), in other words, how the

implementation is derived from the design. Fortunately, “there is much less of a cusp in TO

(Object Technology) between analysis/design on one hand and implementation on the other”

(Bergin, TJOE, 3). The design of object-oriented programs is very closely related to the actual

code of object-oriented programs.

In order to demonstrate this relationship, “[s]tudents must see the system’s logic from above

and they must see the outcome of their work, that is to say the running program” (Angster 1).

Java-DACTL very clearly illustrates this relationship by beginning the implementation process

for the student based on the student’s design. The student can compare her design with the

resulting skeleton code and understand how different elements of the design fit into the code.

Show Students Many Examples of Design

Students will often get stuck in a pattern of thinking and find it difficult to imagine more than

one solution to a problem. It is helpful to show the student a number of solutions to one

problem to get the student to think more creatively. This practice will make the students better

designers: “Appreciation and development of good design is enhanced via the study of

Page 12: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

12

alternative designs for the same product” (Evans, 2). One way of doing this is to have

individual students or small groups of students come up with designs for the same problem,

and present their designs to the class. If Java-DACTL is being used as a design tool in the

class, solutions to a common problem can be demonstrated using a common medium (the tool),

and the differences in actual solutions can be highlighted. Java-DACTL can also save

particularly good solutions from one class so that it can be shown to later classes.

Java-DACTL is an attempt to address the specific concerns of teaching and learning OOD.

Within the class setting, the tool mediates helpfully between the respective roles of the teacher

and the student. Java-DACTL gives students practice in thinking from a macro-perspective. It

helps the instructor approach OOD from the top down; helps the student to attempt to solve a

real design problem; it helps the teacher more explicitly explain–and the student to

understand–the relationship between the design and the implementation; and it can help the

instructor to build a library of design examples to show to the student. With certain

modifications in the tool, such as improved diagraming ability, Java-DACTL could be used by

students in higher levels to speed the process of making a design and starting its

implementation.

The Importance of UML

Modeling languages are useful because of their universality; they allow design ideas to be

communicated to other programmers and archived for future reference or revision. Students

Page 13: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

13

learning design will also need to communicate their design ideas, and so will need to use some

sort of modeling language that is at least recognized and understood throughout the class.

Java-DACTL is based on the modeling language UML. UML was developed from a number

of popular object-oriented modeling methodologies (Booch, OMT-2, OOSE), with the

intention that it would be the standard for modeling object-oriented systems. UML allows the

design of a system to be approached from a number of different views, each view further

defining some aspect or detail of the system as a whole. The sum of the views seen together

describe the system as a whole. UML is also useful through different phases of systems

design, from the initial analysis through implementation and revision. The decision to use

UML in Java-DACTL was based on the idea that, as Bergin writes: “Students need to be able

to design their programs–somehow. They may as well learn a technique into which they can

grow”

(TOOAD, 1).

For the sake of beginners, Java-DACTL uses a simplified version of UML. This tool is meant

to be easy to use, and a design tool that implements all of UML, like Rational Rose, is not easy

to learn or use. The UML concepts used in this tool can be quickly grasped by students.

Meanwhile, by using part of UML they are making progress towards developing an essential

competency in a modeling language that will most likely be important to them in the future.

Why Java?

Page 14: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

14

Java is an excellent object-oriented language for beginners. Java is a simple language, yet

powerful and robust. As a true object-oriented language it is superior to C++, which is

developed from non-object C, and must be somewhat backwards compatible. C++ is a more

difficult language than Java, and as certain OOD principles are not easily transferred to C++,

“C++ is probably not the best language for a CS1 design course” (Evans, 3). The simplicity of

Java means that the instructor can spend more time on design, and the student can pick up

much of the implementation on her own. Java-DACTL is written in Java because of its other

nice qualities, like platform independence. It is not vital, however, that Java be taught with

Java-DACTL. Any good object-oriented language can be taught, once a code generator for

that language has been written and substituted for the Java generator.

A Description of Java-DACTL

In the previous sections of this paper I have tried to show how Java-DACTL could be useful,

and to explain why it is based in certain technologies. This section will be a description of the

tool in general, followed by a more technical description of how Java-DACTL was put

together.

General Description of Java-DACTL

Java-DACTL enables students designing object-oriented programs to (1) analyze the problem

at hand and work out how to attack it; (2) flesh out a design, based on classes and objects; (3)

begin implementation by generating Java skeleton code from the finished design. Java-

Page 15: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

15

DACTL is intended to be simple and easy to use because “time spent on learning CASE tools,

notation, methodologies, and so on is time taken from topics in computer science that must be

taught as necessary background in computer science” (Astrachan, 4). Because of the intuitive

interface of Java-DACTL, a short introduction to UML and CRC cards by the instructor should

be all that is required for the student to be on her way to designing an object-oriented program

with this tool (Fig. 1).

The student starts by either opening a previously saved project or creating a new project (Fig.

2). Once a project is open, a tree appears on the left of the screen with the project name at the

top and a list of the project’s existing use cases and classes below. This affords the student a

handy overview of the project that is being worked on. The student can then choose to work in

one of four views: she can fill in use case (Fig. 3) or CRC card (Fig. 5) forms or she can make

use case (Fig. 4) or class diagrams (Fig. 6). The student can also change the names of the

various objects or the project itself in the tree view.

To work in a particular view the student must select the menu item from the project menu or

type its menu shortcut key. In order to maximize screen real estate, each view has its own

window. These view windows appear on the right side of the interface (Fig. 1). The student

can have as many or as few views open as a time as she desires. The student is able to switch

back and forth easily between the views. Clicking on a view that is already displayed brings

that view to the top. When the student enters or changes information for any one of the views,

the tool updates the equivalent information for the other views. For example, if the name of a

Page 16: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

16

class is changed in the tree view, the class name is automatically updated in the class diagram

view and in the corresponding CRC card.

Each of the two diagraming views has its own specialized diagraming tools, which help the

user to make “legal” diagrams. Figures in both of the diagram views can be moved, resized,

deleted (either permanently or with “cut”) and restored (with “undo”). There is also a feature

which prevents the user from accidentally drawing a figure so small that it can’t be selected

and deleted (a common problem when I was testing the system). The form views also perform

certain checks. To prevent the duplication of information in a project–for example, entering

the same class multiple times into the system–the two form views supply lists of previously

entered names, and will not add a new item with the same name as an old item; rather if an

attempt is made to add a same-name item, the old item is selected. The two pairs of form-

diagram views work together. Any use case that is drawn in the diagram view will appear in

the use case form view as a new use case form. If a name for the use case is typed in the

“name” field of the use case form, this name is added to the figure in the diagram view as a

label. In this way, the user has a consistent view of the whole program being designed at all

times.

When the student is satisfied with her design, she can generate Java skeleton code by choosing

the “Generate Code” menu item (or shortcut key). A code generation window (Fig. 7) is

opened by the tool. This window displays messages which describe what is happening while

the skeleton code is being generated. The tool generates a separate *.java file for each class in

Page 17: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

17

the design (Fig. 8), which it saves in a location that was selected by the student. The student

can then save her design to be reopened and possibly modified at a later time, and begin to

program by filling in the skeleton code.

Technical Description of Java-DACTL Design

As with all programs, Java-DACTL depends on contributions from a number of difference

sources. These range from course work to textbooks. The earliest contributor was Bergin’s

Java class CS631N, which emphasized object-oriented design. In this class students learned to

“document ... object interactions with simple diagrams and with CRC cards. These simple

diagrams can use a visual syntax taken from OO modeling tools, though in a simplified form”

(Bergin, TJOE). As noted above, Java-DACTL is based on a simplified form of UML and

CRC cards.

The “seed code” of the tool was the applet PaintDrawApplet from Bergin’s paper “Graphical

User Interface Programming for Multi-Platform Applications.” At one point in this paper,

Bergin speculatively assigns a project to his intended reader: “Learn about the Unified

Modeling Language (UML), which is a graphical technique for designing object oriented

software. Build me (in Java) a simple UML modeling tool” (GUIPMPA, 3:11). Java-DACTL

is more or less the resulting product of this assignment.

More detailed requirements of such a modeling tool were provided by the technical discussion

Page 18: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

18

in UML Toolkit. There the specific functions which any “modern CASE tool should provide”

in order to be complete are specified. These functions are:

• Draw diagrams ...

• Act as a repository: ... If the name of a class is changed in one diagram, the change

must be replaced in all other diagrams in which the class is used.

• Support navigation: The tool should make it easy to navigate the model

[ . . . ]

• Generate code: An advanced tool should be able to generate code, where all the

information in the model is translated into code skeletons that are used as a base for

the implementation phase.

[ . . . ]

• Cover the model at all abstraction levels: The tools should be easy to navigate from

the top-level description of the system ... down to the code level. (Erikksson, 34-36)

As described previously in this paper, Java-DACTL was built following these very helpful

design guidelines.

The actual implementation of Java-DACTL was achieved using the Model-View-Controller

pattern, which allows for a great deal of flexibility in how information is displayed to the user

and stored in the system. The model acts as a repository for information for the current project

and is not influenced by the mode of display. Because of the model’s independence the design

Page 19: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

19

can be viewed or updated by the user in any one of five views, and any changes are reflected in

each of the other views. Similarly, the model is not influenced by the kind of code that is

generated from the finished design. Java-DACTL is capable of displaying information in a

number of views quite easily, because of the fact that the model for each of the views is the

same, and the views each “know” how to display the information in the model that is relevant

to them.

In developing this project I adopted the method set forth in Bergin’s CS631N. The project,

therefore, evolved in three stages, namely: Analysis, Design, and Implementation. In the

initial Analysis and Design phases I had a poor understanding of who would eventually be

using this tool, so it was difficult, at first, to understand what I was really trying to build. It is

rather surprising that my initial scoping document is not all that different from the

implementation that eventually evolved. The implementation phase took slightly longer that

planned, which as we know is the norm in writing software, though the implementation itself

was not terribly difficult. A few interruptions contributed to the delay in developing this

project. One of these interruptions was the ITiCSE conference in Cracow, which I attended

with Dr. Bergin and Al Rossi, to present a poster on this project. The conference was quite

helpful in giving me an understanding of how Java-DACTL could be useful to instructors

teaching object-oriented programming.

Conclusion and Future Work

Page 20: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

20

As it exists now, Java-DACTL is a simple, flexible tool for teaching CS1 students object-

oriented design and programming. This tool encourages a top-down approach, and could be an

enhancement to patterns already used in teaching objects. In order to be a truly complete

beginner’s design tool, however, there are a few additions that should be made to Java-

DACTL. These additions would include the ability to print each of the views, and the ability to

draw diagrams and make CRC cards from existing code. Another addition that would make

the tool more powerful, which was mentioned above, is a more complex diagraming ability.

It would be fairly simple to add the printing capability to Java-DACTL. Students would be

able to print diagram windows and detailed lists of use cases and CRC cards, in a presentable

format. This would allow students to painlessly produce a design document from Java-DACTL

that could be submitted to the instructor. This capability is desirable because ordinarily

“students will resent producing such a document, mostly because the document doesn’t help

solve the problem or write the program” (Astrachan, 3). In this case, producing the design

document with the tool does help solve the problem and write the program.

The UML Toolkit includes among the requirements for a complete CASE tool “Reverse

engineer: An advanced tool should be able to read existing code and produce models from it.

Thus a model could be made from existing code; or a developer could iterate between working

in the modeling tool and programming” (Erikksson, 35). In the case of Java-DACTL, adding a

reverse engineering capability would be useful because an important OO teaching pattern,

Readers-Writers, is based on the idea “that students can read and learn from artifacts more

Page 21: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

21

complex than they can build” (Bergin, TJOE). The student would be able to take a large,

complex program and reverse engineer it with Java-DACTL to discover its design.

A more complex diagraming capability, one that would allow the user to make better class

diagrams and add the ability to make sequence diagrams, would result in more explicit

skeleton code. This embellishment would allow the tool to be used profitably in any CS

course.

Page 22: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

22

Works Cited Angster, Erzsébet. “A Simple OO System Pattern to Introduce OOP with Design.” The

Eleventh Annual ACM Conference on Object-Oriented Programming Systems, Languages and Applications [6-10 October 1996]. 20 August 1999. <http://www.mcs.vuw.ac.nz/comp/Research/design1/1996/submissions/ 10Erzsebet_Angster.htm>

Astrachan, Owen. “Object Design in the First Year: An Oxymoron.” The Eleventh Annual

ACM Conference on Object-Oriented Programming Systems, Languages and Applications [6-10 October 1996]. 20 August 1999. <http://www.mcs.vuw.ac.nz/comp/ Research/design1/1996/submissions/17Owen_Astrachan.htm>

Bergin, Joseph. “Graphical User Interface Programming for Multi-Platform Applications in

Java 1.1 or GUI Programming in Java for Everyone” [GUIPMPAJ]. Vers. 2. Last modified June 1998. 11 August 1998. <http://csis.pace.edu/~bergin/sol/java/gui/>

_____. “Outline of Model-View-Controller Paradigm as Expressed in the Java Libraries.”

1996-1999. 7 July 1999. <http://csis.pace.edu/~bergin/papers/ModelViewController.html>

_____. “Teaching Java / Objects Early” [TJOE]. Manuscript in E-mail to Anna Armentrout. 12

August 1999. _____. “Teaching Object-Oriented Analysis and Design in CS1” [TOOAD]. 3 August 1999.

<http://csis.pace.edu/~bergin/papers/OOAD.html> Eriksson, Hans-Erik and Magnus Penker. UML Toolkit. New York: Wiley, 1997. Evans, M.D. “CS1 As An Architectural Design Course.” The Eleventh Annual ACM

Conference on Object-Oriented Programming Systems, Languages and Applications [6-10 October 1996]. 20 August 1999. <http://www.mcs.vuw.ac.nz/comp/ Research/design1/1996/submissions/07Mike_Evans.htm>

Flanagan, David. Java in a Nutshell. Cambridge, MA: O'Reilly, 1997. Harmon, Paul and Mark Watson. Understanding UML: The Developer's Guide: With a Web-Based Application in Java. San Francisco: Kaufmann, 1998. Larman, Craig. Applying UML and Patterns: An Introduction to Object-Oriented Analysis and

Design. Engelwood Cliffs, NJ: Prentice Hall, 1997. Mercer, Rick, Robert Biddle, Robert Duvall and Mike Clancy. “Teaching and Learning Object

Design in the First Academic Year.” The Eleventh Annual ACM Conference on

Page 23: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

23

Object-Oriented Programming Systems, Languages and Applications [6-10 October 1996]. 20 August 1999. <http://www.mcs.vuw.ac.nz/comp/Research/design1/>

UML Resource Center. Rational. 17 October 1998. <http://www.rational.com/uml/index.jtmpl> “A Visual Index to the Swing Components.” The Java Tutorial. August 1999.

Sun Microsystems. <http://java.sun.com/docs/books/tutorial/uiswing/ components/components.html>

Page 24: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

24

Illustrations

Figure 1. Whole Screen View of Project

Page 25: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

25

Figure 2. Open/Save Document Interface

Page 26: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

26

Figure 3. Use Case Form

Page 27: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

27

Figure 4. Use Case Diagram

Page 28: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

28

Page 29: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

29

Figure 5. CRC Form

Page 30: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

30

Figure 6. Class Diagram

Page 31: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

31

Figure 7. Code Generation Window

Page 32: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

32

//import java packages /** Displays the fortune */ class DisplayWindow extends Frame { //constructor public DisplayWindow () { } //attributes String name OkayButton ok //responsibilities //inner classes class OkayButton { //constructor public OkayButton () { } } } Figure 8. Code Files

Page 33: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

33

Code ActorButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This is a GUI element that could be reused in a number of diagram * views. Could change image, as well */ class ActorButton extends ToolButton implements ActionListener { public ActorButton (DiagramCanvas target)

{ super (target,image, "Draw actor", target.ACTOR, Cursor.DEFAULT_CURSOR); } private static final ImageIcon image = new ImageIcon("images/actor.jpg");

} ActorFigure.java import java.awt.*; /** * Handles the drawing of an actor figure.This class was elaborated from a * class written by J.Bergin for "PaintDrawApplet" 12.97 */ public class ActorFigure extends Figure implements java.io.Serializable { public ActorFigure(int ID, String label, int x, int y, int w, int h)

{ super(ID, label, x, y, w, h); } public void draw(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawOval(x+20, y, w/5, h/5); g.drawLine(x+25, y+10, x+25, y+30); g.drawLine(x, y+20, x+50, y+20); g.drawLine(x,y+50, x+25, y+30); g.drawLine(x+25, y+30, x+50, y+50); Color c = g.getColor(); //g.setColor(Color.white); //g.fillOval(x+1, y+1, w - 2, h - 2); g.setColor(Color.red); if (label != null) { FontMetrics font = g.getFontMetrics();

int centerX = findMiddleX(w,label,font); g.drawString(label, x + centerX, y+65);

} g.setColor(c); if(selected) drawSelectors(g);

}

Page 34: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

34

public void drawOutline(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawOval(x+25, y+5, w/5, h/5); g.drawLine(x+25, y+10, x+25, y+30); g.drawLine(x, y+20, x+50, y+20); g.drawLine(x,y+50, x+25, y+30); g.drawLine(x+25, y+30, x+50, y+50);

} } BaseFrame.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This Frame from which the [main] ControlWindow is derived. * Just sets up a basic frame and menu bar * @see ControlWindow */ public class BaseFrame extends JFrame { public BaseFrame(String name, int actionOnClose)

{ super (name); setDefaultCloseOperation(actionOnClose); setSize(400,400); setTitle(name); getContentPane().setLayout (new BorderLayout()); menuBar = new JMenuBar(); fileMenu = new JMenu ("File", true); fileMenu.setMnemonic(KeyEvent.VK_F); menuBar.add(fileMenu); setJMenuBar(menuBar); } JMenuBar menuBar; JMenu fileMenu; JMenu editMenu; } BaseInternalFrame.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; /** * This is the superclass upon which all of the view windows are built. * sets up basic size, menu bar, default close operation. Superclass * JInternalFrame allows this Frame to be added (and not dragged outside of) * a parent frame. * @see DiagramWindow

Page 35: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

35

*/ public class BaseInternalFrame extends JInternalFrame { public BaseInternalFrame(String name)

{ super (name, resizable, closeable, maximizable, iconifiable); setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE); setSize(400,400); setTitle(name); getContentPane().setLayout (new BorderLayout()); menuBar = new JMenuBar(); fileMenu = new JMenu ("File", true); fileMenu.setMnemonic(KeyEvent.VK_F); menuBar.add(fileMenu); editMenu = new JMenu ("Edit", true); editMenu.setMnemonic(KeyEvent.VK_E); menuBar.add(editMenu); setJMenuBar(menuBar);

} JMenuBar menuBar; JMenu fileMenu; JMenu editMenu; private static boolean resizable = true; private static boolean closeable = true; private static boolean maximizable= true; private static boolean iconifiable = true; } ClassDiagramCanvas.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; /** * Handles all mouse drawing events for ClassDiagram view. Key events are * handled by superclass, because key events for all diagram windows can * basically be handled in the same manner. * @see DiagramCanvas */ class ClassDiagramCanvas extends DiagramCanvas implements MouseMotionListener, MouseListener { public ClassDiagramCanvas(ProjectModel pm)

{ super (pm); addMouseMotionListener(this); addMouseListener(this);

}

public void mouseClicked(MouseEvent e) { boolean doDraw = false;

switch (mode) { case MOVE:

//a click while in move mode is a selection or deselection event Point p = e.getPoint();

Page 36: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

36

Enumeration v = figures.elements(); selectedFigure = null; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { if(! f.isSelected())

{ doDraw = true; f.setSelected(true); selectedFigure = f;

} } else { if(f.isSelected())

{ doDraw = true; f.setSelected(false);

} }

} break;

case SQUARE: //if a user clicks while in square mode, draw a default sized square

p = e.getPoint(); int ID = projectModel.newID(); RectangleFigure project = new RectangleFigure(ID, null, p.x,

p.y,100,100); figures.add (project); doDraw = true; break;

case OVAL: //if a user clicks while in oval mode, draw a default sized oval

p = e.getPoint(); ID = projectModel.newID(); OvalFigure usecase = new OvalFigure(ID, null, p.x, p.y, 60, 30); figures.add(usecase); doDraw = true; break;

case CONNECT:

//if a user clicks while in connect mode, //remember the figure they clicked on (if one was clicked on).

p = e.getPoint(); v = figures.elements(); selectedFigure = null; doDraw = false; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { //if not already remembering a figure they clicked on,

//remember this one as "one" if (one == null)

one = f; //if already remembering a figure they clicked on as "one",

Page 37: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

37

//remember this one as "two" and make a new connection. else if (two == null) { doDraw = true;

two = f; ID = projectModel.newID(); Connection c = new Connection (ID, null, one, two); connections.add(c); //then clear "one" and "two" for next time.

one = null; two = null;

} }

} break;

case TEXT:

//if click occurs in text mode, figure out if click occurs on an //element of the diagram and begin the labeling process

requestFocus(); stringBuilder = new StringBuffer(""); p = e.getPoint(); v = figures.elements(); labelFigure = null; stringIndex = -1; doDraw = false; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null)

firstLetter = true; }

} if (!doDraw) { v = connections.elements();

while (v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if (f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null)

firstLetter = true; }

} } break;

} if (doDraw)

repaint(); } public void mouseDragged(MouseEvent e) { e.consume();

Page 38: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

38

switch (mode) { case MOVE:

if(dragging) { flip(selectedFigure);

selectedFigure.move(e.getPoint()); flip(selectedFigure);

} break;

case SQUARE: //in square mode, dragging indicates that object is being manually //drawn and sized

Point secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); int width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } int height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

RectangleFigure project = new RectangleFigure(ID, null, originPoint.x, originPoint.y,width,height);

figures.add (project); selectedFigure = project;

} else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

case OVAL:

//Dragging while in oval mode suggests that oval is being drawn //to user's preferred shape/size

secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

Page 39: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

39

OvalFigure usecase = new OvalFigure (ID, null, originPoint.x, originPoint.y,width,height);

figures.add (usecase); selectedFigure = usecase;

} else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

case RESIZE:

//can't resize ActorFigure if (selectedFigure instanceof ActorFigure)

break; else if (dragging) { Point p = e.getPoint();

int cursortype = drawCursor.getType(); Rectangle figbounds = selectedFigure.getBounds(); int differenceX; int differenceY; switch (cursortype) { case drawCursor.N_RESIZE_CURSOR:

differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(figbounds.width,

figbounds.height + differenceY); break;

case drawCursor.S_RESIZE_CURSOR:

differenceY = p.y - figbounds.y; selectedFigure.setBounds(figbounds.width, differenceY); break;

case drawCursor.E_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; selectedFigure.setBounds(differenceX, figbounds.height); break;

case drawCursor.W_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height); break;

case drawCursor.NW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(p.x, p.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height + differenceY); break;

Page 40: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

40

case drawCursor.NE_RESIZE_CURSOR: differenceX = p.x - figbounds.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(differenceX,

figbounds.height + differenceY); break;

case drawCursor.SE_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; differenceY = p.y - figbounds.y; selectedFigure.setBounds(differenceX, differenceY); break;

case drawCursor.SW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = p.y - figbounds.y; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

differenceY); break;

} } break;

} repaint();

}

//different cursors depending on where mouse is on diagram public void mouseMoved(MouseEvent e) { e.consume();

//if mode is resize, want to display special cursors on edges //and corners of a figure if (mode == RESIZE)

{ Point p = e.getPoint(); Enumeration v = figures.elements(); selectedFigure = null; boolean doDraw = false; int resultcursor = drawCursor.DEFAULT_CURSOR; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { int x = f.getBounds().x;

int y = f.getBounds().y; int xw = f.getBounds().x + f.getBounds().width - 1; int yh = f.getBounds().y + f.getBounds().height - 1; boolean N = false; boolean S = false; boolean E = false; boolean W = false; if (p.x == x)

W = true; if (p.x == xw)

E = true;

Page 41: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

41

if (p.y == y) N = true;

if (p.y == yh) S = true;

if (N && W) resultcursor = drawCursor.NW_RESIZE_CURSOR;

else if (S && E) resultcursor = drawCursor.SE_RESIZE_CURSOR;

else if (S && W) resultcursor = drawCursor.SW_RESIZE_CURSOR;

else if (N && E) resultcursor = drawCursor.NE_RESIZE_CURSOR;

else if (W) resultcursor = drawCursor.W_RESIZE_CURSOR;

else if (E) resultcursor = drawCursor.E_RESIZE_CURSOR;

else if (N) resultcursor = drawCursor.N_RESIZE_CURSOR;

else if (S) resultcursor = drawCursor.S_RESIZE_CURSOR;

selectedFigure = f; } drawCursor = drawCursor.getPredefinedCursor(resultcursor); setCursor(drawCursor);

} }

}

public void mousePressed(MouseEvent e) { e.consume();

switch (mode) { case MOVE:

if(selectedFigure != null && selectedFigure.contains(e.getPoint())) dragging = true; break;

case SQUARE: case OVAL:

selectedFigure = null; Point firstPoint = e.getPoint(); firstPointX = firstPoint.x; firstPointY = firstPoint.y; break;

case ACTOR: int ID = projectModel.newID(); ActorFigure actor = new ActorFigure(ID, null, e.getX(),

e.getY(), 50, 50); figures.add(actor); invalidate(); repaint(); break;

case RESIZE:

Page 42: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

42

int cursortype = drawCursor.getType(); if (cursortype != drawCursor.DEFAULT_CURSOR)

dragging = true; break;

case CONNECT: case TEXT: default:

break; }

}

public void mouseEntered(MouseEvent e) { }

public void mouseExited(MouseEvent e) { } public void mouseReleased(MouseEvent e) { e.consume();

dragging = false; } private Figure one = null; private Figure two = null; private int firstPointX; private int firstPointY; private Point originPoint;

} ClassDiagramWindow.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** * This window in which all the class diagraming action occurs. * Sets up appropriate toolbar and drawing canvas * @see DiagramWindow */ public class ClassDiagramWindow extends DiagramWindow { public ClassDiagramWindow(String name, ProjectModel pm)

{ super (name); usercanvas = new ClassDiagramCanvas(pm); classtools = new ClassToolBar(usercanvas); getContentPane().add(classtools, BorderLayout.WEST); getContentPane().add(usercanvas); }

Page 43: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

43

ClassToolBar classtools; } ClassForm.java import java.awt.*; import java.awt.event.*; import java.lang.reflect.*; import javax.swing.*; import javax.swing.event.*; import java.util.*; import javax.swing.plaf.basic.*; /** * This view window is set up like a CRC card, allowing the user to add * classes and fill in information about each of the classes. */ public class ClassForm extends JInternalFrame implements Observer { public ClassForm(ProjectModel pm) { super("Class - Responsibility - Collaboration Form", true, true, true, true); setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE); setSize(550,450); setTitle("Class - Responsibility - Collaboration Form"); projectModel = pm; projectModel.addObserver(this); blankModel = new DefaultListModel(); Insets zeroInsets = new Insets(0,0,0,0); getContentPane().setLayout (new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = gbc.NONE; gbc.ipady = 10; gbc.ipadx = 10; gbc.insets = new Insets (5,5,0,0); //First column gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = gbc.EAST; //ID: label JLabel label = new JLabel ("ID #: "); getContentPane().add(label, gbc); //Superclass: label gbc.gridy = 1; label = new JLabel("Superclass: "); getContentPane().add(label,gbc); //Function Description: label gbc.gridy = 2; label = new JLabel("Function: "); getContentPane().add(label, gbc); //Inner Classes: label gbc.gridy = 3; label = new JLabel("Inner Classes: ");

Page 44: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

44

getContentPane().add(label, gbc); //Inner classes buttons gbc.gridy = 4; innerButton = new InnerButton(); innerButton.setMargin(zeroInsets); getContentPane().add(innerButton, gbc); gbc.anchor = gbc.CENTER; innerDeleteButton = new InnerDeleteButton(); innerDeleteButton.setMargin(zeroInsets); getContentPane().add(innerDeleteButton,gbc); //Collaborators: label gbc.anchor = gbc.EAST; gbc.gridy = 5; label = new JLabel("Collaborators: "); getContentPane().add(label, gbc); //Collaborators buttons gbc.gridy = 6; collabButton = new CollabButton(); collabButton.setMargin(zeroInsets); getContentPane().add(collabButton, gbc); //Back button gbc.gridy = 7; gbc.anchor = gbc.WEST; backButton = new BackButton(); backButton.setMargin(new Insets(1,1,1,1)); getContentPane().add (backButton, gbc); //Second column gbc.gridx = 1; gbc.gridy = 0; gbc.anchor = gbc.WEST; //ID text area idText = new JTextArea (1,3); idText.setEditable(false); getContentPane().add(idText, gbc); //Superclass list gbc.gridy = 1; //gbc.gridwidth = 2; superclassbox = new SuperComboBox(); superclassbox.setEditable(true); superclassbox.setPreferredSize(new Dimension(120,15)); getContentPane().add(superclassbox, gbc); //Function Description text area gbc.gridy = 2; gbc.gridwidth = 4; funcText = new JTextArea(1,28); JScrollPane textscroll = new JScrollPane(funcText); getContentPane().add(textscroll, gbc); //Inner Classes list gbc.gridwidth = 1; gbc.gridy = 3; innerModel = new DefaultListModel(); innerList = new JList(innerModel); innerList.setVisibleRowCount(3);

Page 45: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

45

innerList.setPrototypeCellValue("BlahBlahBlahBlah"); innerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane listScroll = new JScrollPane(innerList); getContentPane().add(listScroll, gbc); //Inner Classes add/delete textfield gbc.gridy = 4; innerText = new JTextField(8); getContentPane().add(innerText, gbc); //Collaborators list gbc.anchor = gbc.WEST; gbc.gridy = 5; collabModel = new DefaultListModel(); collabList = new JList(collabModel); collabList.setVisibleRowCount(3); collabList.setPrototypeCellValue("BlahBlahBlahBlah"); ListSelectionModel csm = collabList.getSelectionModel(); csm.addListSelectionListener(new CollabListSelectionHandler()); listScroll = new JScrollPane(collabList); getContentPane().add(listScroll, gbc); //Collaborators add/delete textfield gbc.gridy = 6; collabText = new JTextField(8); getContentPane().add(collabText, gbc); //Delete button gbc.anchor = gbc.WEST; gbc.gridwidth = 1; gbc.gridy = 7; deleteButton = new DeleteButton(); getContentPane().add(deleteButton, gbc); //Third column gbc.gridx = 2; gbc.gridy = 0; gbc.anchor = gbc.EAST; //Name label label = new JLabel ("Name: "); getContentPane().add(label,gbc); //Fourth column gbc.gridx = 3; gbc.gridy = 0; gbc.anchor = gbc.WEST; gbc.gridwidth = 2; //class name list classbox = new ClassComboBox(); classbox.setPreferredSize(new Dimension(200,15)); classbox.setEditable(true); getContentPane().add(classbox, gbc); //Responsibilities: label gbc.anchor = gbc.EAST; gbc.gridwidth = 1; gbc.gridy = 3; label = new JLabel("Responsibilities: "); getContentPane().add(label, gbc);

Page 46: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

46

//Responsibilities buttons gbc.gridy = 4; responsButton = new ResponsButton(); responsButton.setMargin(zeroInsets); getContentPane().add(responsButton, gbc); gbc.anchor = gbc.CENTER; responsDeleteButton = new ResponsDeleteButton(); responsDeleteButton.setMargin(zeroInsets); getContentPane().add(responsDeleteButton,gbc); //Attributes: label gbc.anchor = gbc.EAST; gbc.gridy = 5; label = new JLabel("Attributes: "); getContentPane().add(label, gbc); //Attributes buttons gbc.gridy = 6; attribButton = new AttribButton(); attribButton.setMargin(zeroInsets); getContentPane().add(attribButton, gbc); gbc.anchor = gbc.CENTER; attribDeleteButton = new AttribDeleteButton(); attribDeleteButton.setMargin(zeroInsets); getContentPane().add(attribDeleteButton,gbc); //New button gbc.gridy = 7; newButton = new NewButton(); getContentPane().add(newButton, gbc); //Fifth column gbc.gridx = 4; gbc.gridy = 3; gbc.anchor = gbc.WEST; //Responsibilities list responsModel = new DefaultListModel(); responsList = new JList(responsModel); responsList.setVisibleRowCount(3); responsList.setPrototypeCellValue("BlahBlahBlahBlah"); responsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); listScroll = new JScrollPane(responsList); getContentPane().add(listScroll, gbc); //Responsibilities add/delete textfield gbc.gridy = 4; responsText = new JTextField(8); getContentPane().add(responsText, gbc); //Attributes list gbc.anchor = gbc.WEST; gbc.gridy = 5; attribModel = new DefaultListModel(); attribList = new JList(attribModel); attribList.setVisibleRowCount(3); attribList.setPrototypeCellValue("BlahBlahBlahBlah"); attribList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); listScroll = new JScrollPane(attribList); getContentPane().add(listScroll, gbc);

Page 47: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

47

//Attributes add/delete textfield gbc.gridy = 6; attribText = new JTextField(8); getContentPane().add(attribText, gbc); //Next button gbc.gridy = 7; nextButton = new NextButton(); nextButton.setMargin(new Insets(1,1,1,1)); getContentPane().add (nextButton, gbc); classes = projectModel.getClasses(); currentDisplayIndex = -1; } JTextArea idText; ClassComboBox classbox; SuperComboBox superclassbox; JTextArea funcText; DefaultListModel blankModel; JList innerList; DefaultListModel innerModel; JTextField innerText; InnerButton innerButton; InnerDeleteButton innerDeleteButton; JList collabList; DefaultListModel collabModel; JTextField collabText; CollabButton collabButton; JList responsList; DefaultListModel responsModel; JTextField responsText; ResponsButton responsButton; ResponsDeleteButton responsDeleteButton; JList attribList; DefaultListModel attribModel; JTextField attribText; AttribButton attribButton; AttribDeleteButton attribDeleteButton; BackButton backButton; NextButton nextButton; DeleteButton deleteButton; NewButton newButton; //Save text in function description text area if it has been revised public void saveFuncText() { if (currentDisplayIndex >=0) { Action actions[] = funcText.getActions(); if (actions != null)

Page 48: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

48

{ ClassObject currentClass = (ClassObject)classes.elementAt(currentDisplayIndex); currentClass.setFuncDesc(funcText.getText()); Update updateClass = new Update(Update.CLASS_FORM, currentClass.getID(), Update.CHANGE, ClassObject.FUNC_DESC, funcText.getText()); projectModel.registerChange(); projectModel.notifyObservers(updateClass); } } } //Controls actions on the class list box (selections, additions) class ClassComboBox extends JComboBox implements ActionListener { public ClassComboBox() { super(); addActionListener(this); } private boolean updateChange; public void setUpdate() { updateChange = true; } public boolean findItem(String item) { for (int i = 0; i < getItemCount(); i++) { String test = (String)getItemAt(i); if (item.equals(test)) return true; } return false; } public void actionPerformed (ActionEvent e) { String newItem = e.getActionCommand(); //if there are no classes displayed, ignore action if (currentDisplayIndex >= 0) { //a simple selection change if (newItem.equals("comboBoxChanged")) { String item = (String)getSelectedItem(); if (item != null) displayClass(item); } else { if (findItem(newItem)) { //user types in a name already in list displayClass(newItem); } else { //a new item. add only if it isn't a blank item if (! newItem.equals("")) { ClassObject currentClass = (ClassObject)classes.elementAt(currentDisplayIndex); currentClass.setName(newItem); addItem(newItem);

Page 49: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

49

collabModel.addElement(newItem); displayClass(currentDisplayIndex); if (!updateChange) { Update updateClass = new Update(Update.CLASS_FORM,

currentClass.getID(), Update.CHANGE, ClassObject.NAME, newItem); projectModel.registerChange(); projectModel.notifyObservers(updateClass); } } } } } } } //Controls actions on the superclass list box (selections, additions) class SuperComboBox extends JComboBox implements ActionListener { public SuperComboBox() { super(); addActionListener(this); updateChange = false; } private boolean updateChange; public void setUpdate() { updateChange = true; } //check if item is already in list public boolean findItem(String item) { for (int i = 0; i < getItemCount(); i++) { String test = (String)getItemAt(i); if (item.equals(test)) return true; } return false; } public void actionPerformed (ActionEvent e) { String newItem = e.getActionCommand(); ClassObject currentClass = null; int ID = -1; if (newItem != null)//meaningless action { //could be adding a superclass with no classes yet

if (currentDisplayIndex >= 0) { currentClass =

(ClassObject)classes.elementAt(currentDisplayIndex); ID = currentClass.getID(); } //If comboBox is changing, new items must already

//have been added, must be updating a use case if ((currentDisplayIndex >= 0) && (!updateChange)

&& (newItem.equals("comboBoxChanged")))

Page 50: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

50

{ String item = (String)getSelectedItem(); if ((!updateChange) && (item != null)) { currentClass.setSuperClass(item); Update updateClass = new Update(Update.CLASS_FORM, ID,

Update.CHANGE, ClassObject.SUPER_CLASS, item); projectModel.registerChange(); projectModel.notifyObservers(updateClass); } } else if (!(newItem.equals("comboBoxChanged"))) { if (findItem(newItem))//item is duplicate of previous item. { if (currentDisplayIndex >= 0) currentClass.setSuperClass(newItem); if (!updateChange) { Update updateClass = new Update(Update.CLASS_FORM, ID,

Update.CHANGE, ClassObject.SUPER_CLASS, newItem); projectModel.registerChange(); projectModel.notifyObservers(updateClass); } } else //completely new item { if (! newItem.equals("")) { setUpdate(); addItem(newItem); } if (currentDisplayIndex >=0) currentClass.setSuperClass(newItem); if (!updateChange) { Update updateClass = new Update(Update.CLASS_FORM, ID,

Update.ADD, ClassObject.SUPER_CLASS, newItem); projectModel.registerChange(); projectModel.notifyObservers(updateClass); } int n = JOptionPane.showConfirmDialog(ClassForm.this, "Add new superclass to project as a class?","Add Superclass", JOptionPane.YES_NO_OPTION); if (n == JOptionPane.YES_OPTION) { int oldIndex = currentDisplayIndex; ClassObject newClass =

new ClassObject(projectModel.newID()); newClass.setName(newItem); classes.add(newClass); classbox.setUpdate(); classbox.addItem(newItem); collabModel.addElement(newItem); Update addClass = new Update(Update.CLASS_FORM,

newClass.getID(), Update.ADD, 0, newClass); projectModel.registerChange(); projectModel.notifyObservers(addClass); displayClass(oldIndex); } } } }

Page 51: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

51

updateChange = false; } } //Controls actions on back arrow button //scrolls back one entry class BackButton extends JButton implements ActionListener { public BackButton() { super(); init (null, back); addActionListener(this); setToolTipText("Back"); } public final ImageIcon back = new ImageIcon("images/back.jpg"); public void actionPerformed(ActionEvent e) { saveFuncText(); if (currentDisplayIndex > 0) displayClass(currentDisplayIndex - 1); } } //Controls action on next arrow button //scrolls forward one entry class NextButton extends JButton implements ActionListener { public NextButton() { super(); init(null, next); addActionListener(this); setToolTipText("Next"); } public final ImageIcon next = new ImageIcon("images/next.jpg"); public void actionPerformed(ActionEvent e) { saveFuncText(); if (currentDisplayIndex >= 0) { if (!(currentDisplayIndex + 1 >= classes.size())) displayClass(currentDisplayIndex + 1); } } } //Allows a class to be deleted class DeleteButton extends JButton implements ActionListener { public DeleteButton() { super("Delete"); addActionListener(this); } public void actionPerformed(ActionEvent e) { if (currentDisplayIndex >= 0) { ClassObject currentClass =

Page 52: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

52

(ClassObject) classes.elementAt(currentDisplayIndex); String name = currentClass.getName(); classes.removeElementAt(currentDisplayIndex); if (name != null); { classbox.setUpdate(); classbox.removeItem(currentClass.getName()); classbox.setUpdate(); classbox.setSelectedItem(null); collabModel.removeElement(currentClass.getName()); } if (classes.size() > 0) displayClass(0); else displayBlank(); projectModel.registerChange(); Update updateClass = new Update(Update.CLASS_FORM,

currentClass.getID(), Update.DELETE, 0, null); projectModel.notifyObservers(updateClass); } } } //Allows a class to be added class NewButton extends JButton implements ActionListener { public NewButton() { super("New"); addActionListener(this); } public void actionPerformed(ActionEvent e) { saveFuncText(); int ID = projectModel.newID(); ClassObject newClass = new ClassObject(ID); classes.add(newClass); Update updateClass = new Update(Update.CLASS_FORM, ID,

Update.ADD, 0, newClass); projectModel.registerChange(); projectModel.notifyObservers(updateClass); displayClass(classes.indexOf(newClass)); } } //Adds items in InnerClass list class InnerButton extends JButton implements ActionListener { public InnerButton() { super(); init (null, add); addActionListener(this); setToolTipText("Add"); } public final ImageIcon add = new ImageIcon("images/add.jpg"); public void actionPerformed(ActionEvent e)

Page 53: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

53

{ String newItem = innerText.getText(); if (! newItem.equals("")) { if (currentDisplayIndex >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); innerModel.addElement(newItem); innerText.setText(""); Update update = new Update(Update.CLASS_FORM, current.getID(),

Update.ADD, ClassObject.INNER_CLASS, newItem); projectModel.registerChange(); projectModel.notifyObservers(update); } } } } //Deletes items in InnerClass list class InnerDeleteButton extends JButton implements ActionListener { public InnerDeleteButton() { super(); init (null, delete); addActionListener(this); setToolTipText("Delete"); } public final ImageIcon delete = new ImageIcon("images/delete.jpg"); public void actionPerformed(ActionEvent e) { int index = innerList.getSelectedIndex(); if (index >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); Update update = new Update( Update.CLASS_FORM, current.getID(),

Update.DELETE, ClassObject.INNER_CLASS, innerList.getSelectedValue());

innerModel.remove(index); projectModel.registerChange(); projectModel.notifyObservers(update); } } } //Adds items in Responsibilities list class ResponsButton extends JButton implements ActionListener { public ResponsButton() { super(); init (null, add); addActionListener(this); setToolTipText("Add"); } public final ImageIcon add = new ImageIcon("images/add.jpg");

Page 54: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

54

public void actionPerformed(ActionEvent e) { String newItem = responsText.getText(); if (! newItem.equals("")) { if (currentDisplayIndex >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); responsModel.addElement(newItem); responsText.setText(""); Update update = new Update(Update.CLASS_FORM, current.getID(),

Update.CHANGE, ClassObject.RESPONSIBILITY, newItem); projectModel.registerChange(); projectModel.notifyObservers(update); } } } } //Deletes items in Responsibilities list class ResponsDeleteButton extends JButton implements ActionListener { public ResponsDeleteButton() { super(); init (null, delete); addActionListener(this); setToolTipText("Delete"); } public final ImageIcon delete = new ImageIcon("images/delete.jpg"); public void actionPerformed(ActionEvent e) { int index = responsList.getSelectedIndex(); if (index >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); Update update = new Update(Update.CLASS_FORM, current.getID(), Update.DELETE,

ClassObject.RESPONSIBILITY, responsList.getSelectedValue());

responsModel.remove(index); projectModel.registerChange(); projectModel.notifyObservers(update); } } } //Adds items in Collaborators list class CollabButton extends JButton implements ActionListener { public CollabButton() { super(); init (null, add); addActionListener(this); setToolTipText("Add"); }

Page 55: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

55

public final ImageIcon add = new ImageIcon("images/add.jpg"); public void actionPerformed(ActionEvent e) { String newItem = collabText.getText(); if (! newItem.equals("")) { if (currentDisplayIndex >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); collabModel.addElement(newItem); collabText.setText(""); //add this collaborator as a class int oldIndex = currentDisplayIndex; ClassObject newClass = new ClassObject(projectModel.newID()); newClass.setName(newItem); classes.add(newClass); classbox.setUpdate(); classbox.addItem(newItem); Update addClass = new Update(Update.CLASS_FORM,

newClass.getID(), Update.ADD, 0, newClass); projectModel.registerChange(); projectModel.notifyObservers(addClass); displayClass(oldIndex); } } } } class CollabListSelectionHandler implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); int[] selectedList = collabList.getSelectedIndices(); Vector stringList = new Vector(); for (int i = 0; i < selectedList.length; i++) { int index = selectedList[i]; String selectedCollab = (String)collabModel.getElementAt(index); stringList.add(selectedCollab); } current.setCollaborators(stringList); } } //Adds items in Attributes list class AttribButton extends JButton implements ActionListener { public AttribButton() { super(); init (null, add); addActionListener(this); setToolTipText("Add"); } public final ImageIcon add = new ImageIcon("images/add.jpg");

Page 56: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

56

public void actionPerformed(ActionEvent e) { String newItem = attribText.getText(); if (! newItem.equals("")) { if (currentDisplayIndex >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); attribModel.addElement(newItem); attribText.setText(""); Update update = new Update(Update.CLASS_FORM, current.getID(),

Update.CHANGE, ClassObject.ATTRIBUTE, newItem); projectModel.registerChange(); projectModel.notifyObservers(update); } } } } //Deletes items in Attributes list class AttribDeleteButton extends JButton implements ActionListener { public AttribDeleteButton() { super(); init (null, delete); addActionListener(this); setToolTipText("Delete"); } public final ImageIcon delete = new ImageIcon("images/delete.jpg"); public void actionPerformed(ActionEvent e) { int index = attribList.getSelectedIndex(); if (index >= 0) { ClassObject current =

(ClassObject)classes.elementAt(currentDisplayIndex); Update update = new Update(Update.CLASS_FORM, current.getID(),

Update.DELETE, ClassObject.ATTRIBUTE, attribList.getSelectedValue());

attribModel.remove(index); projectModel.registerChange(); projectModel.notifyObservers(update); } } } //function necessary for this class to be an observer //this class gets updates from the observable it is registered with public void update (Observable pm, Object arg) { Update classUpdate = (Update) arg; //only care about certain updates if ((classUpdate.getOrigin() == classUpdate.CLASS_DIAGRAM) || (classUpdate.getOrigin() == classUpdate.TREE_CO)) { int act = classUpdate.getAction(); switch (act) { case classUpdate.ADD:

Page 57: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

57

if (classUpdate.getField() == ClassObject.SUPER_CLASS) { String newItem = (String) classUpdate.getArg(); superclassbox.setUpdate(); superclassbox.addItem(newItem); if (currentDisplayIndex >= 0) displayClass(currentDisplayIndex); } else { ClassObject newClass = (ClassObject)classUpdate.getArg(); int index = classes.indexOf(newClass); displayClass(index); } break; case classUpdate.DELETE: if (classUpdate.getField() == ClassObject.SUPER_CLASS) { String deleteName = (String)classUpdate.getArg(); superclassbox.setUpdate(); superclassbox.removeItem((String)classUpdate.getArg()); if (currentDisplayIndex >= 0) displayClass(currentDisplayIndex); } else { String deleteItem = (String)classUpdate.getArg(); if (deleteItem != null) { classbox.removeItem(deleteItem); collabModel.removeElement(deleteItem); } if (classes.size() > 0) displayClass(0); else displayBlank(); } break; case classUpdate.CHANGE: int ID = classUpdate.getID(); int index = -1; if (ID >= 0) { ClassObject changeField = projectModel.findClass(ID); index = classes.indexOf(changeField); currentDisplayIndex = index; } if (classUpdate.getArg() instanceof String) { if (classUpdate.getField() == ClassObject.NAME) { String newItem = (String)classUpdate.getArg(); if (newItem != null) { classbox.setUpdate(); classbox.addItem(newItem); collabModel.addElement(newItem); displayClass(currentDisplayIndex); } }

Page 58: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

58

} else { LabelChange lc = (LabelChange)classUpdate.getArg(); String oldItem = lc.getOld(); String newItem = lc.getNew(); if (newItem != null) { int field = classUpdate.getField(); switch (field) { case ClassObject.NAME: classbox.setUpdate(); classbox.removeItem(oldItem); collabModel.removeElement(oldItem); classbox.setUpdate(); classbox.addItem(newItem); collabModel.addElement(newItem); displayClass(currentDisplayIndex); break; case ClassObject.SUPER_CLASS: superclassbox.setUpdate(); superclassbox.removeItem(oldItem); superclassbox.setUpdate(); superclassbox.addItem(newItem); if (index >= 0) displayClass(currentDisplayIndex); break; case ClassObject.INNER_CLASS: ClassObject current = projectModel.findClass(ID); currentDisplayIndex = classes.indexOf(current); displayClass(currentDisplayIndex); innerModel.removeElement(oldItem); innerModel.addElement(newItem); break; } } } break; default: break; } } else if (classUpdate.getOrigin() == Update.OPEN) { if (! classes.isEmpty()) { for (int index = 0; index < classes.size(); index ++) { currentDisplayIndex = index; ClassObject current = (ClassObject)classes.elementAt(index); String name = current.getName(); String supr = current.getSuperClass(); if (name != null) { classbox.setUpdate(); classbox.addItem(name); collabModel.addElement(name);

Page 59: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

59

} if (supr != null) { superclassbox.setUpdate(); superclassbox.addItem(supr); } } displayClass(0); } } } //Displays the selected class in the CRC Form public void displayClass(int index) { currentDisplayIndex = index; ClassObject currentClass =

(ClassObject)classes.elementAt(currentDisplayIndex); Integer id = new Integer(currentClass.getID()); idText.setText(id.toString()); classbox.setSelectedItem(currentClass.getName()); String supername = currentClass.getSuperClass(); superclassbox.setSelectedItem(currentClass.getSuperClass()); funcText.setText(currentClass.getFuncDesc()); innerModel = currentClass.getInnerClasses(); innerList.setModel(innerModel); responsModel = currentClass.getResponsibilities(); responsList.setModel(responsModel); attribModel = currentClass.getAttributes(); attribList.setModel(attribModel); Vector collabs = currentClass.getCollaborators(); if (collabs.isEmpty()) collabList.clearSelection(); else { int [] list = new int[collabs.size()]; int listIndex = 0; for (int i = 0; i < collabModel.getSize(); i++) { String listItem = (String)collabModel.getElementAt(i); if (collabs.contains(listItem)) { list[listIndex] = i; listIndex ++; } } collabList.setSelectedIndices(list); } repaint(); } public void displayClass(String name) { int index; for (index = 0; index < classes.size(); index++) { ClassObject current = (ClassObject) classes.elementAt(index); if (name.equals(current.getName())) break; } if (index < classes.size())

Page 60: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

60

displayClass(index); } //Displays a blank form public void displayBlank() { currentDisplayIndex = -1; idText.setText(""); classbox.setSelectedItem(null); superclassbox.setSelectedItem(null); funcText.setText(""); innerList.setModel(blankModel); repaint(); } protected ProjectModel projectModel; protected Vector classes; protected int currentDisplayIndex; } ClassObject.java import java.io.*; import java.lang.*; import java.util.*; import javax.swing.text.*; import javax.swing.*; /** * The object that holds all the information about an individual class. * These are stored in a vector in ProjectModel and manipulated by ClassForm. * */ class ClassObject extends Object implements Serializable { public ClassObject(int num) { IDNumber = num; InnerClasses = new DefaultListModel(); Responsibilities = new DefaultListModel(); Attributes = new DefaultListModel(); Collaborators = new Vector(); } public int getID() { return IDNumber; } public String getName() { return Name; } public String getSuperClass() { return SuperClass; }

Page 61: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

61

public String getFuncDesc() { return FuncDesc; } public DefaultListModel getInnerClasses() { return InnerClasses; } public DefaultListModel getResponsibilities() { return Responsibilities; } public Vector getCollaborators() { return Collaborators; } public void addCollaborator(String item) { Collaborators.add(item); } public void removeCollaborator(String item) { Collaborators.remove(item); } public void setCollaborators(Vector list) { Collaborators = list; } public DefaultListModel getAttributes() { return Attributes; } public void setName(String name) { Name = name; } public void setSuperClass(String name) { SuperClass = name; } public void setFuncDesc(String desc) { FuncDesc = desc; } public String toString() { return new String("Class: " + IDNumber + " name: " + Name + " super: " + SuperClass); } private int IDNumber; private String Name = null; private String SuperClass = null; private String FuncDesc; private DefaultListModel InnerClasses; private DefaultListModel Responsibilities;

Page 62: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

62

private DefaultListModel Attributes; private Vector Collaborators; public static final int NAME = 1; public static final int SUPER_CLASS = 2; public static final int FUNC_DESC = 3; public static final int INNER_CLASS = 4; public static final int RESPONSIBILITY = 5; public static final int COLLABORATION = 6; public static final int ATTRIBUTE = 7; } ClassToolBar.java import javax.swing.*; import java.awt.event.*; /** * The tool bar that contains the tools specific to the class diagram view. * */ class ClassToolBar extends DiagramToolBar { public ClassToolBar(DiagramCanvas target)

{ super(target); add(move);

add(square); add(text); add(connect);

add(resize); }

MoveButton move = new MoveButton (this.target);

SquareButton square = new SquareButton (this.target, "Draw class"); TextButton text = new TextButton (this.target); ConnectButton connect = new ConnectButton(this.target,

ConnectButton.classimage, "Draw association"); ResizeButton resize = new ResizeButton(this.target);

} CodeGenerator.java import java.util.*; import java.io.*; import javax.swing.*; /** * This class should maybe be renamed JavaCodeGenerator. * Writes skeleton code based on the Class vector in ProjectModel * implements observer so it knows if the project has changed since * code was last generated. */ class CodeGenerator implements Observer { public CodeGenerator (ProjectModel pm, CodeWindow cw) { projectModel = pm; messages = cw; hasChanged = false; calledGenerate = false; fileChooser = new JFileChooser();

Page 63: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

63

fileChooser.setFileSelectionMode(fileChooser.DIRECTORIES_ONLY); projectModel.addObserver(this); } public void update (Observable obs, Object arg) { Update codeUpdate = (Update)arg; int origin = codeUpdate.getOrigin(); switch (origin) { case (codeUpdate.PROJECT): case (codeUpdate.CLASS_FORM): case (codeUpdate.CLASS_DIAGRAM): case (codeUpdate.SEQUENCE_DIAGRAM): case (codeUpdate.TREE_CO): hasChanged = true; if (calledGenerate) { projectModel.setCodeState(hasChanged); Update generated = new Update(Update.CODE_GENERATOR,

-1, 0,0,"true"); projectModel.registerChange(); projectModel.notifyObservers(generated); } break; case (codeUpdate.OPEN): hasChanged = ! projectModel.getCodeState(); break; default: break; } } public void generateCode() { calledGenerate = true; JTextArea messageArea = messages.getCodeArea(); //there have been changes to the model since code was last generated

if (hasChanged) { //if code has been generated before,

//sets the previously used directory as the default if (pathDirectory != null) fileChooser.setSelectedFile(pathDirectory); int returnVal = fileChooser.showDialog(messages,

"Choose code location"); //user has picked a directory

if (returnVal == JFileChooser.APPROVE_OPTION) { pathDirectory = fileChooser.getSelectedFile(); messageArea.setText("Code being generated in: "

+ pathDirectory.toString() + "\n"); String projectName = projectModel.getName(); File codeDirectory = new File(pathDirectory,

projectName + " code"); codeDirectory.mkdir(); messageArea.append("Directory created: " +

codeDirectory.toString() + "\n"); messageArea.append("\nGenerating skeleton code...\n"); Vector classes = projectModel.getClasses(); for (int i =0; i < classes.size(); i++) { ClassObject current = (ClassObject)classes.elementAt(i); String className = current.getName(); if (className == null)

Page 64: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

64

className = "NewClass" + current.getID(); try { out = new PrintWriter(new FileOutputStream(codeDirectory

+ "\\" + className + ".java")); } catch (IOException e) { System.out.println("File error: " + e); } functionDescription(current); classDeclaration(className, current.getSuperClass()); constructor(className); attributes(current); responsibilities(current); innerClasses(current); end(); out.close(); messageArea.append(className + ".java" + " generated.\n"); } messageArea.append("...done."); hasChanged = false; projectModel.setCodeState(hasChanged); Update generated = new Update(Update.CODE_GENERATOR,

-1, 0,0,"false"); projectModel.registerChange(); projectModel.notifyObservers(generated); } //user didn't select a directory in which to generate

//code or user selected "cancel" else

messageArea.setText("Generate code command cancelled by user.\n"); } else //model hasn't changed since code was last updated. messageArea.setText("There have been no updates

since code was last generated."); } protected void functionDescription (ClassObject current) { out.println("//import java packages" ); out.println(""); out.println("/** " + current.getFuncDesc()); out.println(" */"); } protected void classDeclaration (String name, String superclass) { if (!(superclass == null)) { superclass = " extends " + superclass; out.println("class " + name + superclass); } else out.println("class " + name); } protected void constructor (String name) { out.println("{ //constructor"); out.println(indent + "public " + name + " ()"); out.println(indent + "{"); out.println(indent + "}"); out.println("");

Page 65: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

65

} protected void attributes (ClassObject current) { DefaultListModel attribs = current.getAttributes(); out.println(indent + "//attributes"); for (int i = 0; i< attribs.getSize(); i++) { String member = (String)attribs.getElementAt(i); out.println(indent + member); } out.println(""); } protected void responsibilities (ClassObject current) { out.println(indent + "//responsibilities" ); DefaultListModel response = current.getResponsibilities(); for (int i = 0; i< response.getSize(); i++) { String function = (String)response.getElementAt(i); out.println(indent + "public void " + function + " ()"); out.println(indent + "{"); out.println(indent + "}"); out.println(""); } } protected void innerClasses (ClassObject current) { out.println(indent + "//inner classes"); DefaultListModel inClasses = current.getInnerClasses(); for (int i = 0; i< inClasses.getSize(); i++) { String inner = (String)inClasses.getElementAt(i); out.println(indent + "class " + inner); out.println(indent + "{ //constructor"); out.println(indent + indent + "public " + inner + " ()"); out.println(indent + indent + "{"); out.println(indent + indent + "}"); out.println(indent + "}"); out.println(""); } } protected void end() { out.println("}"); } public File getPath() { return pathDirectory; } private ProjectModel projectModel; private boolean hasChanged; private boolean calledGenerate; private CodeWindow messages = null; private JFileChooser fileChooser; private File pathDirectory; private PrintWriter out; private String indent = " "; }

Page 66: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

66

CodeWindow.java import java.awt.*; import javax.swing.*; import java.util.*; /** * A window that displays status messages when code is being generated. */ public class CodeWindow extends JInternalFrame { public CodeWindow(ProjectModel pm)

{ super("Skeleton Code Generation Messages", true, true); setSize(400,400); getContentPane().setLayout(new BorderLayout());

code = new JTextArea(400,400); JScrollPane scrollPane = new JScrollPane(code); getContentPane().add(scrollPane); projectModel = pm;

}

public JTextArea getCodeArea() { return code; }

ProjectModel projectModel;

JTextArea code; } ConnectButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Tool bar button, action listener that changes mode so connections can * be drawn in diagram window. */ class ConnectButton extends ToolButton implements ActionListener { public ConnectButton (DiagramCanvas target, String imagename, String hint)

{ super (target,new ImageIcon(imagename), hint, target.CONNECT, Cursor.DEFAULT_CURSOR);

} public static final String usecaseimage = "images/connect.jpg"; public static final String classimage = "images/bentcnct.jpg"; public static final String sequenceimage = "images/message.jpg";

} Connection.java import java.math.*; import java.awt.*;

Page 67: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

67

/** * A figure that can be drawn in diagram views. Shows that two figures are * linked in some way. Based on a class written by J.Bergin for "PaintDrawApplet" 12.97 */ public class Connection extends Figure implements java.io.Serializable { protected Figure first;

protected Figure second;

public Connection(int ID, String label, Figure first, Figure second) { super(ID, label, 0, 0, 0, 0);

this.first = first; this.second = second; int wide = second.center().x - first.center().x; int high = second.center().y - first.center().y; if (wide < 0)

wide = -wide; if (high < 0)

high = -high; setBounds (first.center().x, first.center().y, wide, high);

} public void draw(Graphics g) { int x1 = first.center().x, y1 = first.center().y,

x2 = second.center().x, y2 = second.center().y; g.drawLine(x1, y1, x2, y2); Color c = g.getColor(); g.setColor(Color.red); if (label != null) { FontMetrics font = g.getFontMetrics();

int centerX = findMiddleX(x1 + x2,label,font); g.drawString(label, centerX, (y1 + y2)/2-2);

} g.setColor(c);

}

//checks if figure f is one part of a connection. public boolean checkConnect(Figure f) { if ((f.equals(first))||(f.equals(second)))

return true; else return false;

} public Figure getFirst() { return first; } public Figure getSecond() { return second; } public void drawOutline(Graphics g) { int x1 = first.center().x, y1 = first.center().y,

x2 = second.center().x, y2 = second.center().y;

Page 68: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

68

g.drawLine(x1, y1, x2, y2); }

} ControlWindow.java //Java-DACTL, Java Design, Analysis, and Coding TooL with UML //Anna S. Armentrout //Copyright (c) 1999 //Pace University import java.io.*; import java.util.zip.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.tree.*; import java.beans.*; /** * The "main" class. This class sets up the GUI and allows view windows * to be displayed. */ public class ControlWindow extends BaseFrame {

public static void main(String args[]) { try

{ UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName());

} catch(Exception e){} ControlWindow control = new ControlWindow ("Java-DACTL"); control.setVisible(true);

} public ControlWindow(String name) { super (name, DISPOSE_ON_CLOSE);

setSize(800,600); newItem = new NewMenuItem(); openItem = new OpenMenuItem(); closeItem = new CloseMenuItem(); saveItem = new SaveMenuItem(); saveItem.setEnabled(false);

printItem = new PrintMenuItem(); printItem.setEnabled(false);

exitItem = new ExitMenuItem(); fileMenu.add(newItem); fileMenu.add(openItem); fileMenu.add(closeItem); fileMenu.add(saveItem); fileMenu.add(printItem); fileMenu.add(exitItem);

Page 69: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

69

JMenu menu = new JMenu ("Project"); menu.setMnemonic(KeyEvent.VK_P); ucfItem = new UseCaseFormsItem();

ucfItem.setEnabled(false); ucdItem = new UseCaseDiagramItem();

ucdItem.setEnabled(false); classFormsItem = new ClassFormsItem();

classFormsItem.setEnabled(false); classDiagramItem = new ClassDiagramItem(); classDiagramItem.setEnabled(false);

sequenceItem = new SequenceItem(); sequenceItem.setEnabled(false);

codeItem = new CodeItem(); codeItem.setEnabled(false);

menu.add(ucfItem); menu.add(ucdItem); menu.add(classFormsItem); menu.add(classDiagramItem); menu.add(sequenceItem); menu.add(codeItem); menuBar.add(menu); //May be added later

//Would be nice if view windows on right could be "tiled" in some way //menu = new JMenu("Window");

//menu.setMnemonic(KeyEvent.VK_W); //menuBar.add(menu); //menu = new JMenu("Help"); //menu.setMnemonic(KeyEvent.VK_H); //menuBar.add(menu); scrollMenu = new JScrollPane();

scrollMenu.setPreferredSize(new Dimension(200,800)); windowArea = new JDesktopPane(); windowArea.putClientProperty("JDesktopPane.dragMode", "outline"); splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,

scrollMenu, windowArea); getContentPane().add(splitPane); addWindowListener(closer);

} // Anonymous inner class extending WindowAdapter.

//Handles the window close event. WindowListener closer = new WindowAdapter() { public void windowClosing(WindowEvent e)

{ dispose(); System.exit(0);

} };

NewMenuItem newItem;

Page 70: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

70

OpenMenuItem openItem; CloseMenuItem closeItem; SaveMenuItem saveItem; PrintMenuItem printItem; ExitMenuItem exitItem; UseCaseFormsItem ucfItem; UseCaseDiagramItem ucdItem; ClassFormsItem classFormsItem; ClassDiagramItem classDiagramItem; SequenceItem sequenceItem; CodeItem codeItem; JSplitPane splitPane; JScrollPane scrollMenu; JDesktopPane windowArea; UseCaseForm useCaseForm; UseCaseDiagramWindow useCaseDiagramWindow = null; ClassForm classForm;

ClassDiagramWindow classDiagramWindow = null; SequenceDiagramWindow sequenceDiagramWindow = null; CodeGenerator codeGenerator;

CodeWindow codeWindow; ProjectModel projectModel;

boolean viewsDone = false; File openFile; JFileChooser fileOpener; File saveFile; JFileChooser fileSaver; public void createViews() { useCaseForm = new UseCaseForm(projectModel); useCaseForm.setVisible(false); useCaseDiagramWindow =

new UseCaseDiagramWindow("Use Case Diagram", projectModel); useCaseDiagramWindow.setVisible(false); classForm = new ClassForm(projectModel); classForm.setVisible(false); classDiagramWindow =

new ClassDiagramWindow("Class Diagram", projectModel); classDiagramWindow.setVisible(false); sequenceDiagramWindow =

new SequenceDiagramWindow("Sequence Diagram", projectModel); sequenceDiagramWindow.setVisible(false); codeWindow = new CodeWindow(projectModel); codeGenerator = new CodeGenerator(projectModel, codeWindow); codeWindow.setVisible(false); windowArea.add(useCaseForm); windowArea.add(useCaseDiagramWindow); windowArea.add(classForm); windowArea.add(classDiagramWindow);

Page 71: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

71

windowArea.add(sequenceDiagramWindow); windowArea.add(codeWindow); } public void enOrDisAble(boolean enable) { saveItem.setEnabled(enable); printItem.setEnabled(enable); ucfItem.setEnabled(enable); ucdItem.setEnabled(enable); classFormsItem.setEnabled(enable); classDiagramItem.setEnabled(enable); sequenceItem.setEnabled(enable); codeItem.setEnabled(enable); }

class NewMenuItem extends JMenuItem implements ActionListener { public NewMenuItem() { super("New Project", KeyEvent.VK_N); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,

ActionEvent.CTRL_MASK)); addActionListener(this); } //Open a new project. (Should close any open project first) public void actionPerformed (ActionEvent e) { if (projectModel != null) closeItem.actionPerformed(new ActionEvent(this,

ActionEvent.ACTION_PERFORMED, "close")); //The model for this project projectModel = new ProjectModel(); //add the project name to the project model projectModel.setName("New Project"); ProjectMutableTreeNode treetop =

new ProjectMutableTreeNode(projectModel.getName(), projectModel.getID());

ProjectTree tree = new ProjectTree(treetop, projectModel); scrollMenu.setViewportView(tree); createViews();//(re)create all the various views. viewsDone = true; enOrDisAble(true); scrollMenu.setVisible(true); DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel(); treeModel.reload(); } } class OpenMenuItem extends JMenuItem implements ActionListener { public OpenMenuItem() { super("Open Project", KeyEvent.VK_O); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,

ActionEvent.CTRL_MASK));

Page 72: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

72

fileOpener = new JFileChooser(); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (projectModel != null) closeItem.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "close")); if (openFile != null) { fileOpener.setCurrentDirectory(openFile); fileOpener.setSelectedFile(openFile); } else if (saveFile != null) { fileOpener.setCurrentDirectory(saveFile); fileOpener.setSelectedFile(saveFile); } else { if (codeGenerator != null) { File path = codeGenerator.getPath(); if (path != null) fileOpener.setSelectedFile(path); } } int returnVal = fileOpener.showOpenDialog(ControlWindow.this); if (returnVal == JFileChooser.APPROVE_OPTION) { openFile = fileOpener.getSelectedFile(); try { FileInputStream fileIn = new FileInputStream(openFile); GZIPInputStream decompress = new GZIPInputStream(fileIn); ObjectInputStream in = new ObjectInputStream(decompress); try { projectModel = (ProjectModel)in.readObject(); ProjectMutableTreeNode treetop =

new ProjectMutableTreeNode(projectModel.getName(), projectModel.newID());

ProjectTree tree = new ProjectTree(treetop, projectModel); scrollMenu.setViewportView(tree); if (! viewsDone) { createViews(); viewsDone = true; } enOrDisAble(true); projectModel.registerChange(); Update open = new Update(Update.OPEN, 0,0,0,null); projectModel.notifyObservers(open); scrollMenu.setVisible(true); DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel(); treeModel.reload(); } catch(ClassNotFoundException cnfe) { System.out.println(cnfe); } }

Page 73: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

73

catch (IOException ioe) { System.out.println(ioe); } } } } class CloseMenuItem extends JMenuItem implements ActionListener { public CloseMenuItem() { super("Close Project", KeyEvent.VK_C); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { //save first then close Object[] options = { "Save","Don't Save","Don't Close"}; int n = JOptionPane.showOptionDialog(ControlWindow.this, "Save Project before closing?","Close Options", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]); switch (n) { case JOptionPane.YES_OPTION: saveItem.actionPerformed(new ActionEvent(this,

ActionEvent.ACTION_PERFORMED, "save")); case JOptionPane.NO_OPTION: projectModel = null; useCaseForm.setVisible(false); useCaseDiagramWindow.setVisible(false); classForm.setVisible(false); classDiagramWindow.setVisible(false); sequenceDiagramWindow.setVisible(false); codeWindow.setVisible(false); enOrDisAble(false); scrollMenu.setVisible(false); break; case JOptionPane.CANCEL_OPTION: break; } } } class SaveMenuItem extends JMenuItem implements ActionListener { public SaveMenuItem() { super("Save Project", KeyEvent.VK_S); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,

ActionEvent.CTRL_MASK)); fileSaver = new JFileChooser();

Page 74: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

74

addActionListener(this); } public void actionPerformed (ActionEvent e) { if (saveFile != null) { fileSaver.setCurrentDirectory(saveFile); fileSaver.setSelectedFile(saveFile); } else if (openFile != null) { fileSaver.setCurrentDirectory(openFile); fileSaver.setSelectedFile(openFile); } else { File path = codeGenerator.getPath(); if (path != null) fileSaver.setSelectedFile(path); } int returnVal = fileSaver.showSaveDialog(ControlWindow.this); if (returnVal == JFileChooser.APPROVE_OPTION) { saveFile = fileSaver.getSelectedFile(); try { FileOutputStream fileOut = new FileOutputStream(saveFile); GZIPOutputStream compress = new GZIPOutputStream(fileOut); ObjectOutputStream out = new ObjectOutputStream(compress); out.writeObject(projectModel); out.flush(); out.close(); } catch (IOException ioe) { System.out.println(ioe); } } } }

class PrintMenuItem extends JMenuItem implements ActionListener { public PrintMenuItem() { super("Print Current Window", KeyEvent.VK_P); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { } } class ExitMenuItem extends JMenuItem implements ActionListener { public ExitMenuItem() { super("Exit", KeyEvent.VK_X); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4,

ActionEvent.ALT_MASK));

Page 75: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

75

addActionListener(this); } public void actionPerformed (ActionEvent e) { int closeOp = getDefaultCloseOperation(); if (closeOp == DISPOSE_ON_CLOSE) { setVisible(false); dispose(); System.exit(0); } else setVisible(false); } } class UseCaseFormsItem extends JMenuItem implements ActionListener { public UseCaseFormsItem() { super("Use Case Forms", KeyEvent.VK_U); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (useCaseForm.isClosed()) { try { useCaseForm.setClosed(false); windowArea.add(useCaseForm); } catch(PropertyVetoException pve) { System.out.println("Error: unable to reopen Use Case Form.\n"); } } useCaseForm.setVisible(true); useCaseForm.moveToFront(); repaint(); } }

class UseCaseDiagramItem extends JMenuItem implements ActionListener

{ public UseCaseDiagramItem() { super("Use Case Diagram", KeyEvent.VK_C); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (useCaseDiagramWindow.isClosed()) { try { useCaseDiagramWindow.setClosed(false); windowArea.add(useCaseDiagramWindow); } catch (PropertyVetoException pve) { System.out.println("Error: unable to reopen Use Case

Page 76: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

76

Diagram Window.\n"); } } useCaseDiagramWindow.setVisible(true); useCaseDiagramWindow.moveToFront(); } }

class ClassFormsItem extends JMenuItem implements ActionListener { public ClassFormsItem() { super("Class Forms", KeyEvent.VK_F); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (classForm.isClosed()) { try { classForm.setClosed(false); windowArea.add(classForm); } catch(PropertyVetoException pve) { System.out.println("Error: unable to reopen Class Form."); } } classForm.setVisible(true); classForm.moveToFront(); repaint(); } }

class ClassDiagramItem extends JMenuItem implements ActionListener { public ClassDiagramItem() { super("Class Diagram", KeyEvent.VK_D); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (classDiagramWindow.isClosed()) { try { classDiagramWindow.setClosed(false); windowArea.add(classDiagramWindow); } catch (PropertyVetoException pve) { System.out.println("Error: unable to reopen

Class Diagram Window.\n"); } } classDiagramWindow.setVisible(true); classDiagramWindow.moveToFront(); }

Page 77: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

77

}

class SequenceItem extends JMenuItem implements ActionListener { public SequenceItem() { super("Sequence Diagram", KeyEvent.VK_S); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_5,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (sequenceDiagramWindow.isClosed()) { try { sequenceDiagramWindow.setClosed(false); windowArea.add(sequenceDiagramWindow); } catch (PropertyVetoException pve) { System.out.println("Error: unable to reopen

Sequence Diagram Window.\n"); } } sequenceDiagramWindow.setVisible(true); sequenceDiagramWindow.moveToFront(); } } class CodeItem extends JMenuItem implements ActionListener { public CodeItem() { super("Generate Code", KeyEvent.VK_G); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e) { if (codeWindow.isClosed()) { try { codeGenerator.generateCode(); codeWindow.setClosed(false); windowArea.add(codeWindow);

} catch (PropertyVetoException pve) { System.out.println("Error: unable to open Code Window."); }

} else codeGenerator.generateCode(); codeWindow.setVisible(true); codeWindow.moveToFront(); } } }

Page 78: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

78

DiagramCanvas.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; /** * The superclass of other diagram canvases. This class defines all * of the Key Listener behavior, which is the same in all the diagram views. * This class was expanded from a class written by J.Bergin "PaintDrawApplet" 12.97 */ class DiagramCanvas extends JComponent implements KeyListener, Observer { public DiagramCanvas(ProjectModel pm)

{ setBackground(Color.white); addKeyListener(this); mode = defaultmode; stringBuilder = new StringBuffer(""); projectModel = pm;

} public void update (Observable pm, Object arg) { } public void doLabelUpdate(String newLabel) { //overriden for each type of diagram canvas } public void doDeleteUpdate(boolean undo) {//overridden for each type of diagram canvas } public void doRestoreUpdate(Figure restoreItem) {//overridden for each type of diagram canvas } public void invalidate() { super.invalidate();

offscreen = null; } public void update (Graphics g) { if (doubleBuffering) paint (g);

else super.update(g); } public void flip(Figure f) { Graphics g = getGraphics();

g.setXORMode(getBackground()); f.drawOutline(g); g.dispose();

}

Page 79: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

79

private void doDraw(Graphics g) { Enumeration e = connections.elements();

while (e.hasMoreElements()) ((Figure) e.nextElement()).draw(g);

e=figures.elements(); while (e.hasMoreElements())

((Figure) e.nextElement()).draw(g); } public void paintComponent (Graphics g) { if (!doubleBuffering)

{ doDraw(g); return;

} Dimension d = getSize(); int h = d.height; int w = d.width; if (offscreen == null) { offscreen = createImage (w,h);

og = offscreen.getGraphics(); og.setColor(getBackground()); og.fillRect(0,0,w,h);

} og = offscreen.getGraphics(); og.setClip(0,0,w,h); doDraw(og); g.drawImage(offscreen, 0,0,null); og.setColor(getBackground()); og.fillRect(0,0,w,h); og.dispose();

}

public void keyPressed (KeyEvent e) { int pressed = e.getKeyCode();

switch (pressed) { case KeyEvent.VK_LEFT:

if (stringIndex > 0) stringIndex --;

else stringIndex = stringBuilder.length() - 1;

break;

case KeyEvent.VK_RIGHT: if (stringIndex >= 0)

stringIndex = stringIndex + 2; if (stringIndex >= stringBuilder.length())

stringIndex = -1; break;

case KeyEvent.VK_DELETE: deleteObject(false); break;

Page 80: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

80

default: break;

} } public void keyReleased (KeyEvent e) { } public void keyTyped (KeyEvent e) { e.consume();

char typed = e.getKeyChar(); switch (mode) { case TEXT:

char stringfrag; switch (typed) { case KeyEvent.VK_ENTER:

if (labelFigure != null) doLabelUpdate(stringBuilder.toString());

stringBuilder = new StringBuffer(""); firstLetter = false; labelFigure = null; stringIndex = -1; break;

case KeyEvent.VK_BACK_SPACE:

if (labelFigure != null) { if (firstLetter)

firstLetter = false; else { if (stringIndex < 0)

stringIndex = stringBuilder.length() - 1; if (stringIndex >= 0)

stringBuilder.deleteCharAt(stringIndex); stringIndex --;

} String changedlabel = stringBuilder.toString(); labelFigure.setLabel(changedlabel);

} break;

default: if (labelFigure != null) { if (firstLetter)

{ stringBuilder.append(labelFigure.getLabel()); firstLetter = false;

} stringfrag = e.getKeyChar(); if (stringIndex >= 0) { stringBuilder.insert(stringIndex + 1, stringfrag);

stringIndex ++; } else

stringBuilder.append(stringfrag);

Page 81: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

81

labelFigure.setLabel(stringBuilder.toString()); } break;

} repaint(); break;

default: break;

} } public boolean deleteObject(boolean undo) { if (selectedFigure != null)

{ doDeleteUpdate(undo); boolean connected = false; for (int index = 0; index < connections.size(); index++) { Connection c = (Connection)connections.elementAt(index);

connected = c.checkConnect(selectedFigure); if (connected) { connections.removeElement(c);

index--; if (undo)

deletes.push(c); connected = false;

} } if (undo)

deletes.push(selectedFigure); figures.removeElement(selectedFigure);

} repaint(); selectedFigure = null; return !(deletes.empty());

} public boolean undoDeleteObject() { Figure restore = (Figure)deletes.pop();

figures.addElement((Object)restore); doRestoreUpdate(restore); while (!(deletes.empty())) { restore = (Figure)deletes.peek();

if (restore instanceof Connection) { connections.addElement(restore);

deletes.pop(); doRestoreUpdate(restore);

} else break;

} repaint(); return !(deletes.empty());

}

public void changeMode(int newmode) { if (mode == TEXT)

Page 82: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

82

{ if (labelFigure != null) doLabelUpdate(stringBuilder.toString());

} mode = newmode; selectedFigure = null; labelFigure = null;

} private Image offscreen = null; private final boolean doubleBuffering = true; Graphics og; // The offscreen graphics context.

protected Figure selectedFigure = null; protected Figure labelFigure = null; protected boolean firstLetter = false; protected StringBuffer stringBuilder; protected int stringIndex; protected boolean dragging = false; protected Vector figures = new Vector(); protected Vector connections = new Vector(); protected Stack deletes = new Stack(); protected Vector projectObjects; protected Stack deletedObjects = new Stack(); protected int mode; protected Cursor drawCursor; protected ProjectModel projectModel; public static final int defaultmode = 1; public static final int MOVE = 1; public static final int TEXT = 2; public static final int SQUARE = 3; public static final int OVAL = 4; public static final int ACTOR = 5; public static final int CONNECT = 6; public static final int RESIZE = 7; public static final int LIFELINE = 8;

} DiagramToolBar.java import javax.swing.*; /** * The superclass of all diagram tool bars. This class sets up the * canvas that should respond to any tool actions. */ class DiagramToolBar extends JToolBar { public DiagramToolBar(DiagramCanvas target)

{ super(JToolBar.VERTICAL); this.target = target;

}

public DiagramCanvas target; }

Page 83: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

83

DiagramWindow.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** * The superclass of all diagram windows. This class sets up the menus * and the "cut" and "undo" actions. */ public class DiagramWindow extends BaseInternalFrame implements KeyListener, Runnable { public DiagramWindow(String name)

{ super (name); undoMenuItem = new UndoMenuItem(); editMenu.add(undoMenuItem); CutMenuItem item = new CutMenuItem (); editMenu.add(item); addKeyListener(this); run(); }

DiagramCanvas usercanvas; static final boolean undo = true;

private boolean enabled = false; private UndoMenuItem undoMenuItem; public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DELETE) usercanvas.deleteObject(!undo); } public void keyReleased(KeyEvent e)

{ } public void keyTyped(KeyEvent e) { }

public void run() { } class CutMenuItem extends JMenuItem implements ActionListener { public CutMenuItem() { super("Cut", KeyEvent.VK_C); setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,

ActionEvent.CTRL_MASK)); addActionListener(this); } public void actionPerformed (ActionEvent e)

Page 84: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

84

{ enabled = usercanvas.deleteObject(undo); undoMenuItem.setEnabled(enabled); } } class UndoMenuItem extends JMenuItem implements ActionListener

{ public UndoMenuItem() { super("Undo", KeyEvent.VK_U);

setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));

addActionListener(this); setEnabled(enabled);

}

public void actionPerformed (ActionEvent e) { enabled = usercanvas.undoDeleteObject();

setEnabled(enabled); }

} } Figure.java import java.awt.*; /** * This class was adapted from Figure.java from J.Bergin's * "PaintDrawApplet" 12.97 * It is the superclass of all figures in the diagram views. * Each figure knows its own ID number and draws its own label. */ public abstract class Figure implements java.io.Serializable { protected Rectangle bounds;

protected String label; protected int IDNumber; protected boolean selected = false; public Figure (int ID, int x, int y, int w, int h) { bounds = new Rectangle (x,y,w,h);

IDNumber = ID; } public Figure(int ID, String label, int x, int y, int w, int h) { bounds = new Rectangle(x, y, w, h);

this.label = label; IDNumber = ID;

} public String getLabel() { return label; } public void setLabel(String s) { label = s;

Page 85: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

85

} public int getID() { return IDNumber; } public int findMiddleX(int width, String label, FontMetrics font) { int labelwidth = font.stringWidth(label);

int beginningofmiddle = width/2 - labelwidth/2; return beginningofmiddle;

} public int findMiddleY(int itemheight, FontMetrics font) { int labelheight = font.getHeight();

int bottomofmiddle = itemheight/2 + labelheight/4; return bottomofmiddle;

} public void setBounds(int x, int y, int w, int h) { bounds = new Rectangle (x,y,w,h); } public void setBounds(int w, int h) { bounds.setSize(w,h); } public Rectangle getBounds() { return bounds; } public void setLocation(Point p) { bounds.setLocation(p); } public void setLocation(int x, int y) { bounds.setLocation(x,y); } public abstract void draw(Graphics g); public abstract void drawOutline(Graphics g); public Connection connect(int ID, String label, Figure b) { return new Connection(ID, label, this, b); } public boolean isSelected(){ return selected;} public void setSelected(boolean t){selected = t;} public void toggleSelected(){selected = !selected;} public void drawSelectors(Graphics g) { g.fillRect(bounds.x - 2 , bounds.y - 2, 4, 4);

g.fillRect(bounds.x + bounds.width - 2 , bounds.y-2, 4, 4); g.fillRect(bounds.x-2 , bounds.y + bounds.height - 2, 4, 4); g.fillRect(bounds.x + bounds.width - 2 ,

Page 86: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

86

bounds.y + bounds.height - 2, 4, 4); } public Rectangle rectangle(){ return bounds; } public Point location(){ return new Point(bounds.x, bounds.y); } public Point center(){ return new Point(bounds.x+bounds.width/2,

bounds.y+bounds.height/2); } public Dimension dimension(){ return new Dimension(bounds.width,

bounds.height);} public void move(int x, int y) { bounds.setLocation(x,y); } public void move(Point p) { bounds.setLocation(p); } public boolean contains(Point p) { return bounds.contains(p); } public boolean contains(int x, int y) { return bounds.contains(x, y); } public boolean contains(Figure f) { Rectangle figbounds = f.getBounds();

return bounds.contains(figbounds); }

} LabelChange.java import java.lang.*; /** * This is the encapsulation of two strings. Both the old and new name * need to be known for certain name change updates. */ public class LabelChange { public LabelChange (String oldLabel, String newLabel)

{ this.oldLabel = oldLabel; this.newLabel = newLabel;

}

public String getOld() { return oldLabel; } public String getNew() { return newLabel; }

Page 87: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

87

private String oldLabel; private String newLabel;

} LifelineButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This is a GUI element that changes the mode in the incomplete * sequence diagram view. */ class LifelineButton extends ToolButton implements ActionListener { public LifelineButton (DiagramCanvas target)

{ super (target,image, "Draw object lifeline", target.LIFELINE, Cursor.DEFAULT_CURSOR);

} public static final ImageIcon image =

new ImageIcon("images/lifeline.jpg"); } MoveButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This is a GUI element that allows the mode of a diagram canvas to * be changed so that a figure can be moved around. */ class MoveButton extends ToolButton implements ActionListener { public MoveButton (DiagramCanvas target)

{ super (target,image, "Move", target.MOVE, Cursor.MOVE_CURSOR); } private static final ImageIcon image = new ImageIcon("images/move.jpg");

} OvalButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Changes diagram mode so user can draw an oval. */ class OvalButton extends ToolButton implements ActionListener

Page 88: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

88

{ public OvalButton (DiagramCanvas target) { super (target,image, "Draw use case", target.OVAL,

Cursor.CROSSHAIR_CURSOR); } private static final ImageIcon image = new ImageIcon("images/oval.jpg");

} OvalFigure.java import java.awt.*; /** * Oval figures have ID numbers that correspond to the ID numbers of * Use Cases in the use case vector of the project model. They are * diagramatic representations of use cases. This class was elaborated from a * class written by J.Bergin for "PaintDrawApplet" 12.97 * see@ Figure */ public class OvalFigure extends Figure implements java.io.Serializable { public OvalFigure(int ID, String label, int x, int y, int w, int h)

{ super(ID, label, x, y, w, h); } public void draw(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawOval(x, y, w, h); Color c = g.getColor(); g.setColor(Color.white); g.fillOval(x+1, y+1, w - 2, h - 2); g.setColor(Color.red); if (label != null) { FontMetrics font = g.getFontMetrics();

int centerX = findMiddleX(w,label,font); int centerY = findMiddleY(h,font); g.drawString(label, x + centerX, y + centerY);

} g.setColor(c); if(selected) drawSelectors(g);

} public void drawOutline(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawOval(x, y, w, h); }

} ProjectModel.java //Java-DACTL, Java Design, Analysis, and Coding TooL with UML //Anna S. Armentrout //September 1999 //Copyright (c) 1999

Page 89: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

89

//Pace University import java.util.*; import java.io.*; /** * The "heart" of the modeling tool, this is the model. Project model keeps * track of the additions and changes made in all the views, and alerts the * views of changes made. A fairly simple class, most changes are recorded in * the vitally important use case and class vectors by the views */ class ProjectModel extends Observable implements Serializable { public ProjectModel ()

{ IDTag = 0; useCases = new Vector(); classes = new Vector();

codeCurrent = true; projectID = newID();

} public int newID() { int current = IDTag;

IDTag ++; return current;

}

public int getID() { return projectID; }

public synchronized void setName(String name) { projectName = name; }

public String getName() { return projectName; }

public synchronized Vector getUseCases() { return useCases; } public synchronized Vector getClasses() { return classes; }

public void setCodeState(boolean changed) { codeCurrent = !changed; } public boolean getCodeState() { return codeCurrent; }

Page 90: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

90

//access to private variable public void registerChange() { setChanged(); }

//Find a use case in the use case vector public UseCase findUseCase(int IDnumber) { for (int i = 0; i < useCases.size(); i++) { UseCase current = (UseCase)useCases.elementAt(i); if (current.getID() == IDnumber) return current; } return null; } //Find a class in the class vector public ClassObject findClass(int IDnumber) { for (int i = 0; i < classes.size(); i++) { ClassObject current = (ClassObject)classes.elementAt(i); if (current.getID() == IDnumber) return current; } return null; } private int IDTag;

private String projectName; private int projectID;

private Vector useCases; private Vector classes;

private boolean codeCurrent; } ProjectMutableTreeNode.java import javax.swing.tree.*; /** * A node in the Project Tree. * see@ ProjectTree */ public class ProjectMutableTreeNode extends DefaultMutableTreeNode { public ProjectMutableTreeNode(String name, int ID) { super (name); IDnumber = ID; } public int getID() { return IDnumber; } private int IDnumber; }

Page 91: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

91

ProjectTree.java //Java-DACTL, Java Design, Analysis, and Coding TooL with UML //Anna S. Armentrout //September 1999 //Copyright (c) 1999 //Pace University import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.tree.*; import javax.swing.event.*; import java.util.*; /** * This tree is an overview of the project, and is displayed on the left side * of the GUI at all times. Is updated as user changes and adds to project. * see@ ProjectMutableTreeNode */ public class ProjectTree extends JTree implements Observer, TreeSelectionListener, KeyListener { public ProjectTree(ProjectMutableTreeNode topnode, ProjectModel pm)

{ super(topnode); setCellRenderer(new CodeChangeRenderer()); top = topnode; projectModel = pm; treeModel = (DefaultTreeModel)this.getModel(); setEditable(true); getSelectionModel().setSelectionMode(

TreeSelectionModel.SINGLE_TREE_SELECTION); putClientProperty("JTree.lineStyle", "Angled"); setShowsRootHandles(true); addTreeSelectionListener(this); addKeyListener(this); projectModel.addObserver(this); }

ProjectModel projectModel;

DefaultTreeModel treeModel; ProjectMutableTreeNode selectedNode = null; ProjectMutableTreeNode top; ProjectMutableTreeNode usecaseNode = null; ProjectMutableTreeNode classNode = null; ProjectMutableTreeNode sequenceNode = null; ProjectMutableTreeNode codeNode = null; String oldNodeName = null; String codeCurrent = "Code is up-to-date."; String codeObsolete = "Code could be refreshed."; public ProjectMutableTreeNode findNode(int ID,

ProjectMutableTreeNode typeNode) { ProjectMutableTreeNode foundNode = (ProjectMutableTreeNode)typeNode.getFirstChild(); while (foundNode != null)

Page 92: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

92

{ if (foundNode.getID() == ID) break; foundNode = (ProjectMutableTreeNode)typeNode.getChildAfter

(foundNode); } return foundNode; } public void valueChanged(TreeSelectionEvent e) { ProjectMutableTreeNode node; node = (ProjectMutableTreeNode)(e.getPath().getLastPathComponent()); selectedNode = node; oldNodeName = (String)node.getUserObject(); } public void keyPressed (KeyEvent e) { } public void keyReleased (KeyEvent e) { } public void keyTyped (KeyEvent e) { char typed = e.getKeyChar(); if (typed == KeyEvent.VK_ENTER) { if (selectedNode != null) { Update nameChanged = null; int ID = selectedNode.getID(); String newName = (String)selectedNode.getUserObject(); //Naming a use case if (oldNodeName.equals("New Use Case")) { UseCase nameUC = projectModel.findUseCase(ID); nameUC.setName(newName); nameChanged = new Update(Update.TREE_UC, ID, Update.CHANGE,

UseCase.NAME, newName); } //Naming a class else if (oldNodeName.equals("New Class")) { ClassObject nameClass = projectModel.findClass(ID); nameClass.setName(newName); nameChanged = new Update(Update.TREE_CO, ID, Update.CHANGE,

ClassObject.NAME, newName); } //Naming a sequence diagram else if (oldNodeName.equals("New Sequence Diagram")) { } //These names can't be changed else if ( (oldNodeName.equals("Use Cases")) || (oldNodeName.equals("Classes")) || (oldNodeName.equals("Sequence Diagrams")) || (oldNodeName.equals(codeCurrent)) || (oldNodeName.equals(codeObsolete)) )

Page 93: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

93

selectedNode.setUserObject(oldNodeName); //Renaming the project else if (selectedNode.equals(top)) { projectModel.setName(newName); nameChanged = new Update(Update.TREE_UC, ID, Update.CHANGE,

0, newName); } //The node had a name previously and it is being changed else { ProjectMutableTreeNode parent =

(ProjectMutableTreeNode)selectedNode.getParent(); //use case name is being changed if (parent.equals(usecaseNode)) { UseCase nameUC = projectModel.findUseCase(ID); nameUC.setName(newName); nameChanged = new Update(Update.TREE_UC, ID, Update.CHANGE,

UseCase.NAME, new LabelChange(oldNodeName, newName)); } //class name is being changed else if (parent.equals(classNode)) { ClassObject nameClass = projectModel.findClass(ID); nameClass.setName(newName); nameChanged = new Update(Update.TREE_CO, ID, Update.CHANGE,

ClassObject.NAME, new LabelChange(oldNodeName, newName)); } //sequence diagram name is being changed else if (parent.equals(sequenceNode)) {//changing the name of a sequence diagram } else { ProjectMutableTreeNode grandparent =

(ProjectMutableTreeNode)parent.getParent(); //name of an inner class is being changed if (grandparent.equals(classNode)) nameChanged = new Update(Update.TREE_CO, parent.getID(),

Update.CHANGE, ClassObject.INNER_CLASS,

new LabelChange(oldNodeName, newName)); } } //if one of the above cases was true if (nameChanged != null) { projectModel.registerChange(); projectModel.notifyObservers(nameChanged); } } } oldNodeName = null; selectedNode = null; }

public void update(Observable pm, Object arg) { Update treeUpdate = (Update)arg;

int origin = treeUpdate.getOrigin();

Page 94: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

94

int action = treeUpdate.getAction(); switch (origin) { case Update.USE_CASE_FORM: case Update.USE_CASE_DIAGRAM: if (action == Update.ADD) { if (treeUpdate.getField() == 0) { if (usecaseNode == null) { usecaseNode = new ProjectMutableTreeNode("Use Cases", projectModel.newID()); treeModel.insertNodeInto(usecaseNode, top,

top.getChildCount()); } UseCase newUC = (UseCase)treeUpdate.getArg(); ProjectMutableTreeNode newNode =

new ProjectMutableTreeNode("New Use Case", treeUpdate.getID());

treeModel.insertNodeInto(newNode, usecaseNode, usecaseNode.getChildCount());

} } else if (action == Update.CHANGE) { if (treeUpdate.getField() == UseCase.NAME) { int findID = treeUpdate.getID(); ProjectMutableTreeNode changeNode = findNode(findID,

usecaseNode); if (changeNode != null) { if (treeUpdate.getArg() instanceof String) changeNode.setUserObject(treeUpdate.getArg()); else { LabelChange lc = (LabelChange)treeUpdate.getArg(); changeNode.setUserObject(lc.getNew()); } } } treeModel.reload(); } else if (action == Update.DELETE) { if (treeUpdate.getField() != UseCase.ACTOR) { int deleteID = treeUpdate.getID(); ProjectMutableTreeNode deleteNode = findNode(deleteID, usecaseNode); if (deleteNode != null) treeModel.removeNodeFromParent(deleteNode); } } break; case Update.CLASS_FORM: case Update.CLASS_DIAGRAM: if (action == Update.ADD) { if (treeUpdate.getField() == 0) { if (classNode == null) { classNode = new ProjectMutableTreeNode("Classes", projectModel.newID());

Page 95: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

95

treeModel.insertNodeInto(classNode, top, top.getChildCount());

} ClassObject newClass = (ClassObject)treeUpdate.getArg(); String name = newClass.getName(); if (name == null) name = "New Class"; ProjectMutableTreeNode newNode =

new ProjectMutableTreeNode(name, treeUpdate.getID()); treeModel.insertNodeInto(newNode, classNode,

classNode.getChildCount()); } else if (treeUpdate.getField() == ClassObject.INNER_CLASS) { int parentID = treeUpdate.getID(); ProjectMutableTreeNode parentNode = findNode(parentID, classNode); if (parentNode != null) { ProjectMutableTreeNode newNode =

new ProjectMutableTreeNode((String)treeUpdate.getArg(), projectModel.newID());

treeModel.insertNodeInto(newNode, parentNode, parentNode.getChildCount());

} } } else if (action == Update.CHANGE) { if (treeUpdate.getField() == ClassObject.NAME) { int findID = treeUpdate.getID(); ProjectMutableTreeNode changeNode = findNode(findID,

classNode); if (changeNode != null) { if (treeUpdate.getArg() instanceof String) changeNode.setUserObject(treeUpdate.getArg()); else { LabelChange lc = (LabelChange)treeUpdate.getArg(); changeNode.setUserObject(lc.getNew()); } } } else if (treeUpdate.getField() == ClassObject.INNER_CLASS) { } treeModel.reload(); } else if (action == Update.DELETE) { if (treeUpdate.getField() == 0) { int deleteID = treeUpdate.getID(); ProjectMutableTreeNode deleteNode = findNode(deleteID,

classNode); if (deleteNode != null) treeModel.removeNodeFromParent(deleteNode); } if (treeUpdate.getField() == ClassObject.INNER_CLASS) { int parentID = treeUpdate.getID();

Page 96: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

96

ProjectMutableTreeNode parent = findNode(parentID, classNode);

if (parent != null) { String innerClass = (String)treeUpdate.getArg(); ProjectMutableTreeNode innerNode = (ProjectMutableTreeNode)parent.getFirstChild(); while (innerNode != null) { String checkString = (String)innerNode.getUserObject(); if (checkString.equals(innerClass)) break; innerNode =(ProjectMutableTreeNode)

parent.getChildAfter(innerNode); } if (innerNode != null) treeModel.removeNodeFromParent(innerNode); } } } break; case Update.SEQUENCE_DIAGRAM: if (action == Update.ADD); else if (action == Update.CHANGE); else if (action == Update.DELETE); break; case Update.CODE_GENERATOR: String changed = (String)treeUpdate.getArg(); if (changed.equals("true")) { if (codeNode == null) { codeNode = new ProjectMutableTreeNode(codeObsolete,

projectModel.newID()); treeModel.insertNodeInto(codeNode, top, top.getChildCount()); } else codeNode.setUserObject(codeObsolete); } else { if (codeNode == null) { codeNode = new ProjectMutableTreeNode(codeCurrent,

projectModel.newID()); treeModel.insertNodeInto(codeNode, top, top.getChildCount()); } else codeNode.setUserObject(codeCurrent); } treeModel.reload(); break; case Update.OPEN: Vector objects = projectModel.getUseCases(); if (! objects.isEmpty()) { if (usecaseNode == null) { usecaseNode = new ProjectMutableTreeNode("Use Cases",

Page 97: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

97

projectModel.newID()); treeModel.insertNodeInto(usecaseNode, top,

top.getChildCount()); } for (int i = 0; i < objects.size(); i++) { UseCase current = (UseCase)objects.elementAt(i); String name = current.getName(); if (name == null) name = "New Use Case"; ProjectMutableTreeNode newNode =

new ProjectMutableTreeNode(name, current.getID()); treeModel.insertNodeInto(newNode, usecaseNode,

usecaseNode.getChildCount()); } } objects = projectModel.getClasses(); if (! objects.isEmpty()) { if (classNode == null) { classNode = new ProjectMutableTreeNode("Classes",

projectModel.newID()); treeModel.insertNodeInto(classNode, top,

top.getChildCount()); } for (int i = 0; i < objects.size(); i++) { ClassObject current = (ClassObject)objects.elementAt(i); String name = current.getName(); if (name == null) name = "New Class"; ProjectMutableTreeNode newNode =

new ProjectMutableTreeNode(name, current.getID()); treeModel.insertNodeInto(newNode, classNode,

classNode.getChildCount()); DefaultListModel inner = current.getInnerClasses(); if (! inner.isEmpty()) { for (int index = 0; index < inner.getSize(); index ++) { String innerName = (String)inner.getElementAt(index); ProjectMutableTreeNode innerNode =

new ProjectMutableTreeNode(innerName, projectModel.newID());

treeModel.insertNodeInto(innerNode, newNode, newNode.getChildCount());

} } } } break; default: break; } } class CodeChangeRenderer extends DefaultTreeCellRenderer

Page 98: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

98

{ public CodeChangeRenderer() { changedIcon = new ImageIcon("images/redleaf.gif"); sameIcon = new ImageIcon("images/blueleaf.gif"); } ImageIcon changedIcon; ImageIcon sameIcon; private static final int RED = 0; private static final int BLUE = 1; private static final int REGULAR = 2; public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded,

leaf, row, hasFocus); if (leaf) { int type = isCodeNode(value); switch (type) { case RED: setIcon(changedIcon); break; case BLUE: setIcon(sameIcon); break; } } return this; } protected int isCodeNode(Object value) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; if (node.equals(codeNode)) { String name = (String)node.getUserObject(); if (name.equals(codeObsolete)) return RED; else if (name.equals(codeCurrent)) return BLUE; } return REGULAR; } } }

Page 99: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

99

ProjectTreeModelListener.java import java.io.*; import javax.swing.tree.*; import javax.swing.event.*; /** * Allows Tree to know if one of the nodes' names has been changed. * This code was adapted from the tutorial on Trees at * http://java.sun.com/docs/books/tutorial/uiswing/components/ * example-swing/DynamicTree.java * based on an example by Richard Stanford. * see@ ProjectTree */ public class ProjectTreeModelListener implements TreeModelListener { public ProjectTreeModelListener() { super(); } public void treeStructureChanged(TreeModelEvent e) { } public void treeNodesInserted(TreeModelEvent e) { } public void treeNodesRemoved(TreeModelEvent e) { } public void treeNodesChanged(TreeModelEvent e) { ProjectMutableTreeNode node; node =

(ProjectMutableTreeNode)(e.getTreePath().getLastPathComponent()); /* * If the event lists children, then the changed * node is the child of the node we've already * gotten. Otherwise, the changed node and the * specified node are the same. */ try { int index = e.getChildIndices()[0]; node = (ProjectMutableTreeNode)(node.getChildAt(index)); } catch (NullPointerException exc) { System.out.println ("Null pointer"); } System.out.println("The user has finished editing the node."); System.out.println("New value: " + node.getUserObject()); } } RectangleFigure.java

Page 100: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

100

import java.awt.*; /** * Rectangle figures have ID numbers that correspond to the ID numbers of * Classes in the class vector of the project model. They are diagramatic * representations of classes. This class was elaborated from a class written * by J.Bergin for "PaintDrawApplet" 12.97 * see@ Figure */ public class RectangleFigure extends Figure implements java.io.Serializable { public RectangleFigure(int ID, String label, int x, int y, int w, int h)

{ super(ID, label, x, y, w, h); } public void draw(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawRect(x, y, w, h); Color c = g.getColor(); g.setColor(Color.white); g.fillRect(x+1, y+1, w - 1, h - 1); g.setColor(Color.red); if (label != null) { FontMetrics font = g.getFontMetrics();

int centerX = findMiddleX(w,label,font); int centerY = findMiddleY(h,font); g.drawString(label, x + centerX, y + centerY);

} g.setColor(c); if(selected) drawSelectors(g);

} public void drawOutline(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawRect(x, y, w, h); }

} ResizeButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Allows the user to change the mode in the current diagram canvas so that * they can change the dimensions of a figure. */ class ResizeButton extends ToolButton implements ActionListener { public ResizeButton (DiagramCanvas target)

{ super (target,image, "Resize figure", target.RESIZE, Cursor.DEFAULT_CURSOR);

}

Page 101: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

101

private static final ImageIcon image = new ImageIcon("images/resize.jpg");

} SequenceDiagramCanvas.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; /** * Canvas where sequence diagrams would be drawn. Allows user to show * interactions between objects. Sequence diagrams are currently not fully * implemented. */ class SequenceDiagramCanvas extends DiagramCanvas implements MouseMotionListener, MouseListener { public SequenceDiagramCanvas(ProjectModel pm)

{ super (pm); addMouseMotionListener(this); addMouseListener(this);

} public void mouseClicked(MouseEvent e) { boolean doDraw = false;

switch (mode) { case MOVE:

Point p = e.getPoint(); Enumeration v = figures.elements(); selectedFigure = null; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { if(! f.isSelected())

{ doDraw = true; f.setSelected(true); selectedFigure = f;

} } else { if(f.isSelected())

{ doDraw = true; f.setSelected(false);

} }

} break;

case SQUARE: p = e.getPoint(); int ID = projectModel.newID(); RectangleFigure project = new RectangleFigure(ID, null, p.x,

Page 102: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

102

p.y,100,100); figures.add (project); doDraw = true; break;

case OVAL: p = e.getPoint(); ID = projectModel.newID(); OvalFigure usecase = new OvalFigure(ID, null, p.x, p.y, 60, 30); figures.add(usecase); doDraw = true; break;

case CONNECT:

p = e.getPoint(); v = figures.elements(); selectedFigure = null; doDraw = false; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { if (one == null)

one = f; else if (two == null) { doDraw = true;

two = f; ID = projectModel.newID(); Connection c = new Connection (ID, null, one, two); connections.add(c); one = null; two = null;

} }

} break;

case TEXT:

requestFocus(); stringBuilder = new StringBuffer(""); p = e.getPoint(); v = figures.elements(); labelFigure = null; stringIndex = -1; doDraw = false; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null)

firstLetter = true; }

} if (!doDraw)

Page 103: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

103

{ v = connections.elements(); while (v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if (f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null)

firstLetter = true; }

} } break;

} if (doDraw)

repaint(); } public void mouseDragged(MouseEvent e) { e.consume();

switch (mode) { case MOVE:

if(dragging) { flip(selectedFigure);

selectedFigure.move(e.getPoint()); flip(selectedFigure);

} break;

case SQUARE: Point secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); int width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } int height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

RectangleFigure project = new RectangleFigure(ID, null, originPoint.x, originPoint.y,width,height);

figures.add (project); selectedFigure = project;

} else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

Page 104: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

104

case OVAL: secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

OvalFigure usecase = new OvalFigure (ID, null, originPoint.x, originPoint.y,width,height);

figures.add (usecase); selectedFigure = usecase;

} else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

case RESIZE:

if (selectedFigure instanceof ActorFigure) break;

else if (dragging) { Point p = e.getPoint();

int cursortype = drawCursor.getType(); Rectangle figbounds = selectedFigure.getBounds(); int differenceX; int differenceY; switch (cursortype) { case drawCursor.N_RESIZE_CURSOR:

differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(figbounds.width,

figbounds.height + differenceY); break;

case drawCursor.S_RESIZE_CURSOR:

differenceY = p.y - figbounds.y; selectedFigure.setBounds(figbounds.width, differenceY); break;

case drawCursor.E_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; selectedFigure.setBounds(differenceX, figbounds.height); break;

case drawCursor.W_RESIZE_CURSOR:

Page 105: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

105

differenceX = figbounds.x - p.x; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height); break;

case drawCursor.NW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(p.x, p.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height + differenceY); break;

case drawCursor.NE_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(differenceX,

figbounds.height + differenceY); break;

case drawCursor.SE_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; differenceY = p.y - figbounds.y; selectedFigure.setBounds(differenceX, differenceY); break;

case drawCursor.SW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = p.y - figbounds.y; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

differenceY); break;

} } break;

} repaint();

}

public void mouseMoved(MouseEvent e) { e.consume();

if (mode == RESIZE) { Point p = e.getPoint();

Enumeration v = figures.elements(); selectedFigure = null; boolean doDraw = false; int resultcursor = drawCursor.DEFAULT_CURSOR; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { int x = f.getBounds().x;

Page 106: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

106

int y = f.getBounds().y; int xw = f.getBounds().x + f.getBounds().width - 1; int yh = f.getBounds().y + f.getBounds().height - 1; boolean N = false; boolean S = false; boolean E = false; boolean W = false; if (p.x == x)

W = true; if (p.x == xw)

E = true; if (p.y == y)

N = true; if (p.y == yh)

S = true; if (N && W)

resultcursor = drawCursor.NW_RESIZE_CURSOR; else if (S && E)

resultcursor = drawCursor.SE_RESIZE_CURSOR; else if (S && W)

resultcursor = drawCursor.SW_RESIZE_CURSOR; else if (N && E)

resultcursor = drawCursor.NE_RESIZE_CURSOR; else if (W)

resultcursor = drawCursor.W_RESIZE_CURSOR; else if (E)

resultcursor = drawCursor.E_RESIZE_CURSOR; else if (N)

resultcursor = drawCursor.N_RESIZE_CURSOR; else if (S)

resultcursor = drawCursor.S_RESIZE_CURSOR; selectedFigure = f;

} drawCursor = drawCursor.getPredefinedCursor(resultcursor); setCursor(drawCursor);

} }

}

public void mousePressed(MouseEvent e) { e.consume();

switch (mode) { case MOVE:

if(selectedFigure != null && selectedFigure.contains(e.getPoint())) dragging = true; break;

case SQUARE: case OVAL:

selectedFigure = null; Point firstPoint = e.getPoint(); firstPointX = firstPoint.x; firstPointY = firstPoint.y; break;

Page 107: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

107

case ACTOR:

int ID = projectModel.newID(); ActorFigure actor = new ActorFigure(ID, null, e.getX(), e.getY(),

50, 50); figures.add(actor); invalidate(); repaint(); break;

case RESIZE:

int cursortype = drawCursor.getType(); if (cursortype != drawCursor.DEFAULT_CURSOR)

dragging = true; break;

case CONNECT: case TEXT: default:

break; }

}

public void mouseEntered(MouseEvent e) { }

public void mouseExited(MouseEvent e) { } public void mouseReleased(MouseEvent e) { e.consume();

dragging = false; }

private Figure one = null; private Figure two = null; private int firstPointX; private int firstPointY; private Point originPoint;

} SequenceDiagramWindow.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*;

Page 108: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

108

/** * The window in which users would make sequence diagrams. * Sequence diagrams are currently not fully implemented. */ public class SequenceDiagramWindow extends DiagramWindow { public SequenceDiagramWindow(String name, ProjectModel pm)

{ super (name); usercanvas = new SequenceDiagramCanvas(pm); sequencetools = new SequenceToolBar(usercanvas); getContentPane().add(usercanvas);

getContentPane().add(sequencetools, BorderLayout.WEST); }

SequenceToolBar sequencetools; } SequenceToolBar.java import javax.swing.*; import java.awt.event.*; /** * Sets up the tools needed to create sequence diagrams. * Sequence diagrams are currently not fully implemented. */ class SequenceToolBar extends DiagramToolBar { public SequenceToolBar(DiagramCanvas target)

{ super(target); add(move);

add(square); add(text); add(connect); add(lifeline);

add(resize); }

MoveButton move = new MoveButton (this.target);

SquareButton square = new SquareButton (this.target, "Draw object"); TextButton text = new TextButton (this.target); ConnectButton connect = new ConnectButton(this.target,

ConnectButton.sequenceimage, "Draw message"); LifelineButton lifeline = new LifelineButton(this.target); ResizeButton resize = new ResizeButton(this.target);

} SquareButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A GUI element that changes the mode in the current diagram canvas, * allowing the user to draw a square.

Page 109: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

109

*/ class SquareButton extends ToolButton implements ActionListener { public SquareButton (DiagramCanvas target, String hint)

{ super (target,image, hint, target.SQUARE, Cursor.CROSSHAIR_CURSOR); } private static final ImageIcon image = new ImageIcon("images/square.jpg");

} SystemRectangleFigure.java import java.awt.*; /** * A special rectangle figure that represents the current project * in the use case diagram view. */ public class SystemRectangleFigure extends RectangleFigure { public SystemRectangleFigure(int ID, String label, int x, int y,

int w, int h) { super (ID, label, x, y, w, h); }

public void draw(Graphics g) { int x = bounds.x, y = bounds.y, h = bounds.height, w = bounds.width;

g.drawRect(x, y, w, h); Color c = g.getColor(); //g.setColor(Color.white); //g.fillRect(x+1, y+1, w - 1, h - 1); g.setColor(Color.red); if (label != null) { FontMetrics font = g.getFontMetrics();

int centerX = findMiddleX(w,label,font); g.drawString(label, x + centerX, y - 3);

} g.setColor(c); if(selected) drawSelectors(g);

} } TextButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This is a GUI element that changes the mode in a particular diagram view, * so that a figure can be labeled. */ class TextButton extends ToolButton implements ActionListener { public TextButton (DiagramCanvas target)

{ super (target,image, "Label", target.TEXT, Cursor.TEXT_CURSOR);

Page 110: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

110

} private static final ImageIcon image = new ImageIcon("images/label.jpg");

} ToolButton.java import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * A superclass for the buttons that are used in the various diagram views. */ class ToolButton extends JButton implements ActionListener { public ToolButton (DiagramCanvas target, ImageIcon image, String hinttext,

int modename, int cursor) { super ();

init(null, image); mycanvas = target; mymode = modename; mycursor = cursor; setToolTipText (hinttext); addActionListener (this);

}

public void actionPerformed (ActionEvent e) { mycanvas.changeMode(mymode); Cursor toolCursor = Cursor.getPredefinedCursor(mycursor); mycanvas.setCursor(toolCursor); }

protected DiagramCanvas mycanvas; protected int mymode; protected int mycursor;

} Update.java import java.lang.*; /** * This object encapsulates the information that is sent to all Observers * by the Observable (ProjectModel). The observers are able to determine * what kind of action to take based on this informtion. */ class Update extends Object { public Update(int location, int argID, int action, int field, Object arg)

{ origin = location; objectID = argID; this.action = action; this.field = field; changeObject = arg;

}

Page 111: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

111

public int getOrigin() { return origin; } public int getID() { return objectID; } public int getAction() { return action; } public int getField() { return field; } public Object getArg() { return changeObject; }

public String toString() { return new String("Origin: " + origin + " ID: " + objectID +

" Action: " + action); }

private int origin; public static final int PROJECT = 1; public static final int USE_CASE_FORM = 2; public static final int USE_CASE_DIAGRAM = 3; public static final int CLASS_FORM = 4; public static final int CLASS_DIAGRAM = 5; public static final int SEQUENCE_DIAGRAM = 6;

public static final int TREE_UC = 7; public static final int TREE_CO = 8; public static final int CODE_GENERATOR = 9; public static final int OPEN = 10;

private int objectID; private Object changeObject; private int field; private int action; public static final int ADD = 1; public static final int DELETE = 2; public static final int CHANGE = 3;

} UseCase.java import java.io.*; import java.lang.*; import javax.swing.text.*;

Page 112: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

112

/** * The object that holds all the information about an individual use case. * These are stored in a vector in ProjectModel and manipulated by * UseCaseForm. */ class UseCase extends Object implements Serializable { public UseCase(int num)

{ IDNumber = num; }

public int getID() { return IDNumber; } public String getName() { return Name; } public String getActor() { return Actor; } public String getPurpose() { return Purpose; } public String getDescription() { return Description; } public void setName(String name) { Name = name; } public void setActor(String actor) { Actor = actor; } public void setPurpose(String purpose) { Purpose = purpose; } public void setDescription(String desc) { Description = desc; } public String toString() { return new String("UseCase: " + IDNumber + " name: " + Name +

" actor: " + Actor); } private int IDNumber; private String Name = null; private String Actor = null;

Page 113: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

113

private String Purpose; private String Description; public static final int NAME = 1; public static final int ACTOR = 2; public static final int PURPOSE = 3; public static final int DESCRIPTION = 4;

} UseCaseDiagramCanvas.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; /** * Handles all mouse drawing events for UseCaseDiagram view. Key events are * handled by superclass, because key events for all diagram windows can * basically be handled in the same manner. * @see DiagramCanvas */ class UseCaseDiagramCanvas extends DiagramCanvas

implements MouseMotionListener, MouseListener { public UseCaseDiagramCanvas(ProjectModel pm)

{ super (pm); addMouseMotionListener(this); addMouseListener(this); projectObjects = projectModel.getUseCases(); projectModel.addObserver(this);

} public Figure findFigure(int IDnumber) { for (int i = 0; i < figures.size(); i++)

{ Figure current = (Figure)figures.elementAt(i); if (current.getID() == IDnumber)

return current; } return null;

}

/** Arrange the figures on the drawing canvas **/ public void arrange() { int actorCount = 0;

int usecaseCount = 0; //count number of respective elements in vector Enumeration v = figures.elements(); while (v.hasMoreElements()) { Figure current = (Figure)v.nextElement();

if (current instanceof ActorFigure) actorCount++;

else if (current instanceof OvalFigure) usecaseCount++;

Page 114: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

114

} //set number of columns based on number of usecases int numColumns; if (usecaseCount <= 6)

numColumns = 1; else if (usecaseCount <= 12)

numColumns = 2; else if (usecaseCount <= 21)

numColumns = 3; else numColumns = 4; //number of rows for usecases based on number of columns int numRows; numRows = usecaseCount / numColumns; if ((usecaseCount % numColumns) != 0)

numRows ++;

//This sections arranges all the elements in the figure vector //variables for actor figures boolean left = true; int actorRow = 0; //variables for usecase figures int usecaseColumn = 0; int usecaseRow = 0; //space between elements, and between top left edge of canvas and figure int gutter = 20; v = figures.elements(); while (v.hasMoreElements()) { int xpos;

int ypos; Figure current = (Figure)v.nextElement(); if (current instanceof ActorFigure) { if (left)

{ xpos = gutter; ypos = gutter + (actorRow * (actorHeight + gutter)); left = false;

} else { xpos = (2 * gutter) + actorWidth + (numColumns *

(gutter + usecaseWidth)); ypos = gutter + (actorRow * (actorHeight + gutter)); left = true; actorRow ++;

} } else if (current instanceof SystemRectangleFigure) { xpos = (gutter + (gutter / 2)) + actorWidth;

ypos = gutter; int width = (gutter * numColumns) + (usecaseWidth * numColumns); int height = (gutter * numRows) + (usecaseHeight * numRows); current.setBounds(width, height);

} else // current instanceof OvalFigure

Page 115: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

115

{ xpos = (gutter * 2) + actorWidth + (usecaseColumn * (usecaseWidth + gutter));

ypos = gutter + (gutter / 2) + (usecaseRow * (usecaseHeight + gutter));

usecaseColumn ++; if (usecaseColumn == numColumns) { usecaseColumn = 0;

usecaseRow ++; }

} current.setLocation(xpos, ypos);

} } /** Overridden update function **/ public void update (Observable pm, Object arg) { Update diagramUpdate = (Update)arg;

if ((diagramUpdate.getOrigin() == Update.USE_CASE_FORM) || (diagramUpdate.getOrigin() == Update.TREE_UC))

{ int action = diagramUpdate.getAction(); switch (action) { case diagramUpdate.ADD:

//add an actor (or name an existing one with no name) if (diagramUpdate.getField() == UseCase.ACTOR) { //if there is an existing UC this actor is associated with

if (diagramUpdate.getID() >= 0) { Figure actorsUseCase =

findFigure(diagramUpdate.getID());//find the UC ActorFigure actor = null; Connection special = null; //find any connection that might exist for (int i = 0; i < connections.size(); i++) { Connection check = (Connection)connections.elementAt(i);

if (check.checkConnect(actorsUseCase)) { special = check;

if (check.getFirst() instanceof ActorFigure) actor = (ActorFigure)check.getFirst();

else if (check.getSecond() instanceof ActorFigure) actor = (ActorFigure)check.getSecond();

} } if (actor != null) { String oldActorName = actor.getLabel();

if (oldActorName != null) { connections.removeElement(special); //get rid of old actor

actor = new ActorFigure(projectModel.newID(), (String)diagramUpdate.getArg(), 0,

0, actorWidth, actorHeight); figures.add(actor);//new actor figure Connection newConn = new Connection (projectModel.newID(),

null, actor, actorsUseCase); connections.add(newConn); //new connection

} else //use case is connected to a blank actor

Page 116: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

116

actor.setLabel((String)diagramUpdate.getArg()); } else //usecase is not connected to an actor { actor = new ActorFigure(projectModel.newID(),

(String)diagramUpdate.getArg(), 0, 0, actorWidth, actorHeight);

figures.add(actor); Connection newConn = new Connection(projectModel.newID(),

null, actor, actorsUseCase); connections.add(newConn);

} } else //no usecase associated with actor { ActorFigure actor = new ActorFigure(projectModel.newID(),

(String)diagramUpdate.getArg(), 0, 0, actorWidth, actorHeight);

figures.add(actor); } arrange(); repaint();

} else //add a use case { OvalFigure oval = new OvalFigure(diagramUpdate.getID(),

null, 0, 0, usecaseWidth, usecaseHeight); figures.add(oval); arrange(); repaint();

} break;

case diagramUpdate.CHANGE: if (diagramUpdate.getField() == UseCase.ACTOR) { Figure newActor = null;

String actor = (String)diagramUpdate.getArg(); ActorFigure changedActor = null; for (int i = 0; i < figures.size(); i++) { if (figures.elementAt(i) instanceof ActorFigure)

{ changedActor = (ActorFigure)figures.elementAt(i); if (actor.equals(changedActor.getLabel()))

break; }

} Figure oval = findFigure(diagramUpdate.getID()); Connection extra = null; for (int i = 0; i < connections.size(); i++) { Connection consider = (Connection)connections.elementAt(i);

if (consider.checkConnect(oval)) { extra = consider;

break; }

} connections.removeElement(extra); Connection connection = new Connection (projectModel.newID(),

null, changedActor, oval); connections.add(connection);

Page 117: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

117

repaint(); } else if (diagramUpdate.getField() == UseCase.NAME) { String name;

if (diagramUpdate.getArg() instanceof String) { name = (String)diagramUpdate.getArg();

}

else { LabelChange lc = (LabelChange)diagramUpdate.getArg(); name = (String)lc.getNew(); } OvalFigure changedOval =

(OvalFigure)findFigure(diagramUpdate.getID()); changedOval.setLabel(name); repaint(); }

break; case diagramUpdate.DELETE:

//can just delete whole use cases. OvalFigure deleteOval =

(OvalFigure)findFigure(diagramUpdate.getID()); Connection deleteConn = null; for (int i = 0; i < connections.size(); i++) { deleteConn = (Connection)connections.elementAt(i);

if (deleteConn.checkConnect(deleteOval)) break;

} connections.removeElement(deleteConn); figures.removeElement(deleteOval); repaint(); break;

default: break;

} }

else if (diagramUpdate.getOrigin() == diagramUpdate.OPEN) projectObjects = projectModel.getUseCases(); String projectName = projectModel.getName(); int projectID = projectModel.getID(); SystemRectangleFigure project = new SystemRectangleFigure(projectID,

projectName, 0, 0,250,250); figures.add(project); for (int i = 0; i < projectObjects.size(); i++) { UseCase current = (UseCase)projectObjects.elementAt(i); String name = current.getName(); int ovalID = current.getID(); OvalFigure usecase = new OvalFigure(ovalID, name, 0,0,

usecaseWidth, usecaseHeight); figures.add(usecase); String actor = current.getActor(); if (actor != null) { int actorID = projectModel.newID(); ActorFigure newActor = new ActorFigure(actorID, actor, 0,0,

Page 118: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

118

actorWidth, actorHeight); figures.add(newActor); Connection connect = new Connection(projectModel.newID(), null,

newActor, usecase); connections.add(connect); } actor = null; } arrange();

} public void doLabelUpdate(String newLabel) { Update labelUpdate = null;

int ID = -1; UseCase current; if (labelFigure instanceof ActorFigure) { if (connections.size() > 0)

{ Enumeration c = connections.elements(); while (c.hasMoreElements()) { Connection test = (Connection)c.nextElement();

if (test.checkConnect(labelFigure)) { Figure first = test.getFirst();

Figure second = test.getSecond(); if (first.equals(labelFigure))

current = projectModel.findUseCase(second.getID()); else

current = projectModel.findUseCase(first.getID()); ID = current.getID(); current.setActor(newLabel);

} }

} if (oldLabel != null) { LabelChange twoStrings = new LabelChange(oldLabel, newLabel);

labelUpdate = new Update(Update.USE_CASE_DIAGRAM, ID, Update.CHANGE, UseCase.ACTOR, twoStrings);

} else labelUpdate = new Update(Update.USE_CASE_DIAGRAM, ID, Update.ADD,

UseCase.ACTOR, newLabel); } else if (labelFigure instanceof OvalFigure) { ID = labelFigure.getID();

current = projectModel.findUseCase(ID); current.setName(newLabel); LabelChange newAndOld = new LabelChange(oldLabel, newLabel); labelUpdate = new Update(Update.USE_CASE_DIAGRAM, ID, Update.CHANGE,

UseCase.NAME, newAndOld); } oldLabel = null; projectModel.registerChange(); projectModel.notifyObservers(labelUpdate);

}

public void doDeleteUpdate(boolean undo)

Page 119: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

119

{ Update deleteUpdate = null; int ID = -1; UseCase current; if (selectedFigure instanceof ActorFigure) { Enumeration c = connections.elements();

while (c.hasMoreElements()) { Connection test = (Connection)c.nextElement();

if (test.checkConnect(selectedFigure)) { if (test.getFirst().equals(selectedFigure))

{ Figure second = test.getSecond(); current = projectModel.findUseCase(second.getID());

} else { Figure first = test.getFirst();

current = projectModel.findUseCase(first.getID()); } ID = current.getID(); current.setActor(null);

} } if (selectedFigure.getLabel() != null)

deleteUpdate = new Update (Update.USE_CASE_DIAGRAM, ID, Update.DELETE, UseCase.ACTOR, selectedFigure.getLabel());

} else if (selectedFigure instanceof OvalFigure) { ID = selectedFigure.getID();

current = projectModel.findUseCase(ID); if (undo)

deletedObjects.push(current); String deleteName = current.getName(); projectObjects.removeElement(current); deleteUpdate = new Update(Update.USE_CASE_DIAGRAM, ID, Update.DELETE,

0, deleteName); } if (deleteUpdate != null) { projectModel.registerChange();

projectModel.notifyObservers(deleteUpdate); }

} public void doRestoreUpdate(Figure restoreItem) { Update restoreUpdate = null;

if (restoreItem instanceof ActorFigure) restoreUpdate = new Update(Update.USE_CASE_DIAGRAM, -1, Update.ADD,

UseCase.ACTOR, restoreItem.getLabel()); else if (restoreItem instanceof OvalFigure) { UseCase restore = (UseCase)deletedObjects.pop();

projectObjects.add(restore); restoreUpdate = new Update(Update.USE_CASE_DIAGRAM, restore.getID(),

Update.ADD, 0, restore); } else if (restoreItem instanceof Connection) { Figure first = ((Connection)restoreItem).getFirst();

Page 120: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

120

Figure second = ((Connection)restoreItem).getSecond(); OvalFigure restoreFigure; String actorName; if (first instanceof ActorFigure) { restoreFigure = (OvalFigure)second;

actorName = first.getLabel(); } else { restoreFigure = (OvalFigure)first;

actorName = second.getLabel(); } UseCase changeActor = projectModel.findUseCase(restoreFigure.getID()); changeActor.setActor(actorName); restoreUpdate = new Update(Update.USE_CASE_DIAGRAM,

restoreFigure.getID(), Update.CHANGE, UseCase.ACTOR, actorName); } projectModel.registerChange(); projectModel.notifyObservers(restoreUpdate);

} public void mouseClicked(MouseEvent e) { boolean doDraw = false;

switch (mode) { case MOVE:

requestFocus(); Point p = e.getPoint(); Enumeration v = figures.elements(); selectedFigure = null; Figure containsP = null; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { if(! f.isSelected())

{ doDraw = true; if ((containsP == null)||(containsP.contains(f)))

containsP = f; }

} else { if(f.isSelected())

{ doDraw = true; f.setSelected(false);

} }

} if (containsP != null) { containsP.setSelected(true);

selectedFigure = containsP; } break;

case SQUARE: p = e.getPoint(); int ID = projectModel.newID();

Page 121: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

121

SystemRectangleFigure project = new SystemRectangleFigure(ID, null, p.x, p.y,250,250);

figures.add (project); doDraw = true; Update newProject = new Update(Update.PROJECT, ID, Update.ADD,

0, project); projectModel.registerChange(); projectModel.notifyObservers(newProject); break;

case OVAL: p = e.getPoint(); ID = projectModel.newID(); OvalFigure usecase = new OvalFigure(ID, null, p.x, p.y,

usecaseWidth, usecaseHeight); figures.add(usecase); doDraw = true; UseCase addUC = new UseCase(ID); projectObjects.add(addUC); Update newUseCase = new Update (Update.USE_CASE_DIAGRAM, ID,

Update.ADD, 0, addUC); projectModel.registerChange(); projectModel.notifyObservers(newUseCase); break;

case CONNECT:

p = e.getPoint(); v = figures.elements(); selectedFigure = null; doDraw = false; if (one == null) { while(v.hasMoreElements())

{ Figure f = (Figure)v.nextElement(); if(f.contains(p)) { if ((one == null)||(one.contains(f)))

one = f; }

} } else if (two == null) { while (v.hasMoreElements())

{ Figure f = (Figure)v.nextElement(); if (f.contains(p)) { if((two == null)||(two.contains(f)))

two = f; }

} if (one.equals(two)) { two = null;

break; } Figure actor = null; Figure modUseCase = null; if (one instanceof ActorFigure && two instanceof OvalFigure)

Page 122: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

122

{ actor = one; modUseCase = two;

} else if (one instanceof OvalFigure && two instanceof ActorFigure) { actor = two;

modUseCase = one; } if (actor != null) { doDraw = true;

ID = projectModel.newID(); Connection c = new Connection (ID, null, one, two); connections.add(c); String actorName = actor.getLabel(); if (actorName != null) { ID = modUseCase.getID();

int index; UseCase current = projectModel.findUseCase(ID); current.setActor(actorName); Update actorUpdate = new Update (Update.USE_CASE_DIAGRAM,

modUseCase.getID(), Update.CHANGE, UseCase.ACTOR, actorName);

projectModel.registerChange(); projectModel.notifyObservers(actorUpdate);

} } one = null; two = null;

} break;

case TEXT:

if (e.getClickCount() >= 2) { if (labelFigure != null)

doLabelUpdate(stringBuilder.toString()); requestFocus(); stringBuilder = new StringBuffer(""); p = e.getPoint(); v = figures.elements(); labelFigure = null; firstLetter = false; stringIndex = -1; doDraw = false; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null) { oldLabel = labelFigure.getLabel();

firstLetter = true; } break;

}

Page 123: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

123

} /** can't label connections if (!doDraw) { v = connections.elements();

while (v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if (f.contains(p)) { doDraw = true;

labelFigure = f; if (labelFigure.getLabel() != null)

firstLetter = true; }

} }**/ } break;

} if (doDraw)

repaint(); } public void mouseDragged(MouseEvent e) { e.consume();

switch (mode) { case MOVE:

if(dragging) { flip(selectedFigure);

selectedFigure.move(e.getPoint()); flip(selectedFigure);

} break;

case SQUARE: Point secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); int width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } int height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

SystemRectangleFigure project = new SystemRectangleFigure(ID, null, originPoint.x, originPoint.y,width,height);

figures.add (project); selectedFigure = project; Update newProject = new Update(Update.PROJECT, ID, Update.ADD,

0, project); projectModel.registerChange();

Page 124: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

124

projectModel.notifyObservers(newProject); } else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

case OVAL:

secondPoint = e.getPoint(); originPoint = new Point(firstPointX, firstPointY); width = secondPoint.x - firstPointX; if (width < 0) { width = -width;

originPoint.x = secondPoint.x; } height = secondPoint.y - firstPointY; if (height < 0) { height = -height;

originPoint.y = secondPoint.y; } if (selectedFigure == null) { int ID = projectModel.newID();

OvalFigure usecase = new OvalFigure (ID, null, originPoint.x, originPoint.y,width,height);

figures.add (usecase); selectedFigure = usecase; UseCase newUseCase = new UseCase(ID); projectObjects.add(newUseCase); Update useCaseUpdate = new Update(Update.USE_CASE_DIAGRAM, ID,

Update.ADD, 0, newUseCase); projectModel.registerChange(); projectModel.notifyObservers(useCaseUpdate);

} else { selectedFigure.setLocation(originPoint);

selectedFigure.setBounds(width, height); } break;

case RESIZE:

if (selectedFigure instanceof ActorFigure) break;

else if (dragging) { Point p = e.getPoint();

int cursortype = drawCursor.getType(); Rectangle figbounds = selectedFigure.getBounds(); int differenceX; int differenceY; switch (cursortype) { case drawCursor.N_RESIZE_CURSOR:

differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(figbounds.width,

Page 125: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

125

figbounds.height + differenceY); break;

case drawCursor.S_RESIZE_CURSOR:

differenceY = p.y - figbounds.y; selectedFigure.setBounds(figbounds.width, differenceY); break;

case drawCursor.E_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; selectedFigure.setBounds(differenceX, figbounds.height); break;

case drawCursor.W_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height); break;

case drawCursor.NW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(p.x, p.y); selectedFigure.setBounds(figbounds.width + differenceX,

figbounds.height + differenceY); break;

case drawCursor.NE_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; differenceY = figbounds.y - p.y; selectedFigure.setLocation(figbounds.x, p.y); selectedFigure.setBounds(differenceX,

figbounds.height + differenceY); break;

case drawCursor.SE_RESIZE_CURSOR:

differenceX = p.x - figbounds.x; differenceY = p.y - figbounds.y; selectedFigure.setBounds(differenceX, differenceY); break;

case drawCursor.SW_RESIZE_CURSOR:

differenceX = figbounds.x - p.x; differenceY = p.y - figbounds.y; selectedFigure.setLocation(p.x, figbounds.y); selectedFigure.setBounds(figbounds.width + differenceX,

differenceY); break;

} } break;

} repaint();

Page 126: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

126

}

public void mouseMoved(MouseEvent e) { e.consume();

if (mode == RESIZE) { Point p = e.getPoint();

Enumeration v = figures.elements(); selectedFigure = null; boolean doDraw = false; int resultcursor = drawCursor.DEFAULT_CURSOR; while(v.hasMoreElements()) { Figure f = (Figure)v.nextElement();

if(f.contains(p)) { int x = f.getBounds().x;

int y = f.getBounds().y; int xw = f.getBounds().x + f.getBounds().width - 1; int yh = f.getBounds().y + f.getBounds().height - 1; boolean N = false; boolean S = false; boolean E = false; boolean W = false; if (p.x == x)

W = true; if (p.x == xw)

E = true; if (p.y == y)

N = true; if (p.y == yh)

S = true; if (N && W)

resultcursor = drawCursor.NW_RESIZE_CURSOR; else if (S && E)

resultcursor = drawCursor.SE_RESIZE_CURSOR; else if (S && W)

resultcursor = drawCursor.SW_RESIZE_CURSOR; else if (N && E)

resultcursor = drawCursor.NE_RESIZE_CURSOR; else if (W)

resultcursor = drawCursor.W_RESIZE_CURSOR; else if (E)

resultcursor = drawCursor.E_RESIZE_CURSOR; else if (N)

resultcursor = drawCursor.N_RESIZE_CURSOR; else if (S)

resultcursor = drawCursor.S_RESIZE_CURSOR; selectedFigure = f;

} drawCursor = drawCursor.getPredefinedCursor(resultcursor); setCursor(drawCursor);

} }

}

public void mousePressed(MouseEvent e)

Page 127: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

127

{ e.consume(); switch (mode) { case MOVE:

if(selectedFigure != null && selectedFigure.contains(e.getPoint())) dragging = true; break;

case SQUARE: case OVAL:

selectedFigure = null; Point firstPoint = e.getPoint(); firstPointX = firstPoint.x; firstPointY = firstPoint.y; break;

case ACTOR: int ID = projectModel.newID(); ActorFigure actor = new ActorFigure(ID, null, e.getX(), e.getY(),

actorWidth, actorHeight); figures.add(actor); invalidate(); repaint(); break;

case RESIZE:

int cursortype = drawCursor.getType(); if (cursortype != drawCursor.DEFAULT_CURSOR)

dragging = true; break;

case CONNECT: case TEXT: default:

break; }

}

public void mouseEntered(MouseEvent e) { }

public void mouseExited(MouseEvent e) { } public void mouseReleased(MouseEvent e) { e.consume();

switch (mode) { case SQUARE:

case OVAL: if (selectedFigure != null) { Rectangle bounds = selectedFigure.getBounds();

if (bounds.height < 10)

Page 128: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

128

{ selectedFigure.setBounds(bounds.x, bounds.y, bounds.width, 10); repaint();

} bounds = selectedFigure.getBounds(); if (bounds.width < 10) { selectedFigure.setBounds(bounds.x, bounds.y, 10, bounds.height);

repaint(); }

} break;

default: break;

} dragging = false;

} private Figure one = null; private Figure two = null; private int firstPointX; private int firstPointY; private Point originPoint; private String oldLabel; private int actorHeight = 50; private int actorWidth = 50; private int usecaseHeight = 30; private int usecaseWidth = 60;

} UseCaseDiagramWindow.java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** * This window in which all the use case diagraming action occurs. * Sets up appropriate toolbar and drawing canvas * @see DiagramWindow */ public class UseCaseDiagramWindow extends DiagramWindow implements KeyListener { public UseCaseDiagramWindow(String name, ProjectModel pm)

{ super (name); usercanvas = new UseCaseDiagramCanvas(pm); usetools = new UseCaseToolBar(usercanvas); getContentPane().add(usercanvas); getContentPane().add(usetools, BorderLayout.WEST); }

UseCaseToolBar usetools;

Page 129: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

129

} UseCaseForm.java //Java-DACTL, Java Design, Analysis, and Coding TooL with UML //Anna S. Armentrout //September 1999 //Copyright (c) 1999 //Pace University import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; import javax.swing.plaf.basic.*; /** * This view window allows the user to add and revise * use cases. */ public class UseCaseForm extends JInternalFrame implements Observer { public UseCaseForm(ProjectModel pm)

{ super("Use Case", true, true, true, true); setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE); setSize(550,300);

setTitle("Use Case"); projectModel = pm; projectModel.addObserver(this); getContentPane().setLayout (new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints();

gbc.fill = gbc.NONE; gbc.ipady = 10; gbc.ipadx = 10; gbc.insets = new Insets (5,5,0,0);

//First column gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = gbc.EAST; //ID: label JLabel label = new JLabel ("ID #: "); getContentPane().add(label, gbc); //Actors: label gbc.gridy = 1; label = new JLabel("Actors: "); getContentPane().add(label,gbc); //Description: label gbc.gridy = 2; label = new JLabel("Description: "); getContentPane().add(label, gbc); //Back button gbc.gridy = 3; gbc.anchor = gbc.WEST;

Page 130: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

130

backButton = new BackButton(); backButton.setMargin(new Insets(1,1,1,1)); getContentPane().add (backButton, gbc); //Second column gbc.gridx = 1; gbc.gridy = 0; gbc.anchor = gbc.WEST; //ID text area idText = new JTextArea (1,3); idText.setEditable(false); getContentPane().add(idText, gbc); //Actor list gbc.gridy = 1; //actorList = new Vector(); actorlistbox = new ActorComboBox(); actorlistbox.setEditable(true); actorlistbox.setPreferredSize(new Dimension(120,15)); getContentPane().add(actorlistbox, gbc); //Description text area gbc.gridy = 2; gbc.gridwidth = 4; descText = new JTextArea(4,30); JScrollPane textscroll = new JScrollPane(descText); getContentPane().add(textscroll, gbc); //Delete button gbc.gridwidth = 1; gbc.gridy = 3; deleteButton = new DeleteButton(); getContentPane().add(deleteButton, gbc); //Third column gbc.gridx = 2; gbc.gridy = 0; gbc.anchor = gbc.EAST; //Name label label = new JLabel ("Name: "); getContentPane().add(label,gbc); //Purpose label gbc.gridy = 1; label = new JLabel("Purpose: "); getContentPane().add(label, gbc); //Fourth column gbc.gridx = 3; gbc.gridy = 0; gbc.anchor = gbc.WEST; gbc.gridwidth = 2; //Use case name list //usecaseList = new Vector(); usecaselistbox = new UseCaseComboBox(); usecaselistbox.setPreferredSize(new Dimension(200,15)); usecaselistbox.setEditable(true); getContentPane().add(usecaselistbox, gbc);

Page 131: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

131

//Purpose text area gbc.gridy = 1; purposeText = new JTextArea(3,15); textscroll = new JScrollPane(purposeText); getContentPane().add(textscroll, gbc); //New button gbc.gridy = 3; gbc.anchor = gbc.CENTER; newButton = new NewButton(); getContentPane().add(newButton, gbc); //Fifth column gbc.gridx = 4; gbc.gridy = 3; gbc.anchor = gbc.CENTER; gbc.gridwidth = 1; //Next button gbc.anchor = gbc.EAST; nextButton = new NextButton(); nextButton.setMargin(new Insets(1,1,1,1)); getContentPane().add (nextButton, gbc); useCases = projectModel.getUseCases(); currentDisplayIndex = -1;

} JTextArea idText; //Vector usecaseList; UseCaseComboBox usecaselistbox; //Vector actorList; ActorComboBox actorlistbox; JTextArea purposeText; JTextArea descText; BackButton backButton; NextButton nextButton; DeleteButton deleteButton; NewButton newButton;

//Save text in purpose text area if it has been revised public void savePurposeText() { if (currentDisplayIndex >=0)

{ Action actions[] = purposeText.getActions(); if (actions != null) { UseCase currentUC =

(UseCase)useCases.elementAt(currentDisplayIndex); currentUC.setPurpose(purposeText.getText()); Update updateUC = new Update(Update.USE_CASE_FORM,

currentUC.getID(), Update.CHANGE, UseCase.PURPOSE, purposeText.getText());

projectModel.registerChange(); projectModel.notifyObservers(updateUC);

}

Page 132: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

132

} } //Save text in description text area if it has been revised public void saveDescText() { if (currentDisplayIndex >=0)

{ Action actions[] = descText.getActions(); if (actions != null) { UseCase currentUC =

(UseCase)useCases.elementAt(currentDisplayIndex); currentUC.setDescription(descText.getText()); Update updateUC = new Update(Update.USE_CASE_FORM,

currentUC.getID(), Update.CHANGE, UseCase.DESCRIPTION, descText.getText());

projectModel.registerChange(); projectModel.notifyObservers(updateUC);

} }

} //Controls actions on the use case list box (selections, additions) class UseCaseComboBox extends JComboBox implements ActionListener { public UseCaseComboBox()

{ super(); addActionListener(this);

}

private boolean updateChange; public void setUpdate() { updateChange = true; }

public boolean findItem(String item) { for (int i = 0; i < getItemCount(); i++)

{ String test = (String)getItemAt(i); if (item.equals(test))

return true; } return false;

} public void actionPerformed (ActionEvent e) { String newItem = e.getActionCommand();

if (currentDisplayIndex >= 0) { if (newItem.equals("comboBoxChanged"))

{ String item = (String)getSelectedItem(); if (item != null)

displayUseCase(item); } else { if (findItem(newItem))

{ displayUseCase(newItem);

Page 133: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

133

} else { if (! newItem.equals(""))

{ UseCase currentUC = (UseCase)useCases.elementAt(currentDisplayIndex);

currentUC.setName(newItem); addItem(newItem);

displayUseCase(currentDisplayIndex); if (!updateChange) { Update updateUC = new Update(Update.USE_CASE_FORM,

currentUC.getID(), Update.CHANGE, UseCase.NAME, newItem);

projectModel.registerChange(); projectModel.notifyObservers(updateUC);

} }

} }

} }

} //Controls actions on the actor list box (selections, additions) class ActorComboBox extends JComboBox implements ActionListener { public ActorComboBox()

{ super(); addActionListener(this); updateChange = false;

} private boolean updateChange; public void setUpdate() { updateChange = true; } public boolean findItem(String item) { for (int i = 0; i < getItemCount(); i++)

{ String test = (String)getItemAt(i); if (item.equals(test))

return true; } return false;

} public void actionPerformed (ActionEvent e) { String newItem = e.getActionCommand();

UseCase currentUC = null; int ID = -1; if (newItem != null)//meaningless action { //could be adding an actor with no usecases yet

if (currentDisplayIndex >= 0) { currentUC = (UseCase)useCases.elementAt(currentDisplayIndex);

Page 134: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

134

ID = currentUC.getID(); }

//If comboBox is changing, new items must already have been added, //must be updating a use case if ((currentDisplayIndex >= 0) && (!updateChange)

&& (newItem.equals("comboBoxChanged"))) { String item = (String)getSelectedItem();

System.out.println("Selected Item:" + item +"."); if (!updateChange)

{ currentUC.setActor(item); Update updateUC = new Update(Update.USE_CASE_FORM, ID,

Update.CHANGE, UseCase.ACTOR, item); projectModel.registerChange(); projectModel.notifyObservers(updateUC);

} } else if (!(newItem.equals("comboBoxChanged"))) { if (findItem(newItem))//item is duplicate of previous item.

{ if (currentDisplayIndex >= 0) currentUC.setActor(newItem);

if (!updateChange) { Update updateUC = new Update(Update.USE_CASE_FORM, ID,

Update.CHANGE, UseCase.ACTOR, newItem); projectModel.registerChange(); projectModel.notifyObservers(updateUC);

} } else //completely new item { if (! newItem.equals(""))

{ setUpdate(); addItem(newItem);

} if (currentDisplayIndex >=0)

currentUC.setActor(newItem); if (!updateChange)

{ Update updateUC = new Update(Update.USE_CASE_FORM, ID, Update.ADD, UseCase.ACTOR, newItem);

projectModel.registerChange(); projectModel.notifyObservers(updateUC);

} }

} } updateChange = false;

} } //Controls actions on back arrow button //scrolls back one entry class BackButton extends JButton implements ActionListener

{ public BackButton() { super(); init (null, back); addActionListener(this);

Page 135: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

135

setToolTipText("Back"); } public final ImageIcon back = new ImageIcon("images/back.jpg"); public void actionPerformed(ActionEvent e) { savePurposeText();

saveDescText(); if (currentDisplayIndex > 0) displayUseCase(currentDisplayIndex - 1); }

} //Controls action on next arrow button //scrolls forward one entry class NextButton extends JButton implements ActionListener { public NextButton()

{ super(); init(null, next); addActionListener(this); setToolTipText("Next");

} public final ImageIcon next = new ImageIcon("images/next.jpg"); public void actionPerformed(ActionEvent e) { savePurposeText();

saveDescText(); if (currentDisplayIndex >= 0) { if (!(currentDisplayIndex + 1 >= useCases.size()))

displayUseCase(currentDisplayIndex + 1); }

} }

//Allows a use case to be deleted class DeleteButton extends JButton implements ActionListener { public DeleteButton()

{ super("Delete"); addActionListener(this);

} public void actionPerformed(ActionEvent e) { if (currentDisplayIndex >= 0)

{ UseCase currentUC = (UseCase) useCases.elementAt(currentDisplayIndex);

String name = currentUC.getName(); useCases.removeElementAt(currentDisplayIndex); if (name != null);

{ usecaselistbox.setUpdate(); usecaselistbox.removeItem(currentUC.getName());

usecaselistbox.setUpdate(); usecaselistbox.setSelectedItem(null); }

Page 136: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

136

if (useCases.size() > 0) displayUseCase(0);

else displayBlank();

projectModel.registerChange(); Update updateUC = new Update(Update.USE_CASE_FORM,

currentUC.getID(), Update.DELETE, 0, null); projectModel.notifyObservers(updateUC);

} }

}

//Allows a use case to be added class NewButton extends JButton implements ActionListener { public NewButton()

{ super("New"); addActionListener(this);

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

saveDescText(); int ID = projectModel.newID(); UseCase newUC = new UseCase(ID); useCases.add(newUC); Update updateUC = new Update(Update.USE_CASE_FORM, ID, Update.ADD,

0, newUC); projectModel.registerChange(); projectModel.notifyObservers(updateUC); displayUseCase(useCases.indexOf(newUC));

} }

public void update (Observable pm, Object arg) { Update useCaseUpdate = (Update) arg;

if ((useCaseUpdate.getOrigin() == useCaseUpdate.USE_CASE_DIAGRAM) || (useCaseUpdate.getOrigin() == useCaseUpdate.TREE_UC))

{ int act = useCaseUpdate.getAction(); switch (act) { case useCaseUpdate.ADD:

if (useCaseUpdate.getField() == UseCase.ACTOR) { String newItem = (String) useCaseUpdate.getArg();

actorlistbox.setUpdate(); actorlistbox.addItem(newItem); if (currentDisplayIndex >= 0)

displayUseCase(currentDisplayIndex); } else { UseCase newUC = (UseCase)useCaseUpdate.getArg();

int index = useCases.indexOf(newUC); displayUseCase(index);

} break;

Page 137: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

137

case useCaseUpdate.DELETE:

if (useCaseUpdate.getField() == UseCase.ACTOR) { String deleteName = (String)useCaseUpdate.getArg();

actorlistbox.setUpdate(); actorlistbox.removeItem((String)useCaseUpdate.getArg()); if (currentDisplayIndex >= 0)

displayUseCase(currentDisplayIndex); } else { String deleteItem = (String)useCaseUpdate.getArg();

if (deleteItem != null) usecaselistbox.removeItem(deleteItem);

if (useCases.size() > 0) displayUseCase(0);

else displayBlank();

} break;

case useCaseUpdate.CHANGE:

int ID = useCaseUpdate.getID(); int index = -1; if (ID >= 0) { UseCase changeField = projectModel.findUseCase(ID);

index = useCases.indexOf(changeField); currentDisplayIndex = index;

} if (useCaseUpdate.getArg() instanceof String) { if (useCaseUpdate.getField() == UseCase.ACTOR)

{ String newItem = (String)useCaseUpdate.getArg(); if (newItem != "")

{ actorlistbox.setUpdate(); actorlistbox.addItem(newItem); displayUseCase(currentDisplayIndex);

} } else if (useCaseUpdate.getField() == UseCase.NAME) { String newItem = (String)useCaseUpdate.getArg(); if (newItem != null) { usecaselistbox.setUpdate(); usecaselistbox.addItem(newItem); displayUseCase(currentDisplayIndex); } }

} else { LabelChange lc = (LabelChange)useCaseUpdate.getArg();

String oldItem = lc.getOld(); String newItem = lc.getNew(); if (newItem != null)

{ if (useCaseUpdate.getField() == UseCase.NAME) { usecaselistbox.setUpdate();

Page 138: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

138

usecaselistbox.removeItem(oldItem); usecaselistbox.setUpdate(); usecaselistbox.addItem(newItem);

displayUseCase(currentDisplayIndex); } else if (useCaseUpdate.getField() == UseCase.ACTOR) { actorlistbox.setUpdate(); actorlistbox.removeItem(oldItem);

actorlistbox.setUpdate(); actorlistbox.addItem(newItem);

if (index >= 0) displayUseCase(currentDisplayIndex);

} }

} break;

default: break;

} }

else if (useCaseUpdate.getOrigin() == useCaseUpdate.OPEN) { if (! useCases.isEmpty()) { for (int index = 0; index < useCases.size(); index++) { currentDisplayIndex = index; UseCase current = (UseCase)useCases.elementAt(index); String name = current.getName(); String actor = current.getActor(); if (name != null) { usecaselistbox.setUpdate(); usecaselistbox.addItem(name); } if (actor != null) { actorlistbox.setUpdate(); actorlistbox.addItem(actor); } } displayUseCase(0); } }

} //Displays the selected use case in the Use Case Form public void displayUseCase(int index) { currentDisplayIndex = index;

UseCase currentUC = (UseCase)useCases.elementAt(currentDisplayIndex); Integer id = new Integer(currentUC.getID()); idText.setText(id.toString()); //usecaselistbox.setUpdate();

usecaselistbox.setSelectedItem(currentUC.getName()); String actor = currentUC.getActor(); actorlistbox.setUpdate();

actorlistbox.setSelectedItem(currentUC.getActor()); purposeText.setText(currentUC.getPurpose());

Page 139: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

139

descText.setText(currentUC.getDescription()); repaint();

} public void displayUseCase(String name) { int index;

for (index = 0; index < useCases.size(); index++) { UseCase current = (UseCase) useCases.elementAt(index); if (name.equals(current.getName())) break; } if (index < useCases.size())

displayUseCase(index); }

//Displays a blank form public void displayBlank() { currentDisplayIndex = -1;

idText.setText(""); usecaselistbox.setSelectedItem(null); actorlistbox.setSelectedItem(null); purposeText.setText(""); descText.setText(""); repaint();

} protected ProjectModel projectModel; protected Vector useCases; protected int currentDisplayIndex;

} UseCaseToolBar.java import javax.swing.*; import java.awt.event.*; /** * The toolbar for the Use Case Diagram View. * Includes all the tools for drawing use case diagrams. * */ class UseCaseToolBar extends DiagramToolBar { public UseCaseToolBar(DiagramCanvas target)

{ super(target); add(move);

add(square); add(oval); add(actor); add(text); add(connect);

add(resize); }

MoveButton move = new MoveButton (this.target);

Page 140: Java- DACTL: A Tool for Teaching Novice Programmers to Design and

140

SquareButton square = new SquareButton (this.target, "Draw system"); OvalButton oval = new OvalButton (this.target); TextButton text = new TextButton (this.target); ActorButton actor = new ActorButton (this.target); ConnectButton connect = new ConnectButton(this.target,

ConnectButton.usecaseimage, "Draw connection"); ResizeButton resize = new ResizeButton(this.target);}