Przeglądaj źródła

Merge branch 'a3' of tarfeef101/cs349 into master

Tareef Dedhar 6 lat temu
rodzic
commit
5a9121be78
74 zmienionych plików z 1306 dodań i 1 usunięć
  1. BIN
      assignments/a2/.gradle/4.7-rc-2/fileContent/fileContent.lock
  2. BIN
      assignments/a2/.gradle/4.7-rc-2/taskHistory/taskHistory.bin
  3. BIN
      assignments/a2/.gradle/4.7-rc-2/taskHistory/taskHistory.lock
  4. BIN
      assignments/a3/.gradle/4.7/fileChanges/last-build.bin
  5. BIN
      assignments/a3/.gradle/4.7/fileContent/fileContent.lock
  6. BIN
      assignments/a3/.gradle/4.7/fileHashes/fileHashes.bin
  7. BIN
      assignments/a3/.gradle/4.7/fileHashes/fileHashes.lock
  8. BIN
      assignments/a3/.gradle/4.7/taskHistory/taskHistory.bin
  9. BIN
      assignments/a3/.gradle/4.7/taskHistory/taskHistory.lock
  10. BIN
      assignments/a3/.gradle/buildOutputCleanup/buildOutputCleanup.lock
  11. 2 0
      assignments/a3/.gradle/buildOutputCleanup/cache.properties
  12. BIN
      assignments/a3/.gradle/buildOutputCleanup/outputFiles.bin
  13. 0 0
      assignments/a3/.gradle/vcsWorkingDirs/gc.properties
  14. 25 0
      assignments/a3/README.md
  15. 0 1
      assignments/a3/a3.md
  16. 10 0
      assignments/a3/build.gradle
  17. BIN
      assignments/a3/build/classes/java/main/Controls$1.class
  18. BIN
      assignments/a3/build/classes/java/main/Controls$customListener.class
  19. BIN
      assignments/a3/build/classes/java/main/Controls$superListener.class
  20. BIN
      assignments/a3/build/classes/java/main/Controls.class
  21. BIN
      assignments/a3/build/classes/java/main/Gallery.class
  22. BIN
      assignments/a3/build/classes/java/main/Item$1.class
  23. BIN
      assignments/a3/build/classes/java/main/Item$clickListener.class
  24. BIN
      assignments/a3/build/classes/java/main/Item$superListener.class
  25. BIN
      assignments/a3/build/classes/java/main/Item.class
  26. BIN
      assignments/a3/build/classes/java/main/Main$1.class
  27. BIN
      assignments/a3/build/classes/java/main/Main$myAdapter.class
  28. BIN
      assignments/a3/build/classes/java/main/Main.class
  29. BIN
      assignments/a3/build/classes/java/main/Model.class
  30. BIN
      assignments/a3/build/classes/java/main/Observer.class
  31. BIN
      assignments/a3/build/classes/java/main/PicData.class
  32. BIN
      assignments/a3/build/libs/a2-1.0-SNAPSHOT.jar
  33. BIN
      assignments/a3/build/resources/main/blackcyangrid.png
  34. BIN
      assignments/a3/build/resources/main/blackcyanlist.png
  35. BIN
      assignments/a3/build/resources/main/cyanblackgrid.png
  36. BIN
      assignments/a3/build/resources/main/cyanblacklist.png
  37. BIN
      assignments/a3/build/resources/main/emptyStar.png
  38. BIN
      assignments/a3/build/resources/main/folder.jpg
  39. BIN
      assignments/a3/build/resources/main/fullStar.png
  40. BIN
      assignments/a3/build/resources/main/grid.png
  41. BIN
      assignments/a3/build/resources/main/invertedgrid.png
  42. BIN
      assignments/a3/build/resources/main/invertedlist.png
  43. BIN
      assignments/a3/build/resources/main/lightgrid.png
  44. BIN
      assignments/a3/build/resources/main/lightlist.png
  45. BIN
      assignments/a3/build/resources/main/list.png
  46. BIN
      assignments/a3/build/resources/main/star.png
  47. 2 0
      assignments/a3/build/tmp/jar/MANIFEST.MF
  48. BIN
      assignments/a3/gallery.gal
  49. BIN
      assignments/a3/gradle/wrapper/gradle-wrapper.jar
  50. 6 0
      assignments/a3/gradle/wrapper/gradle-wrapper.properties
  51. 172 0
      assignments/a3/gradlew
  52. 84 0
      assignments/a3/gradlew.bat
  53. BIN
      assignments/a3/model.gal
  54. 8 0
      assignments/a3/plan.txt
  55. 2 0
      assignments/a3/settings.gradle
  56. 364 0
      assignments/a3/src/main/java/Controls.java
  57. 357 0
      assignments/a3/src/main/java/Gallery.java
  58. 100 0
      assignments/a3/src/main/java/Main.java
  59. 165 0
      assignments/a3/src/main/java/Model.java
  60. 9 0
      assignments/a3/src/main/java/Observer.java
  61. BIN
      assignments/a3/src/main/resources/blackcyangrid.png
  62. BIN
      assignments/a3/src/main/resources/blackcyanlist.png
  63. BIN
      assignments/a3/src/main/resources/cyanblackgrid.png
  64. BIN
      assignments/a3/src/main/resources/cyanblacklist.png
  65. BIN
      assignments/a3/src/main/resources/emptyStar.png
  66. BIN
      assignments/a3/src/main/resources/folder.jpg
  67. BIN
      assignments/a3/src/main/resources/fullStar.png
  68. BIN
      assignments/a3/src/main/resources/grid.png
  69. BIN
      assignments/a3/src/main/resources/invertedgrid.png
  70. BIN
      assignments/a3/src/main/resources/invertedlist.png
  71. BIN
      assignments/a3/src/main/resources/lightgrid.png
  72. BIN
      assignments/a3/src/main/resources/lightlist.png
  73. BIN
      assignments/a3/src/main/resources/list.png
  74. BIN
      assignments/a3/src/main/resources/star.png

BIN
assignments/a2/.gradle/4.7-rc-2/fileContent/fileContent.lock


BIN
assignments/a2/.gradle/4.7-rc-2/taskHistory/taskHistory.bin


BIN
assignments/a2/.gradle/4.7-rc-2/taskHistory/taskHistory.lock


BIN
assignments/a3/.gradle/4.7/fileChanges/last-build.bin


BIN
assignments/a3/.gradle/4.7/fileContent/fileContent.lock


BIN
assignments/a3/.gradle/4.7/fileHashes/fileHashes.bin


BIN
assignments/a3/.gradle/4.7/fileHashes/fileHashes.lock


BIN
assignments/a3/.gradle/4.7/taskHistory/taskHistory.bin


BIN
assignments/a3/.gradle/4.7/taskHistory/taskHistory.lock


BIN
assignments/a3/.gradle/buildOutputCleanup/buildOutputCleanup.lock


+ 2 - 0
assignments/a3/.gradle/buildOutputCleanup/cache.properties

@@ -0,0 +1,2 @@
+#Wed Jul 04 20:00:50 EDT 2018
+gradle.version=4.7

BIN
assignments/a3/.gradle/buildOutputCleanup/outputFiles.bin


+ 0 - 0
assignments/a3/.gradle/vcsWorkingDirs/gc.properties


+ 25 - 0
assignments/a3/README.md

@@ -0,0 +1,25 @@
+# CS 349 A3 - Gallery, But Worse (aka Fotag!)
+
+This is a simple gallery-esque app to load in and view photos, and add ratings to them. You can also toggle filters for images greater than or equal to a given rating (out of 5 stars). You can toggle between a spacious list layout, or a more condensed grid layout.
+
+## Getting Started
+**Notes**
+ - Image size/aspect ratio: all images are scaled to a square aspect ratio, although any can be selected
+ - Images should be in a format compatible with https://docs.oracle.com/javase/10/docs/api/java/awt/Image.html on your system.
+ - This was built and tested on Debian Stretch using XFCE with Gradle 4.7 and openJDK 10.0.1
+ - That being said, given what I've seen, these tend to look better on "fancier" OSes/window managers.
+ - Load/Save is as instructed: loads/saves images/metadata as long as the filepath is the same. Other data such as ratings is not retained.
+
+**Controls**
+ - Layout: Click the grid or list icon in the top left to switch to that view
+ - Filtering by Rating: In the top bar, click on the amount of stars you wish to be the minimum, or click the current selection to reset to zero.
+ - Rating an Image: Use the same system as above
+ - Viewing a popout image: simply click on an image to open a popup view of it, then simply close it like any window to dismiss it.
+
+## Deployment
+
+Run "java Main" in build/classes/java/main, or "./gradlew run" in the root directory if you do not have gradle installed, and if you do "gradle run" should suffice.
+
+## Authors
+
+* **Tareef Dedhar** - *All work*

+ 0 - 1
assignments/a3/a3.md

@@ -1 +0,0 @@
-# A3

+ 10 - 0
assignments/a3/build.gradle

@@ -0,0 +1,10 @@
+version '1.0-SNAPSHOT'
+
+apply plugin: 'java'
+
+sourceCompatibility = 1.8
+
+task run(type:JavaExec) {
+    classpath = sourceSets.main.runtimeClasspath
+    main = 'Main'
+}

BIN
assignments/a3/build/classes/java/main/Controls$1.class


BIN
assignments/a3/build/classes/java/main/Controls$customListener.class


BIN
assignments/a3/build/classes/java/main/Controls$superListener.class


BIN
assignments/a3/build/classes/java/main/Controls.class


BIN
assignments/a3/build/classes/java/main/Gallery.class


BIN
assignments/a3/build/classes/java/main/Item$1.class


BIN
assignments/a3/build/classes/java/main/Item$clickListener.class


BIN
assignments/a3/build/classes/java/main/Item$superListener.class


BIN
assignments/a3/build/classes/java/main/Item.class


BIN
assignments/a3/build/classes/java/main/Main$1.class


BIN
assignments/a3/build/classes/java/main/Main$myAdapter.class


BIN
assignments/a3/build/classes/java/main/Main.class


BIN
assignments/a3/build/classes/java/main/Model.class


BIN
assignments/a3/build/classes/java/main/Observer.class


BIN
assignments/a3/build/classes/java/main/PicData.class


BIN
assignments/a3/build/libs/a2-1.0-SNAPSHOT.jar


BIN
assignments/a3/build/resources/main/blackcyangrid.png


BIN
assignments/a3/build/resources/main/blackcyanlist.png


BIN
assignments/a3/build/resources/main/cyanblackgrid.png


BIN
assignments/a3/build/resources/main/cyanblacklist.png


BIN
assignments/a3/build/resources/main/emptyStar.png


BIN
assignments/a3/build/resources/main/folder.jpg


BIN
assignments/a3/build/resources/main/fullStar.png


BIN
assignments/a3/build/resources/main/grid.png


BIN
assignments/a3/build/resources/main/invertedgrid.png


BIN
assignments/a3/build/resources/main/invertedlist.png


BIN
assignments/a3/build/resources/main/lightgrid.png


BIN
assignments/a3/build/resources/main/lightlist.png


BIN
assignments/a3/build/resources/main/list.png


BIN
assignments/a3/build/resources/main/star.png


+ 2 - 0
assignments/a3/build/tmp/jar/MANIFEST.MF

@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+

BIN
assignments/a3/gallery.gal


BIN
assignments/a3/gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
assignments/a3/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Tue May 29 15:31:30 EDT 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-rc-2-all.zip

+ 172 - 0
assignments/a3/gradlew

@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"

+ 84 - 0
assignments/a3/gradlew.bat

@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

BIN
assignments/a3/model.gal


+ 8 - 0
assignments/a3/plan.txt

@@ -0,0 +1,8 @@
+idea:
+
+main.java is a jframe holding all the shit
+add a jcomponent which is the top control bar
+add a jcomponent which is the collection of crap, which goes between the 2 layout managers
+  this contains basically a bunch of classes which are also components, which are the pictures+metadata
+  popups are handled like i did in a2
+have a model which is just data everything observes

+ 2 - 0
assignments/a3/settings.gradle

@@ -0,0 +1,2 @@
+rootProject.name = 'a2'
+

+ 364 - 0
assignments/a3/src/main/java/Controls.java

@@ -0,0 +1,364 @@
+import java.io.*;
+import java.io.File;
+import java.util.*;
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+import javax.swing.ImageIcon;
+import java.awt.image.*;
+import javax.imageio.ImageIO;
+import javax.swing.JFileChooser;
+
+public class Controls extends JPanel implements Observer, Serializable
+{
+  private Model model;
+  private JRadioButton grid;
+  private JRadioButton list;
+  private class customListener implements ActionListener, Serializable
+  {
+    public void actionPerformed(ActionEvent e)
+    {
+      if (e.getSource() == grid)
+      {
+        grid.setSelected(true);
+        list.setSelected(false);
+        model.switchLayout(true);
+        grid.setBorderPainted(true);
+        list.setBorderPainted(false);
+      }
+      else
+      {
+        grid.setSelected(false);
+        list.setSelected(true);
+        model.switchLayout(false);
+        list.setBorderPainted(true);
+        grid.setBorderPainted(false);
+      }
+    }
+  }
+  private class superListener implements ActionListener, Serializable
+  {
+    public void actionPerformed(ActionEvent e)
+    {
+      if (e.getSource() == star1)
+      {
+        if (!(star1.isSelected()) || model.getFilter() == 1)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(1);
+        }
+      }
+      else if (e.getSource() == star2)
+      {
+        if (!(star2.isSelected()) || model.getFilter() == 2)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(2);
+        }
+      }
+      else if (e.getSource() == star3)
+      {
+        if (!(star3.isSelected()) || model.getFilter() == 3)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(3);
+        }
+      }
+      else if (e.getSource() == star4)
+      {
+        if (!(star4.isSelected()) || model.getFilter() == 4)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(true);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(fullStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(4);
+        }
+      }
+      else
+      {
+        if (!(star5.isSelected()) || model.getFilter() == 5)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          model.changeFilter(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(true);
+          star5.setSelected(true);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(fullStarIcon);
+          star5.setIcon(fullStarIcon);
+          model.changeFilter(5);
+        }
+      }
+    }
+  }
+  private customListener customlistener;
+  private superListener superlistener;
+  private ButtonGroup layouts;
+  private ButtonGroup stars;
+  private transient Image emptyStarImg;
+  private transient Image fullStarImg;
+  private transient Image gridImg;
+  private transient Image listImg;
+  private transient Image lightGridImg;
+  private transient Image lightListImg;
+  private transient Image folderImg;
+  private ImageIcon emptyStarIcon;
+  private ImageIcon fullStarIcon;
+  private ImageIcon gridIcon;
+  private ImageIcon listIcon;
+  private ImageIcon lightGridIcon;
+  private ImageIcon lightListIcon;
+  private ImageIcon folderIcon;
+  private JButton fileButton;
+  private JRadioButton star1;
+  private JRadioButton star2;
+  private JRadioButton star3;
+  private JRadioButton star4;
+  private JRadioButton star5;
+  private JFileChooser fileChooser;
+
+  // Bob the Builder this shit
+  public Controls(Model model)
+  {
+    this.model = model;
+    this.customlistener = new customListener();
+    this.superlistener = new superListener();
+    this.setBackground(Color.white);
+    this.setLayout(new BorderLayout(0 , 0));
+    this.setPreferredSize(new Dimension(1280,75));
+    this.setMinimumSize(new Dimension(320, 75));
+    
+    try
+    {
+      this.fullStarImg = ImageIO.read(new File("src/main/resources/fullStar.png"));
+    } catch(IOException e) {}
+    
+    try
+    {
+      this.emptyStarImg = ImageIO.read(new File("src/main/resources/emptyStar.png"));
+    } catch(IOException e) {}
+
+    try
+    {
+      this.gridImg = ImageIO.read(new File("src/main/resources/grid.png"));
+    } catch(IOException e) {}
+
+    try
+    {
+      this.listImg = ImageIO.read(new File("src/main/resources/list.png"));
+    } catch(IOException e) {}
+    
+    try
+    {
+      this.lightGridImg = ImageIO.read(new File("src/main/resources/invertedgrid.png"));
+    } catch(IOException e) {}
+
+    try
+    {
+      this.lightListImg = ImageIO.read(new File("src/main/resources/invertedlist.png"));
+    } catch(IOException e) {}
+    
+    try
+    {
+      this.folderImg = ImageIO.read(new File("src/main/resources/folder.jpg"));
+    } catch(IOException e) {}
+    
+    
+    this.fullStarImg = fullStarImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.emptyStarImg = emptyStarImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.gridImg = gridImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.listImg = listImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.lightGridImg = lightGridImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.lightListImg = lightListImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.folderImg = folderImg.getScaledInstance(50, 50,  java.awt.Image.SCALE_SMOOTH);
+    this.fullStarIcon = new ImageIcon(fullStarImg);
+    this.emptyStarIcon = new ImageIcon(emptyStarImg);
+    this.gridIcon = new ImageIcon(gridImg);
+    this.listIcon = new ImageIcon(listImg);
+    this.folderIcon = new ImageIcon(folderImg);
+    
+    this.grid = new JRadioButton(gridIcon, true);
+    grid.addActionListener(customlistener);
+    
+    this.list = new JRadioButton(listIcon, false);
+    list.addActionListener(customlistener);
+    
+    this.layouts = new ButtonGroup();
+    layouts.add(grid);
+    layouts.add(list);
+    grid.setSelected(true);
+    list.setSelected(false);
+    
+    this.fileChooser = new JFileChooser();
+    this.fileButton = new JButton(folderIcon);
+    fileButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        int retval = fileChooser.showOpenDialog(null);
+        
+        if (retval == JFileChooser.APPROVE_OPTION)
+        {
+          File file = fileChooser.getSelectedFile();
+          if (file.isFile())
+          {
+            model.newPic(file.getAbsolutePath(), file.getName(), file.length(), file.lastModified());
+          }
+        }
+      }
+    });
+    
+    this.star1 = new JRadioButton(emptyStarIcon, false);
+    star1.addActionListener(superlistener);
+    this.star2 = new JRadioButton(emptyStarIcon, false);
+    star2.addActionListener(superlistener);
+    this.star3 = new JRadioButton(emptyStarIcon, false);
+    star3.addActionListener(superlistener);
+    this.star4 = new JRadioButton(emptyStarIcon, false);
+    star4.addActionListener(superlistener);
+    this.star5 = new JRadioButton(emptyStarIcon, false);
+    star5.addActionListener(superlistener);
+    this.stars = new ButtonGroup();
+    stars.add(star1);
+    stars.add(star2);
+    stars.add(star3);
+    stars.add(star4);
+    stars.add(star5);
+    star1.setSelected(false);
+    star2.setSelected(false);
+    star3.setSelected(false);
+    star4.setSelected(false);
+    star5.setSelected(false);
+
+
+    JPanel tempPanel = new JPanel();
+    tempPanel.setLayout(new BoxLayout(tempPanel, BoxLayout.X_AXIS));
+    tempPanel.add(grid);
+    tempPanel.add(list);
+    this.add(tempPanel, BorderLayout.LINE_START);
+    this.add(new JLabel("Fotag!", JLabel.CENTER), BorderLayout.CENTER);
+    JPanel tempPanel2 = new JPanel();
+    tempPanel2.setLayout(new BoxLayout(tempPanel2, BoxLayout.X_AXIS));
+    tempPanel2.add(star1);
+    tempPanel2.add(star2);
+    tempPanel2.add(star3);
+    tempPanel2.add(star4);
+    tempPanel2.add(star5);
+    tempPanel2.add(fileButton);
+    this.add(tempPanel2, BorderLayout.LINE_END);
+    model.addObserver(this);
+  }
+
+  public void update(Object observable)
+  {
+    revalidate();
+    repaint();
+  }
+}

+ 357 - 0
assignments/a3/src/main/java/Gallery.java

@@ -0,0 +1,357 @@
+import java.util.*;
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+import java.io.Serializable;
+import javax.swing.ImageIcon;
+import java.awt.image.*;
+import javax.imageio.ImageIO;
+import java.io.File;
+import java.io.*;
+import javax.swing.BorderFactory;
+import java.text.SimpleDateFormat;
+
+public class Gallery extends JPanel implements Observer, Serializable
+{
+  private Model model;
+  private ArrayList<Item> items;
+
+  // Bob the Builder this shit
+  public Gallery(Model model)
+  {
+    // Hook up this observer so that it will be notified when the model
+    // changes.
+    this.model = model;
+    this.setMinimumSize(new Dimension(400, 400));
+    this.items = new ArrayList();
+    reList();
+    reFill();
+    
+    try
+    {
+      Item.fullStarImg = ImageIO.read(new File("src/main/resources/fullStar.png"));
+    } catch(IOException e) {}
+    try
+    {
+      Item.emptyStarImg = ImageIO.read(new File("src/main/resources/emptyStar.png"));
+    } catch(IOException e) {}
+    Item.fullStarImg = Item.fullStarImg.getScaledInstance(32, 32,  java.awt.Image.SCALE_SMOOTH);
+    Item.emptyStarImg = Item.emptyStarImg.getScaledInstance(32, 32,  java.awt.Image.SCALE_SMOOTH);
+    Item.fullStarIcon = new ImageIcon(Item.fullStarImg);
+    Item.emptyStarIcon = new ImageIcon(Item.emptyStarImg);
+
+    model.addObserver(this);
+  }
+
+  /**
+  * Update with data from the model.
+  */
+  public void update(Object observable)
+  {
+    reList();
+    reFill();
+    revalidate();
+    repaint();
+  }
+  
+  private void reList()
+  {
+    ArrayList<PicData> temp = model.getPics();
+    for (int i = items.size(); i < temp.size(); i++)
+    {
+      Item temp2 = new Item(temp.get(i));
+      items.add(temp2);
+    }
+  }
+  
+  private void reFill()
+  {
+    if (model.getGrid())
+    {
+      int unit = 200;
+      int total = this.getWidth();
+      if (total == 0) total = 1280;
+      /*if (items.size() > 0)
+      {
+        int temp = items.get(0).getWidth();
+        if (temp > 0) unit = temp;
+      }*/
+      int cols = total / unit;
+      this.setLayout(new GridLayout(0, cols));
+    }
+    else
+    {
+      this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+    }
+
+    this.removeAll();
+    
+    for (Item i: items)
+    {
+      if (i.getData().getRating() >= model.getFilter()) this.add(i);
+    }
+  }
+}
+
+class Item extends JPanel implements Serializable
+{
+  private PicData data;
+  private ImageIcon picture;
+  private JLabel pic;
+  private JLabel name;
+  private JPanel rating;
+  private JLabel dateSize;
+  public static Image fullStarImg;
+  public static Image emptyStarImg;
+  public static ImageIcon fullStarIcon;
+  public static ImageIcon emptyStarIcon;
+  private JRadioButton star1;
+  private JRadioButton star2;
+  private JRadioButton star3;
+  private JRadioButton star4;
+  private JRadioButton star5;
+  private ButtonGroup stars;
+  
+  private class clickListener extends MouseInputAdapter implements Serializable
+  {
+    public void mousePressed(MouseEvent e)
+    {
+      JFrame tempFrame = new JFrame(data.getName());
+      ImageIcon tempIcon = new ImageIcon(data.getPic());
+      JLabel tempLabel = new JLabel(tempIcon, JLabel.CENTER);
+      tempLabel.setMinimumSize(new Dimension(800, 600));
+      tempFrame.getContentPane().add(tempLabel);
+      tempFrame.pack();
+	    tempFrame.setVisible(true);
+    }
+  }
+  private clickListener clicklistener;
+  
+  private class superListener implements ActionListener, Serializable
+  {
+    public void actionPerformed(ActionEvent e)
+    {
+      if (e.getSource() == star1)
+      {
+        if (!(star1.isSelected()) || data.getRating() == 1)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(1);
+        }
+      }
+      else if (e.getSource() == star2)
+      {
+        if (!(star2.isSelected()) || data.getRating() == 2)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(2);
+        }
+      }
+      else if (e.getSource() == star3)
+      {
+        if (!(star3.isSelected()) || data.getRating() == 3)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(3);
+        }
+      }
+      else if (e.getSource() == star4)
+      {
+        if (!(star4.isSelected()) || data.getRating() == 4)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(true);
+          star5.setSelected(false);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(fullStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(4);
+        }
+      }
+      else
+      {
+        if (!(star5.isSelected()) || data.getRating() == 5)
+        {
+          star1.setSelected(false);
+          star2.setSelected(false);
+          star3.setSelected(false);
+          star4.setSelected(false);
+          star5.setSelected(false);
+          star1.setIcon(emptyStarIcon);
+          star2.setIcon(emptyStarIcon);
+          star3.setIcon(emptyStarIcon);
+          star4.setIcon(emptyStarIcon);
+          star5.setIcon(emptyStarIcon);
+          data.setRating(0);
+        }
+        else
+        {
+          star1.setSelected(true);
+          star2.setSelected(true);
+          star3.setSelected(true);
+          star4.setSelected(true);
+          star5.setSelected(true);
+          star1.setIcon(fullStarIcon);
+          star2.setIcon(fullStarIcon);
+          star3.setIcon(fullStarIcon);
+          star4.setIcon(fullStarIcon);
+          star5.setIcon(fullStarIcon);
+          data.setRating(5);
+        }
+      }
+    }
+  }
+  private superListener superlistener;
+
+  public Item(PicData p)
+  {
+    this.data = p;
+    this.clicklistener = new clickListener();
+    this.superlistener = new superListener();
+    this.star1 = new JRadioButton(emptyStarIcon, false);
+    star1.addActionListener(superlistener);
+    this.star2 = new JRadioButton(emptyStarIcon, false);
+    star2.addActionListener(superlistener);
+    this.star3 = new JRadioButton(emptyStarIcon, false);
+    star3.addActionListener(superlistener);
+    this.star4 = new JRadioButton(emptyStarIcon, false);
+    star4.addActionListener(superlistener);
+    this.star5 = new JRadioButton(emptyStarIcon, false);
+    star5.addActionListener(superlistener);
+    this.stars = new ButtonGroup();
+    stars.add(star1);
+    stars.add(star2);
+    stars.add(star3);
+    stars.add(star4);
+    stars.add(star5);
+    star1.setSelected(false);
+    star2.setSelected(false);
+    star3.setSelected(false);
+    star4.setSelected(false);
+    star5.setSelected(false);
+    this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+    this.setPreferredSize(new Dimension(200, 282));
+    this.setMaximumSize(new Dimension(200, 282));
+    //this.setBorder(BorderFactory.createLineBorder(Color.gray));
+    this.picture = new ImageIcon(data.getPic());
+    this.pic = new JLabel(picture, JLabel.CENTER);
+    this.pic.addMouseListener(clicklistener);
+    this.pic.setAlignmentX(LEFT_ALIGNMENT);
+    this.pic.setPreferredSize(new Dimension(200, 200));
+    this.name = new JLabel("Name: " + data.getName(), JLabel.LEFT);
+    this.name.setAlignmentX(LEFT_ALIGNMENT);
+    this.name.setPreferredSize(new Dimension(200, 25));
+    this.rating = new JPanel();
+    this.rating.setLayout(new BoxLayout(this.rating, BoxLayout.X_AXIS));
+    this.rating.add(star1);
+    this.rating.add(star2);
+    this.rating.add(star3);
+    this.rating.add(star4);
+    this.rating.add(star5);
+    this.rating.setPreferredSize(new Dimension(200, 32));
+    this.rating.setAlignmentX(LEFT_ALIGNMENT);
+    Date tempdate = new Date(data.getLastmod());
+    SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
+    this.dateSize = new JLabel("Created: " + format.format(tempdate), JLabel.LEFT);
+    this.dateSize.setAlignmentX(LEFT_ALIGNMENT);
+    this.dateSize.setPreferredSize(new Dimension(200, 25));
+    this.add(pic);
+    this.add(name);
+    this.add(rating);
+    this.add(dateSize);
+  }
+
+  public PicData getData()
+  {
+    return data;
+  }
+}
+  

+ 100 - 0
assignments/a3/src/main/java/Main.java

@@ -0,0 +1,100 @@
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.*;
+import java.lang.Throwable;
+import javax.imageio.ImageIO;
+
+public class Main
+{
+  public static Model model;
+  public static Gallery gallery;
+  static class myAdapter extends ComponentAdapter
+  {
+    public void componentResized(ComponentEvent ce)
+    {
+      boolean temp = model.getLayout();
+      model.switchLayout(!temp);
+      model.switchLayout(temp);
+    }
+  }
+  public static myAdapter listener;
+
+  public static void main(String[] args)
+  {
+    JFrame window = new JFrame("Fotag!");
+    model = new Model();
+    listener = new myAdapter();
+    window.addComponentListener(listener);
+    
+    try
+    {
+      FileInputStream file = new FileInputStream("savestate.gal");
+      ObjectInputStream object =  new ObjectInputStream(file);
+      model = (Model)object.readObject();
+      object.close();
+
+      for (PicData p: model.getPics())
+      {
+        String filepath = p.getFile();
+        Image img = null;
+        try
+        {
+          img = ImageIO.read(new File(filepath));
+        } catch(IOException e) {}
+        img = img.getScaledInstance(200, 200,  java.awt.Image.SCALE_SMOOTH);
+        p.setPic(img);
+      }
+    }
+    catch (Exception e) {System.out.println("Playing baseball");}
+    
+    gallery = new Gallery(model);
+    Controls controls = new Controls(model);
+    model.notifyObservers();
+    
+    // create a layout panel to hold the views
+    JPanel mainpanel = new JPanel(new BorderLayout(0, 0));
+    window.getContentPane().add(mainpanel);
+    JScrollPane scrollGallery = new JScrollPane(gallery);
+    scrollGallery.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    scrollGallery.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+    mainpanel.add(scrollGallery, BorderLayout.CENTER);
+    mainpanel.add(controls, BorderLayout.PAGE_START);
+
+    // Setup the frame to do frame things
+    window.setPreferredSize(new Dimension(1280,720));
+    window.setMinimumSize(new Dimension(500, 475));
+    window.pack();
+    //window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    
+    window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+    window.addWindowListener(new WindowAdapter()
+    {
+      public void windowClosing(WindowEvent we)
+      {
+          String ObjButtons[] = {"Yes","No"};
+          int PromptResult = JOptionPane.showOptionDialog(null,"Do you want to save your files?","",JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE,null,ObjButtons,ObjButtons[1]);
+          
+          if(PromptResult==JOptionPane.YES_OPTION)
+          {
+            try
+            {
+              ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("savestate.gal"));
+              output.writeObject(model);
+              output.close();
+            } catch (Exception e)
+            {
+              System.out.println("Screw you ankil");
+              e.printStackTrace();
+            }
+          }
+          
+          System.exit(0);
+      }
+    });
+    
+    window.setVisible(true);
+  }
+}

+ 165 - 0
assignments/a3/src/main/java/Model.java

@@ -0,0 +1,165 @@
+import java.util.Observable;
+import java.util.*;
+import java.awt.*;
+import javax.swing.*;
+import java.io.*;
+import javax.imageio.ImageIO;
+
+public class Model extends Observable implements Serializable
+{
+   /** The observers that are watching this model for changes. */
+  private ArrayList<Observer> observers;
+  private ArrayList<PicData> pics;
+  private int filter;
+  private boolean grid;
+
+  // Constructor
+  public Model()
+  {
+    this.observers = new ArrayList();
+    this.pics = new ArrayList();
+    this.filter = 0;
+    this.grid = true;
+    PicData.model = this;
+    setChanged();
+  }
+  
+  public void newPic(String filepath, String name, long size, long lastmod)
+  {
+    PicData temp = new PicData(filepath, name, size, lastmod);
+    pics.add(temp);
+    setChanged();
+    notifyObservers();
+  }
+  
+  public ArrayList<PicData> getPics()
+  {
+    return pics;
+  }
+  
+  public boolean getGrid()
+  {
+    return grid;
+  }
+  
+  public int getFilter()
+  {
+    return filter;
+  }
+  
+  public void changeFilter(int x)
+  {
+    this.filter = x;
+    setChanged();
+    notifyObservers();
+  }
+  
+  public boolean getLayout()
+  {
+    return grid;
+  }
+
+  public void switchLayout(boolean flag)
+  {
+    if (grid != flag)
+    {
+      grid = flag;
+      setChanged();
+      notifyObservers();
+    }
+  }
+  
+  public void update()
+  {
+    setChanged();
+    notifyObservers();
+  }
+
+  // Add observer to be notified on change
+  public void addObserver(Observer observer)
+  {
+    this.observers.add(observer);
+  }
+
+  // Remove an observer from opdate list
+  public void removeObserver(Observer observer)
+  {
+    this.observers.remove(observer);
+  }
+
+   // Notify all observers shit went down
+  public void notifyObservers()
+  {
+    for (Observer observer: this.observers)
+    {
+      observer.update(this);
+    }
+  }
+}
+
+class PicData implements Serializable
+{
+  private int rating;
+  private transient Image pic;
+  private long size;
+  private long lastmod;
+  private String name;
+  private String filepath;
+  public static Model model;
+
+  public PicData(String filepath, String name, long size, long lastmod)
+  {
+    try
+    {
+      this.pic = ImageIO.read(new File(filepath));
+    } catch(IOException e) {}
+    
+    this.pic = pic.getScaledInstance(200, 200,  java.awt.Image.SCALE_SMOOTH);
+    this.size = size/1024;
+    this.lastmod = lastmod;
+    this.name = name;
+    this.rating = 0;
+    this.filepath = filepath;
+  }
+  
+  public void setRating(int x)
+  {
+    this.rating = x;
+    model.update();
+  }
+  
+  public Image getPic()
+  {
+    return pic;
+  }
+  
+  public int getRating()
+  {
+    return rating;
+  }
+  
+  public long getSize()
+  {
+    return size;
+  }
+  
+  public long getLastmod()
+  {
+    return lastmod;
+  }
+  
+  public String getName()
+  {
+    return name;
+  }
+
+  public void setPic(Image i)
+  {
+    this.pic = i;
+  }
+
+  public String getFile()
+  {
+    return filepath;
+  }
+}

+ 9 - 0
assignments/a3/src/main/java/Observer.java

@@ -0,0 +1,9 @@
+/**
+ * An interface that allows an object to receive updates from the object
+ * they listen to.
+ */
+interface Observer
+{
+    void update(Object observable);
+}
+

BIN
assignments/a3/src/main/resources/blackcyangrid.png


BIN
assignments/a3/src/main/resources/blackcyanlist.png


BIN
assignments/a3/src/main/resources/cyanblackgrid.png


BIN
assignments/a3/src/main/resources/cyanblacklist.png


BIN
assignments/a3/src/main/resources/emptyStar.png


BIN
assignments/a3/src/main/resources/folder.jpg


BIN
assignments/a3/src/main/resources/fullStar.png


BIN
assignments/a3/src/main/resources/grid.png


BIN
assignments/a3/src/main/resources/invertedgrid.png


BIN
assignments/a3/src/main/resources/invertedlist.png


BIN
assignments/a3/src/main/resources/lightgrid.png


BIN
assignments/a3/src/main/resources/lightlist.png


BIN
assignments/a3/src/main/resources/list.png


BIN
assignments/a3/src/main/resources/star.png