GUIClass.java
// Package Name
package views.components;
//System imports
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
//Local imports
import model.UMLClass;
import views.components.testable.TestableLabel;
import views.components.testable.TestablePanel;
import views.components.testable.TestableSeparator;
import model.Method;
import model.Field;
/**
* A GUI representation of a UML Class
* @author Ryan
*
*/
public class GUIClass extends TestablePanel {
private static final long serialVersionUID = 1L;
// Instance of UMLClass
private UMLClass umlClass;
// Title of class
private JLabel className;
// Class Properties
// - Maps name to the corresponding label
private HashMap<String, JLabel> fieldLabels;
private HashMap<String, JLabel> methodLabels;
// Store separators to toggle visibility
private JSeparator fieldSeparator;
private JSeparator methodSeparator;
// Regions
private JPanel fieldRegion;
private JPanel methodRegion;
private boolean human;
/**
* Initialize a graphical view of a given UMLClass
* @param umlClass
*/
public GUIClass(UMLClass umlClass) {
super(false);
startOps(umlClass);
}
// For human
public GUIClass(UMLClass umlClass, boolean human) {
super(human);
this.human = human;
startOps(umlClass);
}
private void startOps(UMLClass umlClass) {
this.umlClass = umlClass;
// Initialize label maps
fieldLabels = new HashMap<String, JLabel>();
methodLabels = new HashMap<String, JLabel>();
// Set layout to be a vertical box layout
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
// Initialize region panels, with a vertical BoxLayout
fieldRegion = new TestablePanel(human);
fieldRegion.setLayout(new BoxLayout(fieldRegion, BoxLayout.Y_AXIS));
methodRegion = new TestablePanel(human);
methodRegion.setLayout(new BoxLayout(methodRegion, BoxLayout.Y_AXIS));
// Add a label of the class name
className = generateLabel(umlClass.getName());
className.setFont(className.getFont().deriveFont(Font.BOLD));
add(className);
// Initialize separators
fieldSeparator = generateSeparator(Color.BLACK);
methodSeparator = generateSeparator(Color.BLACK);
// Add separators and regions
add(fieldSeparator);
add(fieldRegion);
add(methodSeparator);
add(methodRegion);
// Set visibility of separators
fieldSeparator.setVisible(false);
methodSeparator.setVisible(false);
// Set the location given the classes location
setLocation(umlClass.getX(), umlClass.getY());
// Add padding and a border
if(human) {
Border padding = BorderFactory.createEmptyBorder(10, 10, 10, 10);
Border outline = BorderFactory.createLineBorder(Color.BLACK, 2);
setBorder(BorderFactory.createCompoundBorder(outline, padding));
}
// Update the box bounds
updateBounds();
// Update fields and methods
updateFields();
updateMethods();
}
/**
* Update the size and bounds of the box
*/
public void updateBounds() {
setSize(getPreferredSize());
setBounds(getX(), getY(), getWidth(), getHeight());
}
/**
* Set the location of the class
*/
public void setLocation(int x, int y) {
super.setLocation(x, y);
updateBounds();
umlClass.setLocation(x, y);
}
/**
* Generate a centered JLabel
* @param text - The label text
* @return - JLabel instance
*/
public JLabel generateLabel(String text) {
JLabel temp = (human) ? new JLabel(text) : new TestableLabel(text);
temp.setAlignmentX(Component.CENTER_ALIGNMENT);
temp.setAlignmentY(Component.TOP_ALIGNMENT);
return temp;
}
/**
* Generate a horizontal separator
* @return - JSeparator instance
*/
public JSeparator generateSeparator(Color c) {
JSeparator mySep = (human) ? new JSeparator(SwingConstants.HORIZONTAL) : new TestableSeparator();
mySep.setAlignmentY(TOP_ALIGNMENT);
mySep.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, c));
return mySep;
}
/**
* Check to make sure the method labels match the class representation.
* This should be called every time the DiagramPanel is notified of a class change
*/
public void updateMethods() {
// Loop through list of class methods
// Check to see if there is a method in the class that is not a label
// If so then add it to the panel
for(Map.Entry<String, Method> entry : umlClass.getMethods().entrySet()) {
Method method = entry.getValue();
if(!methodLabels.containsKey(entry.getKey())) {
JLabel temp = generateLabel(method.toString());
methodLabels.put(entry.getKey(), temp);
// Add label to display
methodRegion.add(temp);
}
}
// Check to see if there is a label that is not in the class
// If so then remove it from the panel
// Map iterator
Iterator<Map.Entry<String, JLabel>> entryIt = methodLabels.entrySet().iterator();
// Iterate over elements
while(entryIt.hasNext()) {
// Get entry
Map.Entry<String, JLabel> entry = entryIt.next();
// Get the label name
String key = entry.getKey();
// Check if label is not in class list
if(!umlClass.getMethods().containsKey(key)) {
// Remove label from display
methodRegion.remove(entry.getValue());
// Remove method
entryIt.remove();
}
}
// Check if need to change field separator visibility
if(methodLabels.size() > 0 && !methodSeparator.isVisible())
methodSeparator.setVisible(true);
else if(methodLabels.size() == 0 && methodSeparator.isVisible())
methodSeparator.setVisible(false);
validate();
repaint();
updateBounds();
}
/**
* Check to make sure the field labels match the class representation.
* This should be called every time the DiagramPanel is notified of a class change
*/
public void updateFields() {
// Loop through list of class methods
// Check to see if there is a field in the class that is not a label
// If so then add it to the panel
for(Map.Entry<String, Field> entry : umlClass.getFields().entrySet()) {
Field field = entry.getValue();
if(!fieldLabels.containsKey(entry.getKey())) {
JLabel temp = generateLabel(field.toString());
fieldLabels.put(entry.getKey(), temp);
// Add label to display
fieldRegion.add(temp);
}
}
// Check to see if there is a label that is not in the class
// If so then remove it from the panel
// Map iterator
Iterator<Map.Entry<String, JLabel>> entryIt = fieldLabels.entrySet().iterator();
// Iterate over elements
while(entryIt.hasNext()) {
// Get entry
Map.Entry<String, JLabel> entry = entryIt.next();
// Get the label name
String name = entry.getKey();
// Check if label is not in class list
if(!umlClass.hasField(name)) {
// Remove label from display
fieldRegion.remove(entry.getValue());
// Remove field
entryIt.remove();
}
}
// Check if need to change field separator visibility
if(fieldLabels.size() > 0 && !fieldSeparator.isVisible())
fieldSeparator.setVisible(true);
else if(fieldLabels.size() == 0 && fieldSeparator.isVisible())
fieldSeparator.setVisible(false);
validate();
repaint();
updateBounds();
}
/**
* Get the name of the represented class
* @return - UMLClass name
*/
public String getName() {
return umlClass.getName();
}
/**
* Refresh the class name
*/
public void updateName() {
className.setText(umlClass.getName());
validate();
repaint();
updateBounds();
}
}