Stanford CS106A FacePamphlet Solution

Wow, I cannot believe that I’ve gotten all the way to the end of this class!! I actually just finished FacePamphlet and couldn’t me more excited.

So, without further adiu, here is my solution the last Stanford CS106, which you can also find on github.

FacePamphlet.java

/* 
 * File: FacePamphlet.java
 * -----------------------
 * When it is finished, this program will implement a basic social network
 * management system.
 */

import acm.program.*;
import acm.graphics.*;
import acm.util.*;
import java.awt.event.*;
import javax.swing.*;

public class FacePamphlet extends Program 
					implements FacePamphletConstants {

	/* Private instance variables*/
	//text fields
	private JTextField name;
	private JTextField status;
	private JTextField picture;
	private JTextField friend;
	
	//creates a new database and a new canvas
	private FacePamphletDatabase profileInfo = new FacePamphletDatabase();
	private FacePamphletCanvas canvas = new FacePamphletCanvas();
	
	//keeps track of the current profile
	private FacePamphletProfile currentProfile = null;
	
	
	/**
	 * This method has the responsibility for initializing the 
	 * interactors in the application, and taking care of any other 
	 * initialization that needs to be performed.
	 */
	public void init() {
		
		//fields on the North Side of the screen
		add(new JLabel("Name "), NORTH); 
		
		name = new JTextField(TEXT_FIELD_SIZE);
		add(name, NORTH);
		
		add(new JButton("Add"), NORTH);
		
		add(new JButton("Delete"), NORTH);
		
		add(new JButton("Lookup"), NORTH);
		
		//fields on the West Side of the screen
		status = new JTextField(TEXT_FIELD_SIZE);
		add(status, WEST);
		
		add(new JButton("Change Status"), WEST);
		
		add(new JLabel(EMPTY_LABEL_TEXT), WEST); //space holder
		
		picture = new JTextField(TEXT_FIELD_SIZE);
		add(picture, WEST);
		
		add(new JButton("Change Picture"), WEST);
		
		add(new JLabel(EMPTY_LABEL_TEXT), WEST); //space holder
		
		friend = new JTextField(TEXT_FIELD_SIZE);
		add(friend, WEST);
		
		add(new JButton("Add Friend"), WEST);
		
		//Action listeners
		addActionListeners();
		status.addActionListener(this);
		picture.addActionListener(this);
		friend.addActionListener(this);
		
		add(canvas);
    }
  
    /**
     * This class is responsible for detecting when the buttons are
     * clicked or interactors are used, so you will have to add code
     * to respond to these actions.
     */
	
    public void actionPerformed(ActionEvent e) {
    	
    	String enteredName = name.getText();
    	
    	//Add button is clicked
    	if(e.getActionCommand().equals("Add") && !name.getText().equals("")) {
    		//if the entered name does not exist in the database, a profile is created
    		if(profileInfo.containsProfile(enteredName) == false) {
    			FacePamphletProfile profile = new FacePamphletProfile(enteredName);
    			profileInfo.addProfile(profile);
    			canvas.displayProfile(profile);
    			canvas.showMessage("New profile created");
    			currentProfile = profile;
    		}
    		//if the entered name is already an existing profile, displays the profile
    		//and tells the user that the profile already exists
    		else{
    			FacePamphletProfile profile = profileInfo.getProfile(enteredName);
    			canvas.displayProfile(profile);
    			canvas.showMessage("A profile with name " + enteredName + " already exists.");
    			currentProfile = profile;
    		}
    	}
    	
    	//Delete button is clicked
    	else if (e.getActionCommand().equals("Delete") && !name.getText().equals("")){
    		//clears the canvas and sets the current profile to null
    		canvas.removeAll();
    		currentProfile = null;
    		//if the entered name exists as a profile, the profile is deleted
    		if(profileInfo.containsProfile(enteredName) == true) {
    			profileInfo.deleteProfile(enteredName);
    			canvas.showMessage("Profile of " + enteredName + " deleted");
    		}
    		//if the entered name is not an actual profile, tells the user 
    		//that the profile does not exist
    		else{
    			canvas.showMessage("A profile with name " + enteredName + " does not exist.");
    		}
    	}
    	
    	//Lookup button is clicked
    	else if (e.getActionCommand().equals("Lookup") && !name.getText().equals("")){
    		canvas.removeAll(); //clears everything off the canvas
    		//if the entered name exists in the database, displays the profile
    		if(profileInfo.containsProfile(enteredName) == true) {
    			FacePamphletProfile profile = profileInfo.getProfile(enteredName);
    			canvas.displayProfile(profile);
    			canvas.showMessage("Displaying " + enteredName);
    			currentProfile = profile;
    		}
    		//if the entered name does not exists, tells the user it doesn't exist
    		//and sets current profile to null
    		else{
    			canvas.showMessage("A profile with name " + enteredName + " does not exist.");
    			currentProfile = null;
    		}
    	}
    	
    	//Change Status is clicked or user clicked enter after entering a status in the text field
    	else if (e.getActionCommand().equals("Change Status") || e.getSource() == status && !status.getText().equals("")){
    		String statusMessage = status.getText();
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			profile.setStatus(profile.getName() + " is " + statusMessage);
    			canvas.displayProfile(profile);
    			canvas.showMessage("Status updated to " + statusMessage);
    		}
    		else{
    			canvas.showMessage("Please select a profile to change status");
    		}
    	}
    	
    	//Change Picture is clicked or user clicked enter after entering picture name into the text field
    	else if (e.getActionCommand().equals("Change Picture") || e.getSource() == picture && !picture.getText().equals("")){
    		String filename = picture.getText();
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			GImage image = null;
    			try {
    				image = new GImage(filename);
    				profile.setImage(image);
    			} catch (ErrorException ex) {
    				image = null;
    			}
    			canvas.displayProfile(profile);
    			if(image == null) {
    				canvas.showMessage("Unable to open image file: " + filename);
    			}
    			else{
    				canvas.showMessage("Picture updated");
    			}
    		}
    		else{
    			println("Please select a profile to change picture");
    		}
    	}
    	
    	//Add Friend is clicked or user clicked enter after entering a friends name into the text field
    	else if (e.getActionCommand().equals("Add Friend") || e.getSource() == friend && !friend.getText().equals("")){
    		String friendName = friend.getText();
    		//checks to see if there is a current profile
    		if(currentProfile != null) {
    			FacePamphletProfile profile = profileInfo.getProfile(currentProfile.getName());
    			//checks to see if the name entered is the users name. The user can't friend him/herself. 
    			if(profile.getName().equals(friendName)) {
    				canvas.showMessage("You cannot friend yourself");
    			}
    			//checks to see if the friend exists in the database
    			else if(profileInfo.containsProfile(friendName)) {
    				FacePamphletProfile friendProfile = profileInfo.getProfile(friendName);
    				//checks to see if the user is already friends with the friend name entered
    				
    				//if the user and the friend entered are not friends, makes them friends
    				if(profile.addFriend(friendName) == true) {
    					profile.addFriend(friendName);
    					friendProfile.addFriend(enteredName);
    					canvas.displayProfile(profile);
    					canvas.showMessage(friendName + " added as a friend.");
    				}
    				//if the user is already friends with the friend name entered, displays this message
    				else {
    					canvas.showMessage(profile.getName() + " already has " + friendName + " as a friend.");
    				}
    			}
    			//if the friend does not exist in the database, displays this message
    			else{
    				canvas.showMessage(friendName + " does not exist.");
    			}
    		}	
    		//if there is not current profile, asks user to select a profile
    		else{
    			canvas.showMessage("Please select a profile to add friend");
    		}	
    	}		
    }
}

FacePamphletCanvas.java

/*
 * File: FacePamphletCanvas.java
 * -----------------------------
 * This class represents the canvas on which the profiles in the social
 * network are displayed.  NOTE: This class does NOT need to update the
 * display when the window is resized.
 */


import acm.graphics.*;
import java.awt.*;
import java.awt.Image.*;
import java.util.*;

public class FacePamphletCanvas extends GCanvas 
					implements FacePamphletConstants {
	
	/* Private instance variables*/
	double nameHeight = 0;
	double lastX = 0;
	double lastY = 0;
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for 
	 * the display
	 */
	public FacePamphletCanvas() {
		// You fill this in
	}
	
	/** 
	 * This method displays a message string near the bottom of the 
	 * canvas.  Every time this method is called, the previously 
	 * displayed message (if any) is replaced by the new message text 
	 * passed in.
	 */
	public void showMessage(String msg) {
		GLabel message = new GLabel(msg);
		double x = getWidth()/2 - message.getWidth()*3/4;
		double y = getHeight() - BOTTOM_MESSAGE_MARGIN;
		if(getElementAt(lastX, lastY) != null) {
			remove(getElementAt(lastX, lastY));
		}
		lastX = x;
		lastY = y;
		message.setFont(MESSAGE_FONT);
		add(message, x, y);
	}
	
	
	/** 
	 * This method displays the given profile on the canvas.  The 
	 * canvas is first cleared of all existing items (including 
	 * messages displayed near the bottom of the screen) and then the 
	 * given profile is displayed.  The profile display includes the 
	 * name of the user from the profile, the corresponding image 
	 * (or an indication that an image does not exist), the status of
	 * the user, and a list of the user's friends in the social network.
	 */
	public void displayProfile(FacePamphletProfile profile) {
		removeAll();
		addName(profile.getName());
		addImage(profile.getImage());
		addStatus(profile.getStatus());
		addFriends(profile.getFriends());
	}
	
	private void addName(String name) {
		GLabel Name = new GLabel(name);
		Name.setFont(PROFILE_NAME_FONT);
		Name.setColor(Color.BLUE);
		double x = LEFT_MARGIN;
		nameHeight = Name.getHeight();
		double y = TOP_MARGIN + nameHeight;
		add(Name, x, y);
	}
	
	private void addImage(GImage image) {
		double x = LEFT_MARGIN;
		double y = TOP_MARGIN + nameHeight + IMAGE_MARGIN; 
		if(image != null) {
			image.setBounds(x, y, IMAGE_WIDTH, IMAGE_HEIGHT);
			add(image);
		}
		else {
			GRect imageRect = new GRect(x, y, IMAGE_WIDTH, IMAGE_HEIGHT);
			add(imageRect);
			GLabel noImage = new GLabel("No Image");
			noImage.setFont(PROFILE_IMAGE_FONT);
			double labelWidth = x + IMAGE_WIDTH/2 - noImage.getWidth()/2;
			double labelHeight = y + IMAGE_HEIGHT/2;
			add(noImage, labelWidth, labelHeight);
		}
	}
	
	private void addStatus(String status) {
		GLabel Status = new GLabel(status);
		Status.setFont(PROFILE_STATUS_FONT);
		double x = LEFT_MARGIN;
		double y = TOP_MARGIN + nameHeight + IMAGE_MARGIN + IMAGE_HEIGHT + STATUS_MARGIN + Status.getHeight();
		if(getElementAt(x, y) != null) {
			remove(getElementAt(x, y));
		}
		add(Status, x, y);
	}

	private void addFriends(Iterator<String>friends) {
		GLabel Friends = new GLabel("Friends:");
		Friends.setFont(PROFILE_FRIEND_LABEL_FONT);
		double x = getWidth()/2;
		double y = TOP_MARGIN + nameHeight;
		add(Friends, x, y);
		Iterator<String> it = friends;
		for(int i = 1; it.hasNext(); i++) {
			GLabel friendName = new GLabel(it.next());
			friendName.setFont(PROFILE_FRIEND_FONT);
			double height = y + Friends.getHeight() * i;
			add(friendName, x, height);
		}
	}
	
}

FacePamphletDatabase.java

/*
 * File: FacePamphletDatabase.java
 * -------------------------------
 * This class keeps track of the profiles of all users in the
 * FacePamphlet application.  Note that profile names are case
 * sensitive, so that "ALICE" and "alice" are NOT the same name.
 */

import java.util.*;

public class FacePamphletDatabase implements FacePamphletConstants {
	
	/* private instance variables */
	private Map<String, FacePamphletProfile> profiles = new HashMap<String, FacePamphletProfile>();
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for 
	 * the database.
	 */
	public FacePamphletDatabase() {
		// You fill this in
	}
	
	
	/** 
	 * This method adds the given profile to the database.  If the 
	 * name associated with the profile is the same as an existing 
	 * name in the database, the existing profile is replaced by 
	 * the new profile passed in.
	 */
	public void addProfile(FacePamphletProfile profile) {
		if(!profiles.containsKey(profile.getName())) {
			profiles.put(profile.getName(), profile);
		}
		else{
			profiles.remove(profile.getName());
			profiles.put(profile.getName(), profile);
		}
	}

	
	/** 
	 * This method returns the profile associated with the given name 
	 * in the database.  If there is no profile in the database with 
	 * the given name, the method returns null.
	 */
	public FacePamphletProfile getProfile(String name) {
		if(profiles.containsKey(name)) {
			return profiles.get(name);
		}
		else{
			return null;
		}
		
	}
	
	
	/** 
	 * This method removes the profile associated with the given name
	 * from the database.  It also updates the list of friends of all
	 * other profiles in the database to make sure that this name is
	 * removed from the list of friends of any other profile.
	 * 
	 * If there is no profile in the database with the given name, then
	 * the database is unchanged after calling this method.
	 */
	public void deleteProfile(String name) {
		if(profiles.containsKey(name)) {
			FacePamphletProfile profileToRemove = profiles.get(name);
			Iterator<String>it = profileToRemove.getFriends();
			while(it.hasNext()) {
				String friendName = it.next();
				FacePamphletProfile friendsProfile = profiles.get(friendName);
				friendsProfile.removeFriend(name);
			}
			profiles.remove(name);
		}
	}

	
	/** 
	 * This method returns true if there is a profile in the database 
	 * that has the given name.  It returns false otherwise.
	 */
	public boolean containsProfile(String name) {
		if(profiles.containsKey(name)) {
			return true;
		}
		else {
			return false;
		}
	}

}

FacePamphletProfile.java

/*
 * File: FacePamphletProfile.java
 * ------------------------------
 * This class keeps track of all the information for one profile
 * in the FacePamphlet social network.  Each profile contains a
 * name, an image (which may not always be set), a status (what 
 * the person is currently doing, which may not always be set),
 * and a list of friends.
 */

import acm.graphics.*;
import java.util.*;

public class FacePamphletProfile implements FacePamphletConstants {
	
	/* Private instance variables*/
	private String Name = "";
	private GImage Image = null;
	private String Status = "No current status";
	private ArrayList <String> friends = new ArrayList<String>();
	
	/** 
	 * Constructor
	 * This method takes care of any initialization needed for
	 * the profile.
	 */
	public FacePamphletProfile(String name) {
		Name = name;
	}

	/** This method returns the name associated with the profile. */ 
	public String getName() {
		return Name;
	}

	/** 
	 * This method returns the image associated with the profile.  
	 * If there is no image associated with the profile, the method
	 * returns null. */ 
	public GImage getImage() {
		if(Image == null) {
			return null;
		}
		else{
			return Image;
		}
	}

	/** This method sets the image associated with the profile. */ 
	public void setImage(GImage image) {
		Image = image;
	}
	
	/** 
	 * This method returns the status associated with the profile.
	 * If there is no status associated with the profile, the method
	 * returns the empty string ("").
	 */ 
	public String getStatus() {
		return Status;
	}
	
	/** This method sets the status associated with the profile. */ 
	public void setStatus(String status) {
		Status = status;
	}

	/** 
	 * This method adds the named friend to this profile's list of 
	 * friends.  It returns true if the friend's name was not already
	 * in the list of friends for this profile (and the name is added 
	 * to the list).  The method returns false if the given friend name
	 * was already in the list of friends for this profile (in which 
	 * case, the given friend name is not added to the list of friends 
	 * a second time.)
	 */
	public boolean addFriend(String friend) {
		if(friends.contains(friend)) {
			return false;
		}
		else{
			friends.add(friend);
			return true;
		}
	}

	/** 
	 * This method removes the named friend from this profile's list
	 * of friends.  It returns true if the friend's name was in the 
	 * list of friends for this profile (and the name was removed from
	 * the list).  The method returns false if the given friend name 
	 * was not in the list of friends for this profile (in which case,
	 * the given friend name could not be removed.)
	 */
	public boolean removeFriend(String friend) {
		if(friends.contains(friend)) {
			friends.remove(friends.indexOf(friend));
			return true;
		}
		else{
			return false;
		}
	}

	/** 
	 * This method returns an iterator over the list of friends 
	 * associated with the profile.
	 */ 
	public Iterator<String> getFriends() {
		return friends.iterator();
	}
	
	/** 
	 * This method returns a string representation of the profile.  
	 * This string is of the form: "name (status): list of friends", 
	 * where name and status are set accordingly and the list of 
	 * friends is a comma separated list of the names of all of the 
	 * friends in this profile.
	 * 
	 * For example, in a profile with name "Alice" whose status is 
	 * "coding" and who has friends Don, Chelsea, and Bob, this method 
	 * would return the string: "Alice (coding): Don, Chelsea, Bob"
	 */ 
	public String toString() {
		String profile = Name + " (" + Status + "): ";
		Iterator<String>it = friends.iterator();
		while(it.hasNext()) {
			profile += it.next() + ", ";
		}
		return profile;
	}
	
}

FacePamphletConstants.java

/*
 * File: FacePamphletConstants.java
 * --------------------------------
 * This file declares several constants that are shared by the
 * different modules in the FacePamphlet application.  Any class
 * that implements this interface can use these constants.
 */

public interface FacePamphletConstants {

	/** The width of the application window */
	public static final int APPLICATION_WIDTH = 800;

	/** The height of the application window */
	public static final int APPLICATION_HEIGHT = 500;

	/** Number of characters for each of the text input fields */
	public static final int TEXT_FIELD_SIZE = 15;

	/** Text to be used to create an "empty" label to put space
	 *  between interactors on EAST border of application.  Note this
	 *  label is not actually the empty string, but rather a single space */
	public static final String EMPTY_LABEL_TEXT = " ";

	/** Name of font used to display the application message at the
	 *  bottom of the display canvas */
	public static final String MESSAGE_FONT = "Dialog-18";

	/** Name of font used to display the name in a user's profile */
	public static final String PROFILE_NAME_FONT = "Dialog-24";
	
	/** Name of font used to display the text "No Image" in user
	 *  profiles that do not contain an actual image */
	public static final String PROFILE_IMAGE_FONT = "Dialog-24";
	
	/** Name of font used to display the status in a user's profile */
	public static final String PROFILE_STATUS_FONT = "Dialog-16-bold";

	/** Name of font used to display the label "Friends" above the
	 *  user's list of friends in a profile */
	public static final String PROFILE_FRIEND_LABEL_FONT = "Dialog-16-bold";

	/** Name of font used to display the names from the user's list
	 *  of friends in a profile */
	public static final String PROFILE_FRIEND_FONT = "Dialog-16";

	/** The width (in pixels) that profile images should be displayed */
	public static final double IMAGE_WIDTH = 200;

	/** The height (in pixels) that profile images should be displayed */
	public static final double IMAGE_HEIGHT = 200;	

	/** The number of pixels in the vertical margin between the bottom 
	 *  of the canvas display area and the baseline for the message 
	 *  text that appears near the bottom of the display */
	public static final double BOTTOM_MESSAGE_MARGIN = 20;

	/** The number of pixels in the hortizontal margin between the 
	 *  left side of the canvas display area and the Name, Image, and 
	 *  Status components that are display in the profile */	
	public static final double LEFT_MARGIN = 20;	

	/** The number of pixels in the vertical margin between the top 
	 *  of the canvas display area and the top (NOT the baseline) of 
	 *  the Name component that is displayed in the profile */	
	public static final double TOP_MARGIN = 20;	
	
	/** The number of pixels in the vertical margin between the 
	 *  baseline of the Name component and the top of the Image 
	 *  displayed in the profile */	
	public static final double IMAGE_MARGIN = 20;

	/** The number of vertical pixels in the vertical margin between 
	 *  the bottom of the Image and the top of the Status component 
	 *  in the profile */		
	public static final double STATUS_MARGIN = 20;

}

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.