diff --git a/ws2010/se/u4/EX4 A1.2.jpg b/ws2010/se/u4/EX4 A1.2.jpg new file mode 100644 index 00000000..78dc2e6a Binary files /dev/null and b/ws2010/se/u4/EX4 A1.2.jpg differ diff --git a/ws2010/se/u4/EX4 A1.2_2.jpg b/ws2010/se/u4/EX4 A1.2_2.jpg new file mode 100644 index 00000000..586a305e Binary files /dev/null and b/ws2010/se/u4/EX4 A1.2_2.jpg differ diff --git a/ws2010/se/u4/ex04/.classpath b/ws2010/se/u4/ex04/.classpath new file mode 100644 index 00000000..f04a1162 --- /dev/null +++ b/ws2010/se/u4/ex04/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ws2010/se/u4/ex04/.project b/ws2010/se/u4/ex04/.project new file mode 100644 index 00000000..752d3f84 --- /dev/null +++ b/ws2010/se/u4/ex04/.project @@ -0,0 +1,17 @@ + + + EiSE-Exercise04 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html new file mode 100644 index 00000000..8315f751 --- /dev/null +++ b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html @@ -0,0 +1,67 @@ + + + + +Dimension Of Deskmod :: Icon Design + + + + + +
+
+
+
+
+

 

+
+
+
+
+

 

+

+
+
+ + + +
+
+ +
+
+ + diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon.png new file mode 100644 index 00000000..ea6bd3ee Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/Papers-icon.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/README-Icons b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/README-Icons new file mode 100644 index 00000000..407409cf --- /dev/null +++ b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/README-Icons @@ -0,0 +1,12 @@ +Tango Icon Theme +---------------- + +This is an icon theme that follows the Tango visual guidelines [1]. Currently +it depends on Imagemagick for creation of 24x24 bitmaps by adding a 1px padding +around the 22x22px version. For GNOME and KDE you will also need +icon-naming-utils that allow the theme to work in these environments before +they follow the new naming scheme [2]. + + +[1] http://tango-project.org/Tango_Icon_Theme_Guidelines +[2] http://tango-project.org/Standard_Icon_Naming_Specification diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/accessories-text-editor.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/accessories-text-editor.png new file mode 100644 index 00000000..c6b62851 Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/accessories-text-editor.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/go-next.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/go-next.png new file mode 100644 index 00000000..6f3f65d3 Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/go-next.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-add.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-add.png new file mode 100644 index 00000000..2acdd8f5 Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-add.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-remove.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-remove.png new file mode 100644 index 00000000..c5524f72 Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/list-remove.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/media-playback-start.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/media-playback-start.png new file mode 100644 index 00000000..66f32d89 Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/media-playback-start.png differ diff --git a/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/process-stop.png b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/process-stop.png new file mode 100644 index 00000000..b68290bf Binary files /dev/null and b/ws2010/se/u4/ex04/bin/de/tud/cs/se/flashcards/ui/process-stop.png differ diff --git a/ws2010/se/u4/ex04/ex04.pdf b/ws2010/se/u4/ex04/ex04.pdf new file mode 100644 index 00000000..efedaef6 Binary files /dev/null and b/ws2010/se/u4/ex04/ex04.pdf differ diff --git a/ws2010/se/u4/ex04/lib/commons-io-1.4.jar b/ws2010/se/u4/ex04/lib/commons-io-1.4.jar new file mode 100644 index 00000000..133dc6cb Binary files /dev/null and b/ws2010/se/u4/ex04/lib/commons-io-1.4.jar differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/MacOSXAdapter.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/MacOSXAdapter.java new file mode 100644 index 00000000..5a31a00c --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/MacOSXAdapter.java @@ -0,0 +1,124 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Michael Eichberg (Software Engineering) + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards; + +import java.awt.Image; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import javax.swing.JOptionPane; + +import de.tud.cs.se.flashcards.ui.Utilities; + +/** + * This class provides the major part of the Mac OS X integration of the + * flashcards app. + *

+ * This class does not introduce any coupling on Mac OS X specific classes + * or technologies. + *

+ * + * @author Michael Eichberg + */ +public class MacOSXAdapter { + + static { + + // properties to make the application look more similar to a native Mac + // OS X application + System.setProperty("apple.laf.useScreenMenuBar", "true"); + System.setProperty("com.apple.mrj.application.growbox.intrudes", + "false"); + System.setProperty("com.apple.mrj.application.apple.menu.about.name", + "Flashcards"); + + try { + Class applicationClass = Class + .forName("com.apple.eawt.Application"); + Object application = applicationClass.getMethod("getApplication") + .invoke(null); + applicationClass.getMethod("setEnabledPreferencesMenu", + boolean.class).invoke(application, Boolean.FALSE); + + Image appImage = java.awt.Toolkit.getDefaultToolkit().getImage( + Utilities.class.getResource("Papers-icon.png")); + applicationClass.getMethod("setDockIconImage", Image.class).invoke( + application, appImage); + + Class applicationAdapterClass = Class + .forName("com.apple.eawt.ApplicationListener"); + Object applicationAdapter = Proxy.newProxyInstance( + System.class.getClassLoader(), + new Class[] { applicationAdapterClass }, + new InvocationHandler() { + + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + if (method.getName().equals("handleAbout")) { + JOptionPane + .showMessageDialog( + null, + "(c) 2010 Michael Eichberg,\nDepartment of Computer Science,\nTechnische Universität Darmstadt", + "Flashcards", + JOptionPane.INFORMATION_MESSAGE, + Utilities.createImageIcon( + "Papers-icon.png", + "The Flashcards Icon")); + args[0].getClass() + .getMethod("setHandled", boolean.class) + .invoke(args[0], Boolean.TRUE); + } else if (method.getName().equals("handleQuit")) { + // Check to see if the user has unsaved + // changes. + // If the user does not have unhandled changes + // call + // setHandled(true) otherwise call + // setHandled(false). + args[0].getClass() + .getMethod("setHandled", boolean.class) + .invoke(args[0], Boolean.TRUE); + } + return null; + } + }); + + applicationClass.getMethod("addApplicationListener", + Class.forName("com.apple.eawt.ApplicationListener")) + .invoke(application, applicationAdapter); + } catch (Exception e) { + System.err.println("Mac OS X integration failed: " + + e.getLocalizedMessage() + "."); + } + } +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/Main.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/Main.java new file mode 100644 index 00000000..a4362108 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/Main.java @@ -0,0 +1,105 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Michael Eichberg (Software Engineering) + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards; + +import java.io.File; +import java.util.Iterator; +import java.util.Map.Entry; + +import javax.swing.UIManager; + +import de.tud.cs.se.flashcards.model.FlashcardSeries; +import de.tud.cs.se.flashcards.ui.FlashcardsWindow; + +/** + * Starts the flashcard application. Basically, each given file is associated + * with its own Frame. + * + * @author Michael Eichberg + */ +public class Main { + + /** + * Starts the application. + * + * @param args + * a list of filenames, a new editor frame is created for each + * file. + */ + public static void main(String[] args) { + + if (System.getProperty("os.name").startsWith("Mac OS X")) { + // we have to avoid tight coupling to make the project usable on + // different platforms + try { + Class.forName("de.tud.cs.se.flashcards.MacOSXAdapter"); + } catch (ClassNotFoundException cnfe) { + System.err + .println("Setting up the Mac OS X integration failed. Error:"); + cnfe.printStackTrace(System.err); + } + } else { + try { + UIManager.setLookAndFeel(UIManager + .getSystemLookAndFeelClassName()); + } catch (Exception e) { + System.err + .println("The native system look and feel is not available (" + + e.getLocalizedMessage() + ")."); + } + } + + // show all user interface related properties + Iterator> properties = javax.swing.UIManager + .getDefaults().entrySet().iterator(); + while (properties.hasNext()) { + Entry property = properties.next(); + System.out.println(property.getKey() + " = " + property.getValue()); + } + + // let's try to open one of the documents specified on the command line + boolean documentOpened = false; + if (args.length > 0) { + for (String arg : args) { + if (FlashcardsWindow.createFlashcardsEditor(new File(arg))) + documentOpened = true; + } + } + // either the user didn't specify a document on the command line or all + // specified documents + // were unreadable + if (!documentOpened) { + new FlashcardsWindow(FlashcardSeries.createInitialFlashcardSeries()); + } + } +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/Flashcard.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/Flashcard.java new file mode 100644 index 00000000..9f7962c2 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/Flashcard.java @@ -0,0 +1,102 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.model; + +import java.awt.Dimension; +import java.io.Serializable; + +/** + * A very simple flashcard. + * + * @author Michael Eichberg + */ +public class Flashcard implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * The width of a flashcard. + */ + public static int WIDTH = 600; + + /** + * The height of a flashcard. + */ + public static int HEIGHT = 400; + + /** + * The dimension of flashcards. + * + * @see #WIDTH + * @see #HEIGHT + */ + public static final Dimension FLASHCARD_DIMENSION = new Dimension(WIDTH, + HEIGHT); + + private String question; + + private String answer; + + public Flashcard(String question, String answer) { + + this.question = question; + this.answer = answer; + } + + // convenience constructor + public Flashcard() { + + this("", ""); + } + + public String getAnswer() { + + return answer; + } + + public String getQuestion() { + + return question; + } + + public void setAnswer(String answer) { + + this.answer = answer; + } + + public void setQuestion(String question) { + + this.question = question; + } + +} \ No newline at end of file diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/FlashcardSeries.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/FlashcardSeries.java new file mode 100644 index 00000000..42b02003 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/model/FlashcardSeries.java @@ -0,0 +1,169 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/** + * A series represents a set of flashcards and basically provides a set of + * management functions. + * + * @author Michael Eichberg + */ +public class FlashcardSeries implements ListModel { + // We did deliberately not extend "AbstractListModel" to avoid that Java + // Serialization of this + // (then Serializable) class would store references to listeners that do not + // belong to the model. + + /** + * Convenience method to create an initial flashcard series. + */ + public static FlashcardSeries createInitialFlashcardSeries() { + + FlashcardSeries flashcards = new FlashcardSeries(); + flashcards.addCard(new Flashcard("lose Kopplung", "loose coupling")); + flashcards.addCard(new Flashcard("hoher Zusammenhalt", "high cohesion")); + flashcards.addCard(new Flashcard("Stellvertreter", "Proxy")); + flashcards.addCard(new Flashcard("Entwurfsmuster", "Design Pattern")); + flashcards.addCard(new Flashcard("Beispiel", "Example")); + flashcards.addCard(new Flashcard("Haus", "House")); + flashcards.addCard(new Flashcard("Hund", "Dog")); + + return flashcards; + } + + public static final ListDataListener[] NO_LIST_DATA_LISTENERS = new ListDataListener[0]; + + // This array is treated as immutable (i.e., its content never changes!) + private ListDataListener[] listDataListeners = NO_LIST_DATA_LISTENERS; + + private final List flashcards = new ArrayList(); + + public synchronized void addListDataListener(ListDataListener l) { + + // It is an error to register the same listener twice! + + ListDataListener[] newListDataListeners = new ListDataListener[this.listDataListeners.length + 1]; + System.arraycopy(this.listDataListeners, 0, newListDataListeners, 0, + this.listDataListeners.length); + newListDataListeners[this.listDataListeners.length] = l; + + this.listDataListeners = newListDataListeners; + } + + public synchronized void removeListDataListener(ListDataListener l) { + + // It is an error to try to remove a listener that is not (no longer) + // registered. + + ListDataListener[] newListDataListeners = new ListDataListener[this.listDataListeners.length - 1]; + int index = 0; + for (; index < listDataListeners.length; index++) { + if (listDataListeners[index] == l) + break; + } + System.arraycopy(listDataListeners, 0, newListDataListeners, 0, index); + if (index < (listDataListeners.length - 1)) { + System.arraycopy(listDataListeners, index + 1, + newListDataListeners, index, listDataListeners.length + - (index + 1)); + } + + this.listDataListeners = newListDataListeners; + } + + protected ListDataListener[] getListDataListeners() { + + return listDataListeners; + } + + protected void fireIntervalAdded(Object source, int index0, int index1) { + + if (listDataListeners != NO_LIST_DATA_LISTENERS) { + ListDataListener[] listeners = listDataListeners; + ListDataEvent e = new ListDataEvent(source, + ListDataEvent.INTERVAL_ADDED, index0, index1); + + for (int i = listeners.length - 1; i >= 0; i -= 1) { + listeners[i].intervalAdded(e); + } + } + } + + protected void fireIntervalRemoved(Object source, int index0, int index1) { + + if (listDataListeners != NO_LIST_DATA_LISTENERS) { + ListDataListener[] listeners = listDataListeners; + ListDataEvent e = new ListDataEvent(source, + ListDataEvent.INTERVAL_REMOVED, index0, index1); + + for (int i = listeners.length - 1; i >= 0; i -= 1) { + listeners[i].intervalRemoved(e); + } + } + } + + public void addCard(Flashcard flashcard) { + + flashcards.add(0, flashcard); + fireIntervalAdded(this, 0, 0); + } + + public void removeCards(int[] indices) { + + int i = indices.length - 1; + while (i >= 0) { + int index = indices[i]; + flashcards.remove(index); + fireIntervalRemoved(this, index, index); + i -= 1; + } + } + + public Flashcard getElementAt(int i) { + + return flashcards.get(i); + } + + public int getSize() { + + return flashcards.size(); + } + +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/persistence/Store.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/persistence/Store.java new file mode 100644 index 00000000..ae072c91 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/persistence/Store.java @@ -0,0 +1,100 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.persistence; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.commons.io.IOUtils; + +import de.tud.cs.se.flashcards.model.Flashcard; +import de.tud.cs.se.flashcards.model.FlashcardSeries; + +/** + * Some helper methods related to persisting a flashcard series. + *

+ * Persistence is currently not handled properly! Do never + * use Java Serialization for long term storage! + *

+ * + * @author Michael Eichberg + */ +public class Store { + + public static final String FILE_ENDING = ".flashcards"; + + public static FlashcardSeries openSeries(File file) throws IOException { + + ObjectInputStream oin = null; + try { + + FlashcardSeries series = new FlashcardSeries(); + + oin = new ObjectInputStream(new FileInputStream(file)); + int size = oin.readInt(); + for (int i = 0; i < size; i++) { + series.addCard((Flashcard) oin.readObject()); + } + + return series; + } catch (ClassNotFoundException e) { + // the file did contain something unexpected... + throw new IOException(e); + } finally { + if (oin != null) + IOUtils.closeQuietly(oin); + } + } + + public static void saveSeries(FlashcardSeries series, File file) + throws IOException { + + ObjectOutputStream oout = null; + try { + oout = new ObjectOutputStream(new FileOutputStream(file)); + oout.writeInt(series.getSize()); + for (int i = series.getSize() - 1; i >= 0; i -= 1) { + oout.writeObject(series.getElementAt(i)); + } + } finally { + if (oout != null) + oout.close(); + } + + } + +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardEditor.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardEditor.java new file mode 100644 index 00000000..ec499dfa --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardEditor.java @@ -0,0 +1,214 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.ui; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; + +import de.tud.cs.se.flashcards.model.Flashcard; + +/** + * An editor to edit basic flashcards. + * + * @author Michael Eichberg + */ +public class FlashcardEditor { + + private final FlashcardsWindow owner; + + // GUI components + + private final JDialog dialog; + + private final Box questionBox; + + private final JLabel questionLabel; + + private final JTextField questionField; + + private final Box answerBox; + + private final JLabel answerLabel; + + private final JScrollPane answerTextAreaScrollPane; + + private final JTextArea answerTextArea; + + private final Box okCancelBox; + + private final JButton okButton; + + private final JButton cancelButton; + + /** + * Creates a new editor that can be used to edit flashcards. + * + * @param owner + * This editor's parent frame. + */ + public FlashcardEditor(FlashcardsWindow owner) { + + this.owner = owner; + + // Setup the components: + + questionField = new JTextField(); + questionField.setAlignmentX(0.0f); + + questionLabel = new JLabel("Question"); + questionLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + questionLabel.setAlignmentX(0.0f); + + questionBox = Box.createVerticalBox(); + questionBox.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10), + BorderFactory.createBevelBorder(BevelBorder.LOWERED))); + questionBox.add(questionLabel); + questionBox.add(Box.createVerticalStrut(5)); + questionBox.add(questionField); + + answerLabel = new JLabel("Answer"); + answerLabel.setAlignmentX(0.0f); + answerLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + + answerTextArea = new JTextArea(); + answerTextArea.setLineWrap(true); + answerTextArea.setWrapStyleWord(true); + + answerTextAreaScrollPane = new JScrollPane(answerTextArea); + answerTextAreaScrollPane.setAlignmentX(0.0f); + answerTextAreaScrollPane.setBorder(UIManager + .getBorder("ScrollPane.border")); + answerTextAreaScrollPane + .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + answerBox = Box.createVerticalBox(); + answerBox.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10), + BorderFactory.createBevelBorder(BevelBorder.LOWERED))); + answerBox.add(answerLabel); + answerBox.add(Box.createVerticalStrut(5)); + answerBox.add(answerTextAreaScrollPane); + + okButton = new JButton("Ok"); + + cancelButton = new JButton("Cancel"); + + okCancelBox = Box.createHorizontalBox(); + okCancelBox.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + okCancelBox.add(Box.createGlue()); + okCancelBox.add(cancelButton); + okCancelBox.add(okButton); + + dialog = new JDialog(this.owner.getFrame(), "Edit Flashcard", true); + dialog.getRootPane().putClientProperty("Window.style", "small"); + dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + dialog.setMinimumSize(new java.awt.Dimension(320, 240)); + dialog.setSize(640, 480); + dialog.setLocationRelativeTo(this.owner.getFrame()); + dialog.getContentPane().add(questionBox, BorderLayout.NORTH); + dialog.getContentPane().add(answerBox); + dialog.getContentPane().add(okCancelBox, BorderLayout.SOUTH); + + // Configure the event handling: + + cancelButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + update = false; + dialog.setVisible(false); + } + }); + okButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + update = true; + dialog.setVisible(false); + } + }); + } + + /** + * True if the card needs to be udpated, false otherwise. This variable is + * set when the dialog is closed. + */ + private boolean update = false; + + /** + * Edits a given flashcard. If the flashcard was edited, then + * true is returned. + * + * @param card + * The flashcard that may be edited. The flashcard is used to + * initialize this dialog. + * @return true if the card was edited; false otherwise. + */ + public boolean edit(Flashcard card) { + + // set to false to make sure that the card is not updated, when the + // dialog is closed + // using the dialogs "close" button + update = false; + + // configure the editor + questionField.setText(card.getQuestion()); + answerTextArea.setText(card.getAnswer()); + + // show the dialog to enable the user to edit the flashcard + dialog.setVisible(true); + + // the dialog is closed + if (update) { + card.setQuestion(questionField.getText()); + card.setAnswer(answerTextArea.getText()); + } + + return update; + } + +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardsWindow.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardsWindow.java new file mode 100644 index 00000000..c9c76b32 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/FlashcardsWindow.java @@ -0,0 +1,497 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.ui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FileDialog; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import de.tud.cs.se.flashcards.model.Flashcard; +import de.tud.cs.se.flashcards.model.FlashcardSeries; +import de.tud.cs.se.flashcards.persistence.Store; +import javax.swing.JLabel; +import javax.swing.ListCellRenderer; + +/** + * A Frame is always associated with exactly one document and it is the parent + * of all related dialogs etc. + * + * @author Michael Eichberg + * @author Ralf Mitschke + */ +public class FlashcardsWindow { + + // The UI components: + + private final JFrame frame; + + private final JMenuBar menuBar; + + private final JMenu fileMenu; + + private final JMenuItem newFileMenuItem; + + private final JMenuItem openFileMenuItem; + + private final JMenuItem saveFileMenuItem; + + private final JMenuItem saveAsFileMenuItem; + + private final JMenuItem closeFileMenuItem; + + private final JToolBar toolbar; + + private final JButton addButton; + + private final JButton removeButton; + + private final JButton editButton; + + private final JButton playButton; + + private final JScrollPane listScrollPane; + + private final JList list; + + private final FlashcardEditor flashcardEditor; + + private final LearnDialog learnDialog; + + private final FileDialog fileDialog; + + // State of the editor: + + private final FlashcardSeries series; + + private File file; + + protected FlashcardsWindow(File file) throws IOException { + this(Store.openSeries(file)); + + this.file = file; + Utilities.setFrameTitle(frame, file); + } + + public static boolean createFlashcardsEditor(File file) { + try { + new FlashcardsWindow(file); + return true; + } catch (Exception e) { + JOptionPane.showMessageDialog( + null, + "The document \"" + file.getName() + + "\" could not be read." + "\n" + + e.getLocalizedMessage(), "", + JOptionPane.WARNING_MESSAGE); + return false; + } + } + + public FlashcardsWindow(FlashcardSeries series) { + + /* + * General Design Decision(s): + * + * ActionListener do not contain domain logic; they always delegate to + * corresponding methods. + * + * All errors are handled as early as possible. + * + * A Frame is associated with exactly one FlashcardSeries. + */ + + this.series = series; + + // setup of this frame; we need to do it here since the rootpane's + // client property has to set before the other components are created + frame = new JFrame(); + frame.getRootPane().putClientProperty("apple.awt.brushMetalLook", + java.lang.Boolean.TRUE); + + Utilities.setFrameTitle(frame, file); + + // dialogs and other components that are related to this frame + flashcardEditor = new FlashcardEditor(this); + + learnDialog = new LearnDialog(this); + + fileDialog = new java.awt.FileDialog(frame); + fileDialog.setFilenameFilter(new FilenameFilter() { + + public boolean accept(File directory, String name) { + return name.endsWith(Store.FILE_ENDING); + } + }); + + // setup the menu and its listeners + newFileMenuItem = new JMenuItem("New"); + newFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + + newFileMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + new FlashcardsWindow(FlashcardSeries.createInitialFlashcardSeries()); + } + + }); + + + + openFileMenuItem = new JMenuItem("Open File..."); + openFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + openFileMenuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + openFlashcardSeries(); + } + }); + + saveFileMenuItem = new JMenuItem("Save"); + saveFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + saveFileMenuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + saveFlashcardSeries(); + } + }); + + saveAsFileMenuItem = new JMenuItem("Save As..."); + saveAsFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, + (java.awt.event.InputEvent.SHIFT_MASK | Toolkit + .getDefaultToolkit().getMenuShortcutKeyMask()))); + saveAsFileMenuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + saveAsFlashcardSeries(); + } + }); + + closeFileMenuItem = new JMenuItem("Close Window"); + closeFileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + closeFileMenuItem.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + closeFlashcardEditor(); + } + }); + + fileMenu = new JMenu("File"); + fileMenu.add(newFileMenuItem); + fileMenu.addSeparator(); + fileMenu.add(openFileMenuItem); + fileMenu.addSeparator(); + fileMenu.add(saveFileMenuItem); + fileMenu.add(saveAsFileMenuItem); + fileMenu.addSeparator(); + fileMenu.add(closeFileMenuItem); + + menuBar = new JMenuBar(); + menuBar.add(fileMenu); + + addButton = Utilities.createToolBarButton(" Create ", "list-add.png", + "create new flashcard"); + addButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + createFlashcard(); + } + }); + + removeButton = Utilities.createToolBarButton(" Delete ", + "list-remove.png", "remove selected flashcards"); + removeButton.setEnabled(false); + removeButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + removeFlashcards(); + } + }); + + editButton = Utilities.createToolBarButton(" Edit ", + "accessories-text-editor.png", "edit selected flashcard"); + editButton.setEnabled(false); + editButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + editFlashcard(); + } + }); + + list = new JList(series); + + list.setCellRenderer(new ListCellRenderer(){ + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = new JLabel(((Flashcard)value).getQuestion()); + label.setEnabled(list.isEnabled()); + label.setFont(list.getFont()); + label.setOpaque(true); + + if (isSelected) { + label.setBackground(list.getSelectionBackground()); + label.setForeground(list.getSelectionForeground()); + } else { + label.setBackground(list.getBackground()); + label.setForeground(list.getForeground()); + } + + return label; + } + }); + + list.addListSelectionListener(new ListSelectionListener() { + + public void valueChanged(ListSelectionEvent event) { + // Only GUI related functionality: + if (list.getSelectedIndex() != -1) { + removeButton.setEnabled(true); + editButton.setEnabled(true); + } else { + removeButton.setEnabled(false); + editButton.setEnabled(false); + } + } + }); + + listScrollPane = new JScrollPane(list); + listScrollPane.setBorder(BorderFactory.createEmptyBorder()); + listScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + playButton = Utilities.createToolBarButton(" Learn ", + "media-playback-start.png", "learn flashcards"); + + + playButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent event) { + + learn(); + } + }); + + + + series.addListDataListener(new ListDataListener() { + public void intervalAdded(ListDataEvent e) { + if(((FlashcardSeries)e.getSource()).getSize() <= 0){ + playButton.setEnabled(false); + } else { + playButton.setEnabled(true); + } + } + + public void intervalRemoved(ListDataEvent e) { + if(((FlashcardSeries)e.getSource()).getSize() <= 0){ + playButton.setEnabled(false); + } else { + playButton.setEnabled(true); + } + } + + public void contentsChanged(ListDataEvent e) {} + }); + + + + + toolbar = new JToolBar(); + toolbar.putClientProperty("JToolBar.isRollover", Boolean.FALSE); + toolbar.add(addButton); + toolbar.add(removeButton); + toolbar.addSeparator(); + toolbar.add(editButton); + toolbar.add(Box.createHorizontalGlue()); + toolbar.add(playButton); + + toolbar.setFloatable(false); + + frame.setJMenuBar(menuBar); + frame.getContentPane().add(listScrollPane); + frame.getContentPane().add(toolbar, BorderLayout.NORTH); + frame.setSize(640, 480); + frame.setLocationByPlatform(true); + frame.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + frame.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosed(WindowEvent event) { + + SwingUtilities.invokeLater(new Runnable() { + + public void run() { + // we have to make sure that the JFrame object will be + // collected... + // (the VM terminates if all frames are disposed and + // finally collected) + System.gc(); + } + }); + } + + }); + + // Everything is setup; show the window: + frame.setVisible(true); + } + + // Implementation of the "logic": + + public FlashcardSeries getSeries() { + return series; + } + + public JFrame getFrame() { + return frame; + } + + protected void openFlashcardSeries() { + fileDialog.setMode(FileDialog.LOAD); + fileDialog.setVisible(true); + String filename = fileDialog.getFile(); + if (filename != null) { + if (!filename.endsWith(Store.FILE_ENDING)) + filename += Store.FILE_ENDING; + File file = new File(fileDialog.getDirectory(), filename); + createFlashcardsEditor(file); + } + } + + protected void saveFlashcardSeries() { + if (file == null) + saveAsFlashcardSeries(); + else + doSave(file); + } + + protected void saveAsFlashcardSeries() { + fileDialog.setMode(FileDialog.SAVE); + fileDialog.setVisible(true); + String filename = fileDialog.getFile(); + if (filename != null) { + if (!filename.endsWith(Store.FILE_ENDING)) + filename += Store.FILE_ENDING; + + File newFile = new File(fileDialog.getDirectory(), filename); + if (newFile.exists()) { + if (JOptionPane + .showConfirmDialog( + frame, + "The file with the name:\n" + + filename + + "\nalready exists.\nDo you want to overwrite the file?", + "Warning", JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) + return; + } + doSave(newFile); + } + + } + + protected void doSave(File file) { + try { + + Store.saveSeries(series, file); + + // Saving the file was successful: + this.file = file; + Utilities.setFrameTitle(frame, file); + + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, "Could not save flashcards", + "Saving the flashcards to :\n" + file.getName() + + "\nfailed.", JOptionPane.ERROR_MESSAGE); + } + } + + public void learn() { + learnDialog.show(); + } + + protected void closeFlashcardEditor() { + frame.setVisible(false); + frame.dispose(); // required to give up all resources + } + + protected void createFlashcard() { + Flashcard card = new Flashcard(); + if (flashcardEditor.edit(card)) + series.addCard(card); + } + + protected void removeFlashcards() { + FlashcardsWindow.this.series.removeCards(list.getSelectedIndices()); + list.clearSelection(); + } + + protected void editFlashcard() { + int index = list.getSelectedIndex(); + flashcardEditor.edit(series.getElementAt(index)); + } + +} \ No newline at end of file diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/LearnDialog.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/LearnDialog.java new file mode 100644 index 00000000..d53fc8fa --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/LearnDialog.java @@ -0,0 +1,196 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.ui; + +import static de.tud.cs.se.flashcards.ui.Utilities.createImageIcon; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.SwingConstants; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; +import javax.swing.border.EtchedBorder; + +import de.tud.cs.se.flashcards.model.Flashcard; +import de.tud.cs.se.flashcards.model.FlashcardSeries; + +/** + * This dialog first renders a flashcard's question and then the answer. + * Additionally, the logic to step through a series of flashcards is provided. + * + * @author Michael Eichberg + */ +public class LearnDialog { + + private final FlashcardsWindow owner; + + private final JDialog dialog; + + protected final Box headerBox; + + protected final JLabel titleLabel; + + protected final JButton cancelButton; + + protected final JLabel contentLabel; + + protected final Box navigationBox; + + protected final JButton nextButton; + + public LearnDialog(FlashcardsWindow owner) { + + this.owner = owner; + + dialog = new JDialog(owner.getFrame(), true); + dialog.getRootPane().putClientProperty( + "apple.awt.draggableWindowBackground", Boolean.TRUE); + dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + + // Create the header components: + titleLabel = new JLabel(); // need to be initialized... + titleLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 10, 10)); + titleLabel.setVerticalAlignment(SwingConstants.CENTER); + titleLabel + .setPreferredSize(new JLabel("XXXXXXXXXX").getPreferredSize()); + + cancelButton = new JButton(createImageIcon("process-stop.png", + "stop learning")); + cancelButton.setBorderPainted(false); + cancelButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + dialog.setVisible(false); + } + }); + + headerBox = Box.createHorizontalBox(); + headerBox.add(titleLabel); + headerBox.add(Box.createHorizontalGlue()); + headerBox.add(cancelButton); + + contentLabel = new JLabel(); // need to be initialized... + contentLabel.setSize(Flashcard.FLASHCARD_DIMENSION); + contentLabel.setPreferredSize(Flashcard.FLASHCARD_DIMENSION); + contentLabel.setBorder(BorderFactory + .createEtchedBorder(EtchedBorder.LOWERED)); + contentLabel.setFont(UIManager.getFont("FormattedTextField.font")); + contentLabel.setHorizontalAlignment(SwingConstants.CENTER); + + // setup the footer + nextButton = new JButton(createImageIcon("go-next.png", "next")); + + navigationBox = Box.createHorizontalBox(); + navigationBox.add(Box.createHorizontalGlue()); + navigationBox.add(nextButton); + nextButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + next(); + } + }); + + dialog.getContentPane().setLayout(new BorderLayout()); + dialog.getContentPane().add(headerBox, BorderLayout.NORTH); + dialog.getContentPane().add(contentLabel, BorderLayout.CENTER); + dialog.getContentPane().add(navigationBox, BorderLayout.SOUTH); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + // dialog.setLocationRelativeTo(owner.getFrame()); + dialog.setLocation(screenSize.width / 2 - (320), + screenSize.height / 2 - 240); + dialog.setUndecorated(true); + ((JComponent) dialog.getContentPane()).setBorder(BorderFactory + .createBevelBorder(BevelBorder.RAISED)); + dialog.pack(); + } + + // The "core" logic: + + enum State { + QUESTION, ANSWER + } + + private State state = null; // initialized by "show" + + private int index = 0; // initialized by "show" + + public void show() { + state = State.QUESTION; + index = -1; + showNextQuestion(); + dialog.setVisible(true); + } + + private void next() { + switch (state) { + + case ANSWER: + showNextQuestion(); + state = State.QUESTION; + break; + + case QUESTION: + showAnswer(); + state = State.ANSWER; + break; + } + } + + private void showNextQuestion() { + index++; + FlashcardSeries fs = owner.getSeries(); + if (fs.getSize() > index) { + titleLabel.setText("Question"); + contentLabel.setText(fs.getElementAt(index).getQuestion()); + } else { + dialog.setVisible(false); + } + } + + private void showAnswer() { + FlashcardSeries fs = owner.getSeries(); + titleLabel.setText("Answer"); + contentLabel.setText(fs.getElementAt(index).getAnswer()); + } + +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html new file mode 100644 index 00000000..8315f751 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon-readme.html @@ -0,0 +1,67 @@ + + + + +Dimension Of Deskmod :: Icon Design + + + + + +
+
+
+
+
+

 

+
+
+
+
+

 

+

+
+
+ + + +
+
+ +
+
+ + diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon.png new file mode 100644 index 00000000..ea6bd3ee Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Papers-icon.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/README-Icons b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/README-Icons new file mode 100644 index 00000000..407409cf --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/README-Icons @@ -0,0 +1,12 @@ +Tango Icon Theme +---------------- + +This is an icon theme that follows the Tango visual guidelines [1]. Currently +it depends on Imagemagick for creation of 24x24 bitmaps by adding a 1px padding +around the 22x22px version. For GNOME and KDE you will also need +icon-naming-utils that allow the theme to work in these environments before +they follow the new naming scheme [2]. + + +[1] http://tango-project.org/Tango_Icon_Theme_Guidelines +[2] http://tango-project.org/Standard_Icon_Naming_Specification diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Utilities.java b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Utilities.java new file mode 100644 index 00000000..bb2a83c5 --- /dev/null +++ b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/Utilities.java @@ -0,0 +1,118 @@ +/** License (BSD Style License): + * Copyright (c) 2010 + * Software Engineering + * Department of Computer Science + * Technische Universität Darmstadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Software Engineering Group or Technische + * Universität Darmstadt nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package de.tud.cs.se.flashcards.ui; + +import java.io.File; +import java.net.URL; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingConstants; + +/** + * General helper methods related to building a user interface with Swing. + * + * @author Michael Eichberg + */ +public class Utilities { + + private Utilities() { + // do nothing - just defined to avoid accidental instance creations + } + + /** + * Sets the frame title based on the name of the file. + * + * @param frame + * The frame's title. + * @param file + * The document's file (which is edited in the frame.) + */ + public static void setFrameTitle(JFrame frame, File file) { + + if (file != null) { + frame.setTitle(file.getName().substring(0, + file.getName().lastIndexOf('.'))); + frame.getRootPane().putClientProperty("Window.documentFile", file); + } else + frame.setTitle("untitled"); + } + + /** + * Creates a JButton object that can be placed in toolbars. + * + * @param title + * The (very short) title of the button. The title will be + * displayed below the button. + * @param iconPath + * The path to the ImageIcon. + * @param iconDescription + * A short description of the icon / the action. + * @return A new JButton. + * @see #createImageIcon(String, String) + */ + public static JButton createToolBarButton(String title, String iconPath, + String iconDescription) { + + JButton button = new JButton(title, createImageIcon(iconPath, + iconDescription)); + button.setVerticalTextPosition(SwingConstants.BOTTOM); + button.setHorizontalTextPosition(SwingConstants.CENTER); + button.setOpaque(false); + button.setBorder(BorderFactory.createEmptyBorder()); + return button; + } + + /** + * Creates an image icon. If the resource is no longer / not available, an + * exception is thrown. + * + * @param path + * A path relative to the location of this classes compiled class + * file. + * @param description + * A short description of the icon. + */ + public static ImageIcon createImageIcon(String path, String description) { + + URL imgURL = Utilities.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL, description); + } else { + throw new UnknownError("Missing resource: " + path + "(" + + description + ")"); + } + } +} diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/accessories-text-editor.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/accessories-text-editor.png new file mode 100644 index 00000000..c6b62851 Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/accessories-text-editor.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/go-next.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/go-next.png new file mode 100644 index 00000000..6f3f65d3 Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/go-next.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-add.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-add.png new file mode 100644 index 00000000..2acdd8f5 Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-add.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-remove.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-remove.png new file mode 100644 index 00000000..c5524f72 Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/list-remove.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/media-playback-start.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/media-playback-start.png new file mode 100644 index 00000000..66f32d89 Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/media-playback-start.png differ diff --git a/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/process-stop.png b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/process-stop.png new file mode 100644 index 00000000..b68290bf Binary files /dev/null and b/ws2010/se/u4/ex04/src/de/tud/cs/se/flashcards/ui/process-stop.png differ diff --git a/ws2010/se/u4/solution.odt b/ws2010/se/u4/solution.odt new file mode 100644 index 00000000..5c4db3d2 Binary files /dev/null and b/ws2010/se/u4/solution.odt differ diff --git a/ws2010/se/u4/solution.pdf b/ws2010/se/u4/solution.pdf new file mode 100644 index 00000000..b0c3a5fe Binary files /dev/null and b/ws2010/se/u4/solution.pdf differ diff --git a/ws2010/se/u5/A2.odt b/ws2010/se/u5/A2.odt new file mode 100644 index 00000000..b496d38f Binary files /dev/null and b/ws2010/se/u5/A2.odt differ diff --git a/ws2010/se/u5/ex05.pdf b/ws2010/se/u5/ex05.pdf new file mode 100644 index 00000000..45579657 Binary files /dev/null and b/ws2010/se/u5/ex05.pdf differ diff --git a/ws2010/se/u5/solution.pdf b/ws2010/se/u5/solution.pdf new file mode 100644 index 00000000..9c01ae55 Binary files /dev/null and b/ws2010/se/u5/solution.pdf differ diff --git a/ws2010/se/u6/.classpath b/ws2010/se/u6/.classpath new file mode 100644 index 00000000..8778ddd5 --- /dev/null +++ b/ws2010/se/u6/.classpath @@ -0,0 +1,5 @@ + + + + + diff --git a/ws2010/se/u6/.project b/ws2010/se/u6/.project new file mode 100644 index 00000000..afdb2c03 --- /dev/null +++ b/ws2010/se/u6/.project @@ -0,0 +1,17 @@ + + + EiSE-Exercise06 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/ws2010/se/u6/EX6 A1.jpg b/ws2010/se/u6/EX6 A1.jpg new file mode 100644 index 00000000..8a43b6f8 Binary files /dev/null and b/ws2010/se/u6/EX6 A1.jpg differ diff --git a/ws2010/se/u6/Ex6 A2.jpg b/ws2010/se/u6/Ex6 A2.jpg new file mode 100644 index 00000000..c1b4a011 Binary files /dev/null and b/ws2010/se/u6/Ex6 A2.jpg differ diff --git a/ws2010/se/u6/ex06.pdf b/ws2010/se/u6/ex06.pdf new file mode 100644 index 00000000..9a398ef5 Binary files /dev/null and b/ws2010/se/u6/ex06.pdf differ diff --git a/ws2010/se/u6/solution.odt b/ws2010/se/u6/solution.odt new file mode 100644 index 00000000..08a98fc9 Binary files /dev/null and b/ws2010/se/u6/solution.odt differ diff --git a/ws2010/se/u6/solution.pdf b/ws2010/se/u6/solution.pdf new file mode 100644 index 00000000..e8219d20 Binary files /dev/null and b/ws2010/se/u6/solution.pdf differ