diff options
| author | Paul Buetow <paul@buetow.org> | 2009-02-18 17:33:22 +0000 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2009-02-18 17:33:22 +0000 |
| commit | 4722100cba287b164957c658c2e035783e20c963 (patch) | |
| tree | 35733fd3e50aeeb493e38ceaea83521a4710f0ac /sources/client | |
| parent | 61f7175cc3e51c0afaf63e380d03824a77464ba8 (diff) | |
moved sources
Diffstat (limited to 'sources/client')
| -rw-r--r-- | sources/client/AboutWindow.java | 50 | ||||
| -rw-r--r-- | sources/client/CalendarTableCellRenderer.java | 135 | ||||
| -rw-r--r-- | sources/client/CalendarTableModel.java | 481 | ||||
| -rw-r--r-- | sources/client/InfoWindow.java | 57 | ||||
| -rw-r--r-- | sources/client/LicenseWindow.java | 33 | ||||
| -rw-r--r-- | sources/client/NetCalendarClient.java | 731 | ||||
| -rw-r--r-- | sources/client/ServerRequester.java | 82 | ||||
| -rw-r--r-- | sources/client/SplashScreen.java | 42 | ||||
| -rw-r--r-- | sources/client/SubWindow.java | 101 | ||||
| -rw-r--r-- | sources/client/helper/DateSpinner.java | 57 | ||||
| -rw-r--r-- | sources/client/helper/GUIHelper.java | 189 | ||||
| -rw-r--r-- | sources/client/inputforms/AdvancedSearching.java | 141 | ||||
| -rw-r--r-- | sources/client/inputforms/CreateNewEvent.java | 122 | ||||
| -rw-r--r-- | sources/client/inputforms/EditExistingEvent.java | 156 | ||||
| -rw-r--r-- | sources/client/inputforms/InputForm.java | 93 | ||||
| -rw-r--r-- | sources/client/inputforms/Preferences.java | 99 | ||||
| -rw-r--r-- | sources/client/inputforms/RenameCategory.java | 123 |
17 files changed, 2692 insertions, 0 deletions
diff --git a/sources/client/AboutWindow.java b/sources/client/AboutWindow.java new file mode 100644 index 0000000..38d947e --- /dev/null +++ b/sources/client/AboutWindow.java @@ -0,0 +1,50 @@ +package client; +import shared.*; + +/** + * This window simply shows an about message about the + * netcalendar. + * @author paul.buetow + * + */ +public class AboutWindow extends InfoWindow { + final static long serialVersionUID = 1L; + /** + * Creates the window and shows it. + * @param sTitleText Specifies the title text of this JFrame. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public AboutWindow(NetCalendarClient netCalendarClient) { + super(netCalendarClient, "About", + Config.VERSION + "\n" + + "(c) 2006, 2009 by Dipl.-Inform. (FH) Paul C. Buetow; " + + "Web: netcalendar.buetow.org; E-Mail: " + getEmailAddr() + "\n\n" + + "NetCalendar is a network capable and mostly UNIX /usr/bin/calendar database compatible Calendar application " + + "programmed in Java. Its initial motivation was a programming project at the Aachen " + + "University of Applied Sciences (www.fh-aachen.de) for the object oriented " + + "programming class. But it became much more than just that!\n\n" + + "Credits:\n\n" + + "Bernhard Schertl " + + "for testing and suggestions for improvements; Web: www.b78.org\n\n" + + "Prof. Dr. rer. nat. H. Fassbender " + + "for supervision of expert opinion; Web: www.fassbender.fh-aachen.de\n\n" + + "Florian P. Buetow " + + "for ideas concerning the splash image; Web: www.florianbuetow.com\n\n" + + "Kay Czarnotta " + + "for ideas concerning the icon and an optimization tip for NetCalendar for Mac OS X; Web: eagleeye.byte-welt.net" + ); + } + + /** + * This method simply returns a string containing the contact email address. + * This method is needed to protect this sourcecode + the email address for + * internet spam because some spambots try to fetch this address from the + * cvsweb interface. + * @return Returns a string containing the contact email address. + */ + private static String getEmailAddr() { + String sEmail = "netcalendar at dev dot buetow dot org"; + sEmail = sEmail.replaceAll(" at ", "@"); + return sEmail.replaceAll(" dot ", "."); + } +} diff --git a/sources/client/CalendarTableCellRenderer.java b/sources/client/CalendarTableCellRenderer.java new file mode 100644 index 0000000..67a9b67 --- /dev/null +++ b/sources/client/CalendarTableCellRenderer.java @@ -0,0 +1,135 @@ +package client; + +import java.awt.*; + +import javax.swing.*; +import javax.swing.table.*; +import java.util.*; + +import shared.*; + +/** + * This class is responsible for the rendering of the JTable of the client gui which contains + * all the events. + * @author buetow + */ +public class CalendarTableCellRenderer extends DefaultTableCellRenderer { + private static final long serialVersionUID = 1L; + private CalendarTableModel tableModel; + // private NetCalendarClient netCalendarClient; + + private static final Color SELECTED_BACKGROUND_COLOR; + private static final Color SELECTED_FOREGROUND_COLOR; + private static final Color ALREADY_OVER_BACKGROUND_COLOR; + private static final Color ALREADY_OVER_FOREGROUND_COLOR; + private static final Color STANDARD_FOREGROUND_COLOR; + private static final Color BACKGROUND_COLOR_1_DAY; + private static final Color BACKGROUND_COLOR_7_DAYS; + private static final Color BACKGROUND_COLOR_28_DAYS; + private static final Color BACKGROUND_COLOR_168_DAYS; + private static final Color BACKGROUND_COLOR_365_DAYS; + private static final Color BACKGROUND_COLOR_MT_365_DAYS; + private static final Color YEARLY_BACKGROUND_COLOR; + private static final Color NOT_YEARLY_BACKGROUND_COLOR; + + + private static final long NANOSECONDS_1_DAY; + private static final long NANOSECONDS_7_DAYS; + private static final long NANOSECONDS_28_DAYS; + private static final long NANOSECONDS_168_DAYS; + private static final long NANOSECONDS_365_DAYS; + + // Initialize once, use often! + static { + SELECTED_BACKGROUND_COLOR = new Color(0, 0, 0); + SELECTED_FOREGROUND_COLOR = new Color(255, 255, 255); + STANDARD_FOREGROUND_COLOR = new Color(0, 0, 0); + ALREADY_OVER_FOREGROUND_COLOR = SELECTED_BACKGROUND_COLOR; + ALREADY_OVER_BACKGROUND_COLOR = SELECTED_FOREGROUND_COLOR; + BACKGROUND_COLOR_1_DAY = new Color(0xff, 0x00, 0x00); + BACKGROUND_COLOR_7_DAYS = new Color(0xff, 0x6c, 0x00); + BACKGROUND_COLOR_28_DAYS = new Color(0xff, 0xa5, 0x00); + BACKGROUND_COLOR_168_DAYS = new Color(0xe7, 0xa5, 0x5e); + BACKGROUND_COLOR_365_DAYS = new Color(230, 218, 161); + BACKGROUND_COLOR_MT_365_DAYS = new Color(0xa2, 0x9c, 0x90); // For more than 365 days + + YEARLY_BACKGROUND_COLOR = new Color(0x65, 0xa9, 0xe3); + NOT_YEARLY_BACKGROUND_COLOR = new Color(0x88, 0xe0, 0x90); + + + NANOSECONDS_1_DAY = 3600 * 24 * 1000; + NANOSECONDS_7_DAYS = NANOSECONDS_1_DAY * 7; + NANOSECONDS_28_DAYS = NANOSECONDS_7_DAYS * 4; + NANOSECONDS_168_DAYS = NANOSECONDS_28_DAYS * 6; + NANOSECONDS_365_DAYS = NANOSECONDS_1_DAY * 365; + } + + /** + * This method creates a custom table cell renderer for the calendar client. + * Its coloring the different cells and sets other special display attributes. + * @param tableModel Specifies the DefaultTableModel object used by the JTable. This is needed to make decisions about displaying a specific cell. + */ + public CalendarTableCellRenderer(CalendarTableModel tableModel) { + // this.netCalendarClient = netCalendarClient; + this.tableModel = tableModel; + } + + /** + * This method returns the Component object of a specific table cell. + * @param jTable Specifies the table object of the calendar client frame. + * @param object Specifies the object which is inside of the specific table cell. + * @param isSelected Specifies if the current cell is selected or not. + * @param hasFocus Specifies if the current cell is focused or not. + * @param iRow Specifies thr row number of the current cell. + * @param iCol specifies the column number of the current cell. + * @return Returns the Component object of a specific table cell. + */ + public Component getTableCellRendererComponent(JTable jTable, Object object, + boolean isSelected, boolean hasFocus, int iRow, int iCol) { + JLabel jLable =(JLabel) super.getTableCellRendererComponent(jTable, object, isSelected, hasFocus, iRow, iCol); + + //MyVector vecSelected = netCalendarClient.getSelectedIndexes(); + + //if (vecSelected.hasLike(new Integer(iRow))) { + if (isSelected) { + jLable.setBackground(SELECTED_BACKGROUND_COLOR); + jLable.setForeground(SELECTED_FOREGROUND_COLOR); + return jLable; + } + + CalendarEvent calendarEvent = tableModel.getEvent(iRow); + jLable.setForeground(STANDARD_FOREGROUND_COLOR); + + if (iCol <= 1) { + if (!calendarEvent.isYearly()) + jLable.setBackground(NOT_YEARLY_BACKGROUND_COLOR); + else + jLable.setBackground(YEARLY_BACKGROUND_COLOR); + + return jLable; + } + + long lCurrentTime = new Date().getTime(); + long lEventTime = calendarEvent.getDate().getTime(); + + if (lCurrentTime + NANOSECONDS_1_DAY > lEventTime) + jLable.setBackground(BACKGROUND_COLOR_1_DAY); + + else if (lCurrentTime + NANOSECONDS_7_DAYS > lEventTime) + jLable.setBackground(BACKGROUND_COLOR_7_DAYS); + + else if (lCurrentTime + NANOSECONDS_28_DAYS > lEventTime) + jLable.setBackground(BACKGROUND_COLOR_28_DAYS); + + else if (lCurrentTime + NANOSECONDS_168_DAYS > lEventTime) + jLable.setBackground(BACKGROUND_COLOR_168_DAYS); + + else if (lCurrentTime + NANOSECONDS_365_DAYS > lEventTime) + jLable.setBackground(BACKGROUND_COLOR_365_DAYS); + + else + jLable.setBackground(BACKGROUND_COLOR_MT_365_DAYS); + + return jLable; + } +} diff --git a/sources/client/CalendarTableModel.java b/sources/client/CalendarTableModel.java new file mode 100644 index 0000000..4520c66 --- /dev/null +++ b/sources/client/CalendarTableModel.java @@ -0,0 +1,481 @@ +package client; + +import javax.swing.table.*; +import javax.swing.*; +import java.util.*; +import shared.*; +import shared.remotecall.*; + +/** + * This class defined the table model of the JTable of the main calendar client window. All table + * data and most of the table actions, like sorting or updating the content, go trough this class. + * @author buetow + * + */ +public final class CalendarTableModel extends AbstractTableModel { + public static final String NUM_HEADER = "#"; + public static final String DATE_HEADER = "Date"; + public static final String CATEGORY_HEADER = "Category"; + public static final String DESCRIPTION_HEADER = "Description"; + public static final String PLACE_HEADER = "Place"; + + private static final int iEnumLength = Config.getStringValue("client_max_events").length(); + private static final long serialVersionUID = 1L; + private static final int iCols = 5; // Num of columns never changes! + private int iRows = 0; + private Vector vecEvents; + private Comparator lastSortComparator = null; + private JTable jTable; + + /** + * Simple constructor, creates a calendar table model to be used with the JTable of the netcalendar client main window. + * @param jTable Specifies the JTable object of this table model. + */ + public CalendarTableModel(JTable jTable) { + this.jTable = jTable; + } + + /** + * This method returns the number of columns of the JTable. + * @return Returns the number of columns of the JTable. + */ + public int getColumnCount() { + return iCols; + } + + /** + * This method retuns the number of rows of the JTable. + * @return Returns the number of rows of the JTable. + */ + public int getRowCount() { + return iRows; + } + + /** + * This method sets the number of rows of the JTable. + * @param iRows Specifies the number of rows of the JTable. + */ + public void setRowCount(int iRows) { + this.iRows = iRows; + } + + /** + * This method checks if a cell is editable or not. + * @param iRow Specifies the tables row. + * @param iCol Specifies the tables column. + * @return Returns true if the cell is editable. Else, false will be returned. + */ + public boolean isCellEditable(int iRow, int iCol) { + if (iCol > 1) + return true; + + return false; + } + + /** + * Gets a specific table value + * @param iRow Specifies the tables row + * @param iCol Specifies the tables column + * @return Returns the object at (row,column) + */ + public Object getValueAt(int iRow, int iCol) { + CalendarEvent calendarEvent = (CalendarEvent) vecEvents.get(iRow); + + switch (iCol) { + case 0: + String sEnum = "" + (iRow + 1); + while (sEnum.length() < iEnumLength) + sEnum = "0" + sEnum; + return sEnum; + case 1: + return calendarEvent.getDate(); + case 2: + return calendarEvent.getDescription(); + case 3: + return calendarEvent.getCategoryName(); + case 4: + return calendarEvent.getPlace(); + } + + return "N/A"; + } + + /** + * This function updates the data of the JTable. + * @param object Specifies the new value. + * @param iRow Specifies the row of the cell to be updated. + * @param iCol Specifies the column of the cell to be updated. + */ + public void setValueAt(Object object, int iRow, int iCol) { + CalendarEvent calendarEvent = (CalendarEvent) vecEvents.get(iRow); + + switch (iCol) { + case 2: + calendarEvent.setDescription((String) object); + break; + case 3: + calendarEvent.setCategoryName((String) object); + break; + case 4: + calendarEvent.setPlace((String) object); + break; + default: + return; + } + + runLastSorter(); + jTable.updateUI(); + + ClientRequest clientRequest = new ClientRequest(ClientRequest.MODIFY_EVENT); + clientRequest.setEvent(calendarEvent); + ServerRequester.sendClientRequest(clientRequest); + } + + /** + * This method returns the class types of a specific table column. + * @param iCol Specifies the column index to get the class type for. + * @return Returns the class type of the specified column. + */ + public Class getColumnClass(int iCol) { + switch (iCol) { + case 0: + return String.class; + case 1: + return MyDate.class; + case 2: + return String.class; + case 3: + return String.class; + case 4: + return String.class; + } + + return String.class; + } + + /** + * This method returns the column header of a specific table column. + * @param iCol Specifies the column index to get the column header for. + * @return Returns the header string of the specified column. + */ + public String getColumnName(int iCol) { + switch (iCol) { + case 0: + return NUM_HEADER; + case 1: + return DATE_HEADER; + case 2: + return DESCRIPTION_HEADER; + case 3: + return CATEGORY_HEADER; + case 4: + return PLACE_HEADER; + } + + return "N/A"; + } + + /** + * This method returns the calendar event which belongs to a specific table row + * @param iRow Specifies the table row index + * @return Returns the calendar event + */ + public CalendarEvent getEvent(int iRow) { + return (CalendarEvent) vecEvents.get(iRow); + } + + /** + * This method updates all the value objects (calendar events) of the table. + * @param vecEvents Specifies the vector of the events to be used. + */ + public void setEvents(Vector vecEvents) { + if (vecEvents == null) + return; + + this.vecEvents = vecEvents; + setRowCount(vecEvents.size()); + + runLastSorter(); + } + + /** + * This method sorts the data again using the last sorting method being used. + */ + private void runLastSorter() { + if (lastSortComparator == null) { + sortByDate(); + + } else { + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + } + } + + /** + * Sorts the table content by a specified table column. + * @param iCol Specifies the table column to sort against. + */ + public void sortByCol(int iCol) { + switch (iCol) { + case 0: + case 1: + sortByDate(); + break; + case 2: + sortByDescription(); + break; + case 3: + sortByCategory(); + break; + case 4: + sortByPlace(); + break; + } + } + + /** + * Reverse sorts the table content by a specified table column. + * @param iCol Specifies the table column to reverse sort against. + */ + public void reverseSortByCol(int iCol) { + switch (iCol) { + case 0: + case 1: + reverseSortByDate(); + break; + case 2: + reverseSortByDescription(); + break; + case 3: + reverseSortByCategory(); + break; + case 4: + reverseSortByPlace(); + break; + } + } + + /** + * Sorts the table content by their IDs. + */ + public void sortByID() { + Main.statusMessage("Sorting by ID..."); + + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + int i = ((CalendarEvent) objectA).getID(); + int j = ((CalendarEvent) objectB).getID(); + if (i == j) + return 0; + else if (i < j) + return -1; + else + return 1; + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + + Main.statusMessage("Sorting by date done"); + } + + /** + * Sorts the table content by their dates. + */ + public void sortByDate() { + Main.statusMessage("Sorting by date..."); + + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + long l = ((CalendarEvent) objectA).getDate().getTime(); + long m = ((CalendarEvent) objectB).getDate().getTime(); + if (l == m) + return 0; + else if (l < m) + return -1; + else + return 1; + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + + Main.statusMessage("Sorting by date done"); + } + + /** + * Sorts the table content by their category names. + */ + public void sortByCategory() { + Main.statusMessage("Sorting by category..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventA.getCategoryName().compareTo(eventB.getCategoryName()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Sorting by category done"); + } + + /** + * Sorts the table content by their description texts. + */ + public void sortByDescription() { + Main.statusMessage("Sorting by description..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventA.getDescription().compareTo(eventB.getDescription()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Sorting by description done"); + } + + /** + * Sorts the table content by their places. + */ + public void sortByPlace() { + Main.statusMessage("Sorting by place..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventA.getPlace().compareTo(eventB.getPlace()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Sorting by place done"); + } + + /** + * Reverse sorts the table content by their IDs. + */ + public void reverseSortByID() { + Main.statusMessage("Reverse sorting by date..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + long i = ((CalendarEvent) objectA).getID(); + long j = ((CalendarEvent) objectB).getID(); + if (i == j) + return 0; + else if (i > j) + return -1; + else + return 1; + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Reverse sorting by date done"); + } + + /** + * Reverse sorts the table content by their dates. + */ + public void reverseSortByDate() { + Main.statusMessage("Reverse sorting by date..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + long l = ((CalendarEvent) objectA).getDate().getTime(); + long m = ((CalendarEvent) objectB).getDate().getTime(); + if (l == m) + return 0; + else if (l > m) + return -1; + else + return 1; + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Reverse sorting by date done"); + } + + /** + * Reverse sorts the table content by their category names. + */ + public void reverseSortByCategory() { + Main.statusMessage("Reverse sorting by category..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventB.getCategoryName().compareTo(eventA.getCategoryName()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Reverse sorting by category done"); + } + + /** + * Reverse sorts the table content by their description texts. + */ + public void reverseSortByDescription() { + Main.statusMessage("Reverse sorting by description..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventB.getDescription().compareTo(eventA.getDescription()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Reverse sorting by description done!"); + } + + /** + * Reverse sorts the table content by their places. + */ + public void reverseSortByPlace() { + Main.statusMessage("Reverse sorting by place..."); + lastSortComparator = new Comparator() { + public int compare(Object objectA, Object objectB) { + CalendarEvent eventA = (CalendarEvent) objectA; + CalendarEvent eventB = (CalendarEvent) objectB; + return eventB.getPlace().compareTo(eventA.getPlace()); + } + public boolean equals(Object object) { + return false; + } + }; + Collections.sort(vecEvents, lastSortComparator); + jTable.updateUI(); + Main.statusMessage("Reverse sorting by place done"); + } +} diff --git a/sources/client/InfoWindow.java b/sources/client/InfoWindow.java new file mode 100644 index 0000000..bdcc744 --- /dev/null +++ b/sources/client/InfoWindow.java @@ -0,0 +1,57 @@ +package client; + +import java.awt.*; +import javax.swing.*; + +/** + * This window simply shows an about message about the + * netcalendar. + * @author paul.buetow + * + */ +public class InfoWindow extends SubWindow { + final static long serialVersionUID = 1L; + private String sText; + + /** + * Creates the window and shows it. + * @param netCalendarClient Specifies the calendar client session object to use. + * @param jTitle Speicifies the title text to be displayd in the title bar. + * @param jText Specifies the text to be displayed at the text area. + */ + public InfoWindow(NetCalendarClient netCalendarClient, String jTitle, String sText) { + super(jTitle, netCalendarClient); + this.sText = sText; + initComponents(); + setResizable(false); + pack(); + setVisible(true); + } + + /** + * This method initializes all the GUI components. + */ + protected void initComponents() { + setSize(306,400); + JPanel contentPane = (JPanel) getContentPane(); + contentPane.setBackground(Color.BLACK); + + // Build the splash screen + JLabel jLabel = new JLabel(new ImageIcon("images/netcal.png")); + contentPane.add(jLabel, BorderLayout.CENTER); + + JTextArea jTextArea = new JTextArea(); + jTextArea.setEditable(false); + jTextArea.setBackground(Color.BLACK); + jTextArea.setForeground(Color.WHITE); + jTextArea.setLineWrap(true); + jTextArea.setWrapStyleWord(true); + jTextArea.setMargin(new Insets(10, 10, 10, 10)); + jTextArea.setText(sText); + jTextArea.setFocusable(false); + jTextArea.setEnabled(false); + JScrollPane jScrollPane = new JScrollPane(jTextArea); + jScrollPane.setPreferredSize(new Dimension(306, 400-261)); + contentPane.add(jScrollPane, BorderLayout.SOUTH); + } +} diff --git a/sources/client/LicenseWindow.java b/sources/client/LicenseWindow.java new file mode 100644 index 0000000..b8a2faa --- /dev/null +++ b/sources/client/LicenseWindow.java @@ -0,0 +1,33 @@ +package client; + +import shared.*; + +/** + * This window simply shows an license message. + * @author buetow + * + */ +public class LicenseWindow extends InfoWindow { + final static long serialVersionUID = 1L; + /** + * Creates the window and shows it. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public LicenseWindow(NetCalendarClient netCalendarClient) { + super(netCalendarClient, "License", + Config.VERSION + "\n" + + "Copyright (C) 2006, 2009 by Paul C. Buetow\n\n" + + "This program is free software; you can redistribute it and/or " + + "modify it under the terms of the GNU General Public License " + + "as published by the Free Software Foundation; either version 2 " + + "of the License, or (at your option) any later version.\n\n" + + "This program is distributed in the hope that it will be useful, " + + "but WITHOUT ANY WARRANTY; without even the implied warranty of " + + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " + + "GNU General Public License for more details.\n\n" + + "You should have received a copy of the GNU General Public License " + + "along with this program; if not, write to the Free Software " + + "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA." + ); + } +} diff --git a/sources/client/NetCalendarClient.java b/sources/client/NetCalendarClient.java new file mode 100644 index 0000000..14c6708 --- /dev/null +++ b/sources/client/NetCalendarClient.java @@ -0,0 +1,731 @@ +/** + */ + +package client; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.table.*; +import java.util.*; + +import shared.*; +import shared.remotecall.*; +import client.inputforms.*; + +/** + * This is the main class of the client part of the netcalendar suite. It contains the main GUI. + * All subguis are created within this class. + * @author buetow + */ +public class NetCalendarClient extends JFrame { + private static final long serialVersionUID = 1L; + private static int iNextSession = 1; + private static int iNumCurrentSessions = 0; + private int iCurrentSession; + private NetCalendarClient netCalendarClient; + private Vector vecFrames = new Vector(); + + // Diverse components + private ClientRequest lastClientRequest = null; + protected int iCurrentMouseSelectedRow = 0; + protected int iCurrentMouseSelectedCol = 0; + + // GUI components + private JMenuBar jMenuBar; + private JPopupMenu jPopupMenu; + private CalendarTableModel tableModel; + private JTable jTable; + + private JTextField jTextFieldRegexp; + private JTextField jTextFieldStatusMessages; + + // Some callback objects + private DoCallback doCallbackEditEvent; + private DoCallback doCallbackDeleteEvent; + private DoCallback doCallbackCopyEvent; + private DoCallback doCallbackDeleteCategory; + private DoCallback doCallbackRenameCategory; + + // Static GUI strings which needs to be specified at least twice + private final static String DELETE_EVENT = "Delete event(s)"; + private final static String EDIT_EVENT = "Edit event(s)"; + private final static String COPY_EVENT = "Copy event(s)"; + private final static String CREATE_EVENT = "Create new event"; + private final static String DELETE_CATEGORY = "Delete whole category(s)"; + private final static String RENAME_CATEGORY = "Rename whole category(s)"; + private final static String ADVANCED_SEARCH = "Advanced searching"; + private final static String SORT_BY_COL = "Sort by this row"; + private final static String REVERSE_SORT_BY_COL = "Reverse sort by this row"; + private final static String ENTER_REGEXP_HERE ="Enter some regexp search string here..."; + + /** + * Standard constructor, creates the client GUI. + */ + public NetCalendarClient() { + super(getSessionString(iNextSession) + Config.VERSION); + this.iCurrentSession = iNextSession++; + + // Save a reference of this to allow to access this object through + // inner-classes + // (See the "Advanced searching" action listener object for example!) + this.netCalendarClient = this; + iNumCurrentSessions++; + + initComponents(); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setLocationRelativeTo(null); + pack(); + setVisible(true); + + // Start a default request to the netcalendar server + update(new ClientRequest(ClientRequest.REQUEST_ALL_EVENTS)); + } + + /** + * Initializes all the GUI components. + */ + private void initComponents() { + this.addWindowListener(new WindowListener() { + public void windowActivated(WindowEvent e) { } + public void windowClosing(WindowEvent e) {} + public void windowDeactivated(WindowEvent e) {} + public void windowDeiconified(WindowEvent e) {} + public void windowIconified(WindowEvent e) { } + public void windowOpened(WindowEvent e) {} + public void windowClosed(WindowEvent e) { + if (--iNumCurrentSessions == 0) + Main.exit(0); + + Main.infoMessage("Closing a session window"); + } + }); + + Container container = getContentPane(); + + jMenuBar = new JMenuBar(); + setJMenuBar(jMenuBar); + + JMenu jMenuSession = new JMenu("Session"); + jMenuBar.add(jMenuSession); + + JMenuItem jMenuItemNewWindow = new JMenuItem("New window"); + jMenuSession.add(jMenuItemNewWindow); + jMenuItemNewWindow.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new NetCalendarClient(); + } + }); + + JMenuItem jMenuItemCloseWindow = new JMenuItem("Close window"); + jMenuSession.add(jMenuItemCloseWindow); + jMenuItemCloseWindow.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + dispose(); + } + }); + + jMenuSession.add(new JSeparator()); + + JMenuItem jMenuItemPreferences = new JMenuItem("Preferences"); + jMenuSession.add(jMenuItemPreferences); + jMenuItemPreferences.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new Preferences(netCalendarClient); + } + }); + + jMenuSession.add(new JSeparator()); + + JMenuItem jMenuItemQuit = new JMenuItem("Quit"); + jMenuSession.add(jMenuItemQuit); + jMenuItemQuit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + System.exit(0); + } + }); + + JMenu jMenuEdit = new JMenu("Edit"); + jMenuBar.add(jMenuEdit); + + JMenuItem jMenuItemCreate = new JMenuItem(CREATE_EVENT); + jMenuEdit.add(jMenuItemCreate); + jMenuItemCreate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new CreateNewEvent(netCalendarClient); + } + }); + + JMenuItem jMenuItemEdit = new JMenuItem(EDIT_EVENT); + jMenuEdit.add(jMenuItemEdit); + doCallbackEditEvent = new DoCallback() { + public void callback(Object obj) { + new EditExistingEvent(netCalendarClient, (CalendarEvent) obj); + } + }; + jMenuItemEdit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + foreachSelectedEvent(doCallbackEditEvent); + } + }); + + JMenuItem jMenuItemCopy = new JMenuItem(COPY_EVENT); + jMenuEdit.add(jMenuItemCopy); + doCallbackCopyEvent = new DoCallback() { + public void callback(Object obj) { + CalendarEvent calendarEvent = (CalendarEvent) obj; + ClientRequest clientRequest = new ClientRequest(ClientRequest.ADD_EVENT); + clientRequest.setEvent(calendarEvent); + ServerRequester.sendClientRequest(clientRequest); + netCalendarClient.updateLast(); + } + }; + jMenuItemCopy.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + foreachSelectedEvent(doCallbackCopyEvent); + } + }); + + JMenuItem jMenuItemDelete = new JMenuItem(DELETE_EVENT); + jMenuEdit.add(jMenuItemDelete); + doCallbackDeleteEvent = new DoCallback() { + public void callback(Object obj) { + deleteEvent((CalendarEvent)obj); + jTable.getSelectionModel().clearSelection(); + } + }; + jMenuItemDelete.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + foreachSelectedEvent(doCallbackDeleteEvent); + } + }); + + jMenuEdit.add(new JSeparator()); + + JMenuItem jMenuItemRenameCategory = new JMenuItem(RENAME_CATEGORY); + jMenuEdit.add(jMenuItemRenameCategory); + doCallbackRenameCategory = new DoCallback() { + public void callback(Object obj) { + new RenameCategory(netCalendarClient, (CalendarEvent) obj); + jTable.getSelectionModel().clearSelection(); + } + }; + jMenuItemRenameCategory.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + foreachSelectedEvent(doCallbackRenameCategory); + } + }); + + JMenuItem jMenuItemDeleteCategory = new JMenuItem(DELETE_CATEGORY); + jMenuEdit.add(jMenuItemDeleteCategory); + doCallbackDeleteCategory = new DoCallback() { + public void callback(Object obj) { + deleteCategory((CalendarEvent)obj); + jTable.getSelectionModel().clearSelection(); + } + }; + jMenuItemDeleteCategory.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + foreachSelectedEvent(doCallbackDeleteCategory); + } + }); + + + JMenu jMenuSorting = new JMenu("Sorting"); + jMenuBar.add(jMenuSorting); + + JMenuItem jMenuItemSortByDate = new JMenuItem("Sort by date"); + jMenuSorting.add(jMenuItemSortByDate); + jMenuItemSortByDate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.sortByDate(); + } + }); + JMenuItem jMenuItemSortByCategory = new JMenuItem("Sort by category"); + jMenuSorting.add(jMenuItemSortByCategory); + jMenuItemSortByCategory.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.sortByCategory(); + } + }); + JMenuItem jMenuItemSortByDescr = new JMenuItem("Sort by description"); + jMenuSorting.add(jMenuItemSortByDescr); + jMenuItemSortByDescr.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.sortByDescription(); + } + }); + JMenuItem jMenuItemSortByPlace = new JMenuItem("Sort by place"); + jMenuSorting.add(jMenuItemSortByPlace); + jMenuItemSortByPlace.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.sortByPlace(); + } + }); + JMenuItem jMenuItemSortByEventIDs = new JMenuItem("Sort by event IDs"); + jMenuSorting.add(jMenuItemSortByEventIDs); + jMenuItemSortByEventIDs.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.sortByID(); + } + }); + + jMenuSorting.add(new JSeparator()); + + JMenuItem jMenuItemReverseSortByDate = new JMenuItem( + "Reverse sort by date"); + jMenuSorting.add(jMenuItemReverseSortByDate); + jMenuItemReverseSortByDate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.reverseSortByDate(); + } + }); + JMenuItem jMenuItemReverseSortByCategory = new JMenuItem( + "Reverse sort by category"); + jMenuSorting.add(jMenuItemReverseSortByCategory); + jMenuItemReverseSortByCategory.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.reverseSortByCategory(); + } + }); + JMenuItem jMenuItemReverseSortByDescr = new JMenuItem( + "Reverse sort by description"); + jMenuSorting.add(jMenuItemReverseSortByDescr); + jMenuItemReverseSortByDescr.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.reverseSortByDescription(); + } + }); + JMenuItem jMenuItemReverseSortByPlace = new JMenuItem( + "Reverse sort by place"); + jMenuSorting.add(jMenuItemReverseSortByPlace); + jMenuItemReverseSortByPlace.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.reverseSortByPlace(); + } + }); + JMenuItem jMenuItemReverseSortByIDs = new JMenuItem( + "Reverse sort by event IDs"); + jMenuSorting.add(jMenuItemReverseSortByIDs); + jMenuItemReverseSortByIDs.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + tableModel.reverseSortByID(); + } + }); + + JMenu jMenuServer = new JMenu("Server"); + jMenuBar.add(jMenuServer); + + JMenuItem jMenuItemUpdate = new JMenuItem("Update events from server"); + jMenuServer.add(jMenuItemUpdate); + jMenuItemUpdate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + update(lastClientRequest); + } + }); + + JMenuItem jMenuItemGetAll = new JMenuItem("Get all events from server"); + jMenuServer.add(jMenuItemGetAll); + ActionListener actionListenerGetAll = new ActionListener() { + public void actionPerformed(ActionEvent event) { + update(new ClientRequest(ClientRequest.REQUEST_ALL_EVENTS)); + } + }; + jMenuItemGetAll.addActionListener(actionListenerGetAll); + + JMenuItem jMenuItemAdvancedSearch = new JMenuItem( + "Advanced searching for events"); + jMenuServer.add(jMenuItemAdvancedSearch); + jMenuItemAdvancedSearch.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new AdvancedSearching(netCalendarClient); + } + }); + + jMenuServer.add(new JSeparator()); + + JMenuItem jMenuItemReloadDatabase = new JMenuItem("Reload database"); + jMenuServer.add(jMenuItemReloadDatabase); + jMenuItemReloadDatabase.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + ServerRequester.sendClientRequest(new ClientRequest( + ClientRequest.RELOAD_DATABASE)); + updateLast(); + } + }); + JMenuItem jMenuItemFlushDatabase = new JMenuItem("Flush database"); + jMenuServer.add(jMenuItemFlushDatabase); + jMenuItemFlushDatabase.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + ServerRequester.sendClientRequest(new ClientRequest( + ClientRequest.FLUSH_DATABASE)); + } + }); + + jMenuServer.add(new JSeparator()); + + JMenuItem jMenuItemShutdownServer = new JMenuItem("Shutdown server"); + jMenuServer.add(jMenuItemShutdownServer); + jMenuItemShutdownServer.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + ServerRequester.sendClientRequest(new ClientRequest( + ClientRequest.SHUTDOWN_SERVER)); + } + }); + + JMenu jMenuAbout = new JMenu("About"); + jMenuBar.add(jMenuAbout); + + JMenuItem jMenuItemAbout = new JMenuItem("About"); + jMenuAbout.add(jMenuItemAbout); + jMenuItemAbout.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new AboutWindow(netCalendarClient); + } + }); + JMenuItem jMenuItemLicense = new JMenuItem("License"); + jMenuAbout.add(jMenuItemLicense); + jMenuItemLicense.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + new LicenseWindow(netCalendarClient); + } + }); + + jPopupMenu = new JPopupMenu(); + ActionListener jPopupMenuActionListener = new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + String sActionCommand = actionEvent.getActionCommand(); + if (sActionCommand.equals(DELETE_EVENT)) { + foreachSelectedEvent(doCallbackDeleteEvent); + + } else if (sActionCommand.equals(CREATE_EVENT)) { + new CreateNewEvent(netCalendarClient); + + } else if (sActionCommand.equals(EDIT_EVENT)) { + foreachSelectedEvent(doCallbackEditEvent); + + } else if (sActionCommand.equals(COPY_EVENT)) { + foreachSelectedEvent(doCallbackCopyEvent); + + } else if (sActionCommand.equals(RENAME_CATEGORY)) { + foreachSelectedEvent(doCallbackRenameCategory); + + } else if (sActionCommand.equals(DELETE_CATEGORY)) { + foreachSelectedEvent(doCallbackDeleteCategory); + + } else if (sActionCommand.equals(ADVANCED_SEARCH)) { + new AdvancedSearching(netCalendarClient); + + } else if (sActionCommand.equals(SORT_BY_COL)) { + tableModel.sortByCol(iCurrentMouseSelectedCol); + + } else if (sActionCommand.equals(REVERSE_SORT_BY_COL)) { + tableModel.reverseSortByCol(iCurrentMouseSelectedCol); + } + } + }; + + JMenuItem jMenuItemPopupCreate = new JMenuItem(CREATE_EVENT); + jMenuItemPopupCreate.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupCreate); + JMenuItem jMenuItemPopupEdit = new JMenuItem(EDIT_EVENT); + jMenuItemPopupEdit.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupEdit); + JMenuItem jMenuItemPopupCopy = new JMenuItem(COPY_EVENT); + jMenuItemPopupCopy.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupCopy); + JMenuItem jMenuItemPopupDelete = new JMenuItem(DELETE_EVENT); + jMenuItemPopupDelete.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupDelete); + jPopupMenu.add(new JSeparator()); + + JMenuItem jMenuItemPopupRenameCategory = new JMenuItem(RENAME_CATEGORY); + jMenuItemPopupRenameCategory.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupRenameCategory); + JMenuItem jMenuItemPopupDeleteCategory = new JMenuItem(DELETE_CATEGORY); + jMenuItemPopupDeleteCategory.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupDeleteCategory); + jPopupMenu.add(new JSeparator()); + + JMenuItem jMenuItemPopupSort = new JMenuItem(SORT_BY_COL); + jMenuItemPopupSort.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupSort); + JMenuItem jMenuItemPopupReverseSort = new JMenuItem(REVERSE_SORT_BY_COL); + jMenuItemPopupReverseSort.addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupReverseSort); + jPopupMenu.add(new JSeparator()); + + JMenuItem jMenuItemPopupAdvancedSearch = new JMenuItem(ADVANCED_SEARCH); + jMenuItemPopupAdvancedSearch + .addActionListener(jPopupMenuActionListener); + jPopupMenu.add(jMenuItemPopupAdvancedSearch); + + jTable = new JTable(); + jTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + jTable.setColumnModel(new DefaultTableColumnModel() { + private static final long serialVersionUID = 1L; + // Dont allow column moving! + public void moveColumn(int iColumnIndex, int iNewColumnIndex) { } + }); + + tableModel = new CalendarTableModel(jTable); + jTable.setModel(tableModel); + jTable.addMouseListener(new MouseListener() { + public void mouseClicked(MouseEvent mouseEvent) { + iCurrentMouseSelectedRow = jTable.rowAtPoint(mouseEvent.getPoint()); + iCurrentMouseSelectedCol = jTable.columnAtPoint(mouseEvent.getPoint()); + + if (mouseEvent.getButton() != MouseEvent.BUTTON1) + jPopupMenu.show(jTable, mouseEvent.getX(), mouseEvent.getY()); + } + + public void mouseEntered(MouseEvent event) { } + public void mouseExited(MouseEvent event) {} + public void mousePressed(MouseEvent event) { } + public void mouseReleased(MouseEvent event) { + } + }); + + CalendarTableCellRenderer cellRenderer = new CalendarTableCellRenderer(tableModel); + + TableColumn column = jTable.getColumn(CalendarTableModel.NUM_HEADER); + column.setMaxWidth(Config.getStringValue("client_max_events").length() * 10); + column.setResizable(false); + column.setCellRenderer(cellRenderer); + + column = jTable.getColumn(CalendarTableModel.CATEGORY_HEADER); + column.setPreferredWidth(10); + column.setCellRenderer(cellRenderer); + + column = jTable.getColumn(CalendarTableModel.PLACE_HEADER); + column.setPreferredWidth(10); + column.setCellRenderer(cellRenderer); + + jTable.getColumn(CalendarTableModel.DATE_HEADER).setCellRenderer(cellRenderer); + jTable.getColumn(CalendarTableModel.DESCRIPTION_HEADER).setCellRenderer(cellRenderer); + + jTextFieldRegexp = new JTextField(); + jTextFieldRegexp.setText(ENTER_REGEXP_HERE); + jTextFieldRegexp.setEnabled(false); + + ActionListener actionListenerSearchRegexp = new ActionListener() { + public void actionPerformed(ActionEvent event) { + ClientRequest clientRequest = new ClientRequest(); + clientRequest.setRegexpAll(jTextFieldRegexp.getText()); + clientRequest.setMainRegexp(true); + jTextFieldRegexp.setText(""); + update(ServerRequester.sendClientRequest(clientRequest)); + lastClientRequest = clientRequest; + } + }; + MouseListener mouseListenerSearchRegexp = new MouseListener() { + public void mouseClicked(MouseEvent mouseEvent) {} + public void mousePressed(MouseEvent mouseEvent) {} + public void mouseReleased(MouseEvent mouseEvent) {} + public void mouseExited(MouseEvent mouseEvent) { + if (jTextFieldRegexp.getText().equals("")) { + jTextFieldRegexp.setText(ENTER_REGEXP_HERE); + jTextFieldRegexp.setEnabled(false); + } + } + public void mouseEntered(MouseEvent mouseEvent) { + if (!jTextFieldRegexp.isEnabled()) { + jTextFieldRegexp.setText(""); + jTextFieldRegexp.setEnabled(true); + } + } + }; + + jTextFieldRegexp.addActionListener(actionListenerSearchRegexp); + jTextFieldRegexp.addMouseListener(mouseListenerSearchRegexp); + + JButton jButtonSearch = new JButton("Search"); + jButtonSearch.addActionListener(actionListenerSearchRegexp); + jButtonSearch.addMouseListener(mouseListenerSearchRegexp); + + JButton jButtonGetAll = new JButton("Get all"); + jButtonGetAll.addActionListener(actionListenerGetAll); + + // Init split panes + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setResizeWeight(1); + jSplitPane.setDividerSize(0); + + JSplitPane jSplitPane2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane2.setResizeWeight(1); + jSplitPane2.setDividerSize(0); + + JSplitPane jSplitPane3 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + jSplitPane3.setResizeWeight(1); + jSplitPane3.setDividerSize(0); + + JSplitPane jSplitPane4 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + jSplitPane4.setDividerSize(0); + + // Init components + JScrollPane jScrollPaneTable = new JScrollPane(jTable); + + jTextFieldStatusMessages = new JTextField("Welcome to " + + Config.VERSION); + jTextFieldStatusMessages.setEditable(false); + + // Set split pane components + jSplitPane.setTopComponent(jScrollPaneTable); + jSplitPane.setBottomComponent(jSplitPane2); + + jSplitPane2.setTopComponent(jSplitPane3); + jSplitPane2.setBottomComponent(jTextFieldStatusMessages); + + JPanel jPanelButtons = new JPanel(); + jPanelButtons.add(jButtonSearch); + jPanelButtons.add(jButtonGetAll); + + jSplitPane3.setLeftComponent(jTextFieldRegexp); + jSplitPane3.setRightComponent(jPanelButtons); + + container.add(jSplitPane); + } + + /** + * This method sends a client request object to the server and used the server response object + * to update the JTable ith its new values using the table model. + * @param clientRequest Specifies the client request object to use for the updating. + */ + public void update(ClientRequest clientRequest) { + if (clientRequest == null) + return; + + update(ServerRequester.sendClientRequest(clientRequest)); + lastClientRequest = clientRequest; + } + + /** + * This method sends the last client request object being used to the server again. If + * If there is no last client request, nothing will be done. + */ + public void updateLast() { + if (lastClientRequest != null) + update(ServerRequester.sendClientRequest(lastClientRequest)); + } + + /** + * This method updates the GUI unsing a given server response object. + * @param serverResponse Specifies the server response to use for the updating. + */ + public void update(ServerResponse serverResponse) { + if (serverResponse == null) + return; + + tableModel.setEvents(serverResponse.getEvents()); + } + + /** + * This method tells the calendar server to delete a given calendar event. + * @param deleteEvent Specifies the calendar event to delete. + */ + public void deleteEvent(CalendarEvent deleteEvent) { + ClientRequest deleteRequest = new ClientRequest( + ClientRequest.DELETE_EVENT); + deleteRequest.setEvent(deleteEvent); + ServerRequester.sendClientRequest(deleteRequest); + updateLast(); + } + + /** + * This method tells the calendar server to delete a given calendar category. + * @param deleteEventsCategory Specifies the calendar event to delete its category! + */ + public void deleteCategory(CalendarEvent deleteEventsCategory) { + ClientRequest deleteRequest = new ClientRequest( + ClientRequest.DELETE_CATEGORY); + deleteRequest.setEvent(deleteEventsCategory); + ServerRequester.sendClientRequest(deleteRequest); + updateLast(); + } + + /** + * If the client has several main windows open, then it will display a + * session indicator so that the user knows which window belongs to which + * session window! + * @param iSession Specifies the session number of the current client window. + * @return Returns the session indicator of the current client session. + */ + private static String getSessionString(int iSession) { + return iSession > 1 ? "[" + iSession + "] " : ""; + } + + /** + * If the client has several main windows open, then it will display a + * session indicator so that the user knows which window belongs to which + * session window. + * @return Returns the session indicator of the current client session. + */ + public String getSessionString() { + return iCurrentSession > 1 ? "[" + iCurrentSession + "] " : ""; + } + + /** + * Runs a callback function on each selected event of the table. + * @param doCallback Specifies the callback object to be used. + */ + public void foreachSelectedEvent(DoCallback doCallback) { + ListSelectionModel listSelectionModel = jTable.getSelectionModel(); + + int iMinIndex = listSelectionModel.getMinSelectionIndex(); + int iMaxIndex = listSelectionModel.getMaxSelectionIndex(); + + Vector vecEvents = new Vector(); + + for (int i = iMinIndex; i <= iMaxIndex; ++i) + if (listSelectionModel.isSelectedIndex(i)) + vecEvents.add(tableModel.getEvent(i)); + + Enumeration enumEvents = vecEvents.elements(); + while (enumEvents.hasMoreElements()) + doCallback.callback(enumEvents.nextElement()); + } + + /** + * This method is for various status messages. All messages will show up in the + * status bar of the current client session window. + * @param sMessage Specifies the message to be displayed in the status bar. + */ + public void statusMessage(String sMessage) { + jTextFieldStatusMessages.setText(sMessage); + jTextFieldStatusMessages.updateUI(); + } + + /** + * This method disposes this JFrame window including all the JFrame windows which + * belong to this session. + */ + public void dispose() { + Enumeration enumFrames = vecFrames.elements(); + + while (enumFrames.hasMoreElements()) + ((JFrame) enumFrames.nextElement()).dispose(); + + super.dispose(); + } + + /** + * This method tells the main netcalendar client JFrame which sub JFrames are opened. + * So that all the sub JFrames will be disposed as well if the main JFrame gets disposed. + * A sub JFrame is for example a input form for advanced searching or the preferences dialog. + * @param jFrame Specifies the frame object to add. . + */ + public void addFrame(JFrame jFrame) { + vecFrames.add(jFrame); + } + + /** + * This method tells the main netcalendar client JFrame which sub JFrames are opened. + * So that all the sub JFrames will be disposed as well if the main JFrame gets disposed. + * A sub JFrame is for example a input form for advanced searching or the preferences dialog. + * @param jFrame Specifies the frame object to remove. + */ + public void removeFrame(JFrame jFrame) { + vecFrames.remove(jFrame); + } +} diff --git a/sources/client/ServerRequester.java b/sources/client/ServerRequester.java new file mode 100644 index 0000000..9cd7485 --- /dev/null +++ b/sources/client/ServerRequester.java @@ -0,0 +1,82 @@ +/** + * + */ +package client; + + +import java.io.*; +import java.net.*; +import java.security.*; +import javax.net.*; +import javax.net.ssl.*; + +import shared.*; +import shared.remotecall.*; + +/** + * This class only has static members. Its used for creating a client socket to connect and + * communicate with the calendar server. + * @author buetow + */ +public class ServerRequester { + /** + * This method creates a new client socket. + * @return Returns a client socket object. + * @throws IOException + */ + private static Socket makeClientSocket() throws IOException { + if (!Config.getBooleanValue("use_ssl")) { + Main.statusMessage("Making non-SSL Socket..."); + return new Socket(Config.getServerAddress(), Config.getIntValue("server_port")); + } + + Main.statusMessage("Making SSL Socket..."); + //Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); + SocketFactory socketFactory = SSLSocketFactory.getDefault(); + return socketFactory.createSocket(Config.getServerAddress(), Config.getIntValue("server_port")); + } + + /** + * Sends a client request to the netcalendar server end receives a server response object. + * @param clientRequest Specifies the client request to send to the calendar server. + * @return Returns the server response. It returns null if no response is available. + */ + public final static ServerResponse sendClientRequest(ClientRequest clientRequest) { + Main.statusMessage("Sending client request to server..."); + + ServerResponse serverResponse = null; + + try { + Socket socket = makeClientSocket(); + socket.setKeepAlive(true); + + // Send the client request to the server + OutputStream outputStream = socket.getOutputStream(); + ObjectOutput objectOutput = new ObjectOutputStream(outputStream); + + objectOutput.writeObject(clientRequest); + objectOutput.flush(); + + // We only want to receive data if the request new events, not if we only send + // changed events! + if (clientRequest.requestsNewEvents()) { + // Recieve the server's response + InputStream inputStream = socket.getInputStream(); + ObjectInput objectInput = new ObjectInputStream(inputStream); + serverResponse = (ServerResponse) objectInput.readObject(); + } + + objectOutput.close(); + socket.close(); + + } catch (Exception e) { + Main.infoMessage("Client error during serialization: " + e.getMessage()); + Main.statusMessage("Error: Client request did not succeed! Server down?"); + return serverResponse; + } + + Main.statusMessage("Last client request succeeded"); + // Returns null if no response is available! + return serverResponse; + } +} diff --git a/sources/client/SplashScreen.java b/sources/client/SplashScreen.java new file mode 100644 index 0000000..6ad8416 --- /dev/null +++ b/sources/client/SplashScreen.java @@ -0,0 +1,42 @@ +package client; + +import java.awt.*; +import javax.swing.*; +import shared.*; + +public class SplashScreen extends JWindow implements Runnable { + private static final long serialVersionUID = 1L; + + /** + * A simple little method to show a title screen in the center + * of the screen for the amount of time given in the constructor + */ + public void run() { + JPanel jPanel = (JPanel)getContentPane(); + jPanel.setBackground(Color.BLACK); + jPanel.setForeground(Color.WHITE); + + // Set the window's bounds, centering the window + int iWidth = 411; + int iHeight = 261; + Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); + + int x = (dimension.width-iWidth)/2; + int y = (dimension.height-iHeight)/2; + setBounds(x,y,iWidth,iHeight); + + JLabel jLabel = new JLabel(new ImageIcon("images/netcal.png")); + jPanel.add(jLabel, BorderLayout.CENTER); + jPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3)); + setVisible(true); + + try { + Thread.sleep(3000); + + } catch (Exception e) { + Main.infoMessage(e.getMessage()); + } + + dispose(); + } +}
\ No newline at end of file diff --git a/sources/client/SubWindow.java b/sources/client/SubWindow.java new file mode 100644 index 0000000..e043679 --- /dev/null +++ b/sources/client/SubWindow.java @@ -0,0 +1,101 @@ +package client; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +import javax.swing.*; + + +/** + * This is the base class for all subwindows of a main session window of + * the calendar client. + * @author buetow + * + */ +public abstract class SubWindow extends JFrame { + protected final static long serialVersionUID = 1L; + protected NetCalendarClient netCalendarClient; + private SubWindow subWindow; + + /** + * Creates the window and shows it. + * @param sTitleText Specifies the title text of this JFrame. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public SubWindow(String sTitleText, NetCalendarClient netCalendarClient) { + super(netCalendarClient.getSessionString() + sTitleText); + netCalendarClient.addFrame(this); + this.netCalendarClient = netCalendarClient; + this.subWindow = this; + this.addWindowListener(new MyWindowListener()); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setLocationRelativeTo(netCalendarClient); + } + + /** + * Creates the window and shows it. + * @param sTitleText Specifies the title text of this JFrame. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public void init(String sTitleText, NetCalendarClient netCalendarClient) { + initComponents(); + pack(); + setVisible(true); + } + + /** + * The implemented method should initialize all the GUI components. + */ + protected abstract void initComponents(); + + /** + * This private class is only needed for removing the current JFrame of the outer class + * from the NetCalendarClient object's frame Vector. + * @author buetow + */ + private class MyWindowListener implements WindowListener { + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent) + */ + public void windowClosed(WindowEvent e) { + netCalendarClient.removeFrame(subWindow); + } + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowActivated(java.awt.event.WindowEvent) + */ + public void windowActivated(WindowEvent e) { } + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + */ + public void windowClosing(WindowEvent e) {} + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowDeactivated(java.awt.event.WindowEvent) + */ + public void windowDeactivated(WindowEvent e) {} + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowDeiconified(java.awt.event.WindowEvent) + */ + public void windowDeiconified(WindowEvent e) {} + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowIconified(java.awt.event.WindowEvent) + */ + public void windowIconified(WindowEvent e) { } + + /* + * (non-Javadoc) + * @see java.awt.event.WindowListener#windowOpened(java.awt.event.WindowEvent) + */ + public void windowOpened(WindowEvent e) {} + } +} diff --git a/sources/client/helper/DateSpinner.java b/sources/client/helper/DateSpinner.java new file mode 100644 index 0000000..e374107 --- /dev/null +++ b/sources/client/helper/DateSpinner.java @@ -0,0 +1,57 @@ +package client.helper; + + +import java.awt.FlowLayout; +import java.util.Calendar; +import java.util.Date; + +import javax.swing.*; + +/** + * This helper class helps to create a date spinner to edit Date objects. + * @author buetow + */ +public class DateSpinner extends JComponent { + private final static long serialVersionUID = 1L; + private Date date; + private SpinnerDateModel spinnerDateModel; + + /** + * Creates a date spinner to set/edit a given date. This constructor uses the + * current date! + */ + public DateSpinner() { + this.date = new Date(); + initComponents(); + } + + /** + * Creates a date spinner to set/edit a given date. + * @param date The date to be used for the date spinner! + */ + public DateSpinner(Date date) { + this.date = date; + initComponents(); + } + + /** + * Initializes all the date spinner GUI components. + */ + private void initComponents() { + setLayout(new FlowLayout(FlowLayout.LEFT, 4, 4)); + + spinnerDateModel = new SpinnerDateModel(date, null, null, Calendar.MONTH); + JSpinner jSpinner = new JSpinner(spinnerDateModel); + new JSpinner.DateEditor(jSpinner, "MM/yy"); + + add(jSpinner); + } + + /** + * Returns the date which is represented by this spinner. + * @return Returns the date which is represented by this spinner. + */ + public Date getDate() { + return spinnerDateModel.getDate(); + } +} diff --git a/sources/client/helper/GUIHelper.java b/sources/client/helper/GUIHelper.java new file mode 100644 index 0000000..5da3bbf --- /dev/null +++ b/sources/client/helper/GUIHelper.java @@ -0,0 +1,189 @@ +package client.helper; + +import javax.swing.*; +import javax.swing.SpringLayout; +import java.awt.*; + +import shared.*; + +/** + * This helper class helps to create well arranged GUI components. + * Its creating form- or grid-style layouts using the SpringLayout class. + * @author buetow + */ +public class GUIHelper { + /** + * Aligns the first <code>iRows</code> * <code>iCols</code> + * components of the parent in a grid. Each component is as big as the maximum + * preferred width and height of the components. + * The parent is made just big enough to fit them all. + * @param containerParent Specifies the container to be used + * @param iRows Specifies the number of rows to use. + * @param iCols Specifies the number of columns to use. + * @param iInitialX Specifies the x location to start the grid at. + * @param iInitialY Specifies the y location to start the grid at. + * @param iXPad Specifies the x padding between the cells. + * @param iYPad Specifies the y padding between the cells + */ + public static void makeGrid(Container containerParent, + int iRows, int iCols, + int iInitialX, int iInitialY, + int iXPad, int iYPad) { + SpringLayout helper; + try { + helper = (SpringLayout)containerParent.getLayout(); + } catch (ClassCastException exc) { + Main.infoMessage("Error: The first argument to makeGrid must use SpringLayout."); + return; + } + + Spring iXPadSpring = Spring.constant(iXPad); + Spring iYPadSpring = Spring.constant(iYPad); + Spring iInitialXSpring = Spring.constant(iInitialX); + Spring iInitialYSpring = Spring.constant(iInitialY); + int max = iRows * iCols; + + // Calculate Springs that are the max of the width/height so that all + // cells have the same size. + Spring maxWidthSpring = helper.getConstraints(containerParent.getComponent(0)). + getWidth(); + Spring maxHeightSpring = helper.getConstraints(containerParent.getComponent(0)). + getWidth(); + for (int i = 1; i < max; i++) { + SpringLayout.Constraints cons = helper.getConstraints( + containerParent.getComponent(i)); + + maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); + maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); + } + + // Apply the new width/height Spring. This forces all the + // components to have the same size. + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = helper.getConstraints( + containerParent.getComponent(i)); + + cons.setWidth(maxWidthSpring); + cons.setHeight(maxHeightSpring); + } + + // Then adjust the x/y constraints of all the cells so that they + // are aligned in a grid. + SpringLayout.Constraints lastCons = null; + SpringLayout.Constraints lastRowCons = null; + for (int i = 0; i < max; i++) { + SpringLayout.Constraints cons = helper.getConstraints( + containerParent.getComponent(i)); + if (i % iCols == 0) { //start of new iRow + lastRowCons = lastCons; + cons.setX(iInitialXSpring); + } else { //x position depends on previous component + cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), + iXPadSpring)); + } + + if (i / iCols == 0) { //first iRow + cons.setY(iInitialYSpring); + } else { //y position depends on previous iRow + cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), + iYPadSpring)); + } + lastCons = cons; + } + + // Set the containerParent's size. + SpringLayout.Constraints pCons = helper.getConstraints(containerParent); + pCons.setConstraint(SpringLayout.SOUTH, + Spring.sum(Spring.constant(iYPad), lastCons.getConstraint(SpringLayout.SOUTH))); + pCons.setConstraint(SpringLayout.EAST, + Spring.sum(Spring.constant(iXPad), lastCons.getConstraint(SpringLayout.EAST))); + } + + /** + * This is a helper method for makeGrid. It returns the constraints for a specific cell. + * @param iRow Specifies the row to get the constraints for. + * @param iCol Specifies the column to get the constraints for. + * @param containerParent Specifies the parent container. + * @param iCols Specifies the number of columns being used. + * @return Returns the constraints object of the current SpringLayout. + */ + private static SpringLayout.Constraints getConstraintsForCell(int iRow, int iCol, + Container containerParent, int iCols) { + + SpringLayout helper = (SpringLayout) containerParent.getLayout(); + Component component = containerParent.getComponent(iRow * iCols + iCol); + return helper.getConstraints(component); + } + + /** + * Aligns the first <code>iRows</code> * <code>iCols</code> + * components of <code>containerParent</code> in + * a grid. Each component in a iColumn is as wide as the maximum + * preferred width of the components in that iColumn; + * height is similarly determined for each iRow. + * The containerParent is made just big enough to fit them all. + * @param iRows Specifies number of rows. + * @param iCols Specifies the number of columns. + * @param iInitialX Specifies the x location to start the grid at. + * @param iInitialY Specifies the y location to start the grid at. + * @param iXPad Specifies the x padding between the cells. + * @param iYPad Specifies the y padding between the cells. + */ + public static void makeCompactGrid(Container containerParent, + int iRows, int iCols, + int iInitialX, int iInitialY, + int iXPad, int iYPad) { + SpringLayout helper; + + try { + helper = (SpringLayout)containerParent.getLayout(); + } catch (ClassCastException exc) { + Main.infoMessage("Error: The first argument to makeCompactGrid must use SpringLayout."); + return; + } + + // Align all cells in each iColumn and make them the same width. + Spring x = Spring.constant(iInitialX); + for (int c = 0; c < iCols; c++) { + Spring width = Spring.constant(0); + for (int r = 0; r < iRows; r++) { + width = Spring.max(width, + getConstraintsForCell(r, c, containerParent, iCols).getWidth()); + } + + for (int r = 0; r < iRows; r++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, containerParent, iCols); + constraints.setX(x); + constraints.setWidth(width); + } + x = Spring.sum(x, Spring.sum(width, Spring.constant(iXPad))); + } + + // Align all cells in each iRow and make them the same height. + Spring y = Spring.constant(iInitialY); + for (int r = 0; r < iRows; r++) { + Spring height = Spring.constant(0); + + for (int c = 0; c < iCols; c++) { + height = Spring.max(height, + getConstraintsForCell(r, c, containerParent, iCols).getHeight()); + } + + for (int c = 0; c < iCols; c++) { + SpringLayout.Constraints constraints = + getConstraintsForCell(r, c, containerParent, iCols); + + constraints.setY(y); + constraints.setHeight(height); + } + + y = Spring.sum(y, Spring.sum(height, Spring.constant(iYPad))); + } + + // Set the containerParent's size. + SpringLayout.Constraints pCons = helper.getConstraints(containerParent); + pCons.setConstraint(SpringLayout.SOUTH, y); + pCons.setConstraint(SpringLayout.EAST, x); + } +} diff --git a/sources/client/inputforms/AdvancedSearching.java b/sources/client/inputforms/AdvancedSearching.java new file mode 100644 index 0000000..1b39320 --- /dev/null +++ b/sources/client/inputforms/AdvancedSearching.java @@ -0,0 +1,141 @@ +/* + * A 1.4 application that uses SpringLayout to create a forms-type layout. + * Other files required: SpringUtilities.java. + */ + +package client.inputforms; + +import java.awt.event.*; +import java.util.*; +import javax.swing.*; + +import client.NetCalendarClient; +import client.helper.DateSpinner; +import client.helper.GUIHelper; + + +import shared.remotecall.*; + +/** + * This class contains all the GUI components of the advanced searching dialog. + * Its used for using the andvanced searching options of the client such as using + * Java regular expressions on specific elements of the calendar database instead and + * date ranges. + * @author buetow + * + */ +public class AdvancedSearching extends InputForm { + private final static long serialVersionUID = 1L; + + // Static elements which are the same on all AdvancedSearching objects! + private final static String BUTTON_GET_ALL = "Get all"; + private final static String[] labels = {"Date string: ", "Description: ", "Category: ", "Place: ", + "Use date ranging: ", "Date range from: ", "Date range to: " + }; + private final static int iNumPairs = labels.length; + private final static int iTextFields = labels.length - 3; + private final static int iCheckBoxes = labels.length - 2; + + /** + * Create the input form window and show it. + * @param netCalendarClient Specifies the current calendar client session window. + */ + public AdvancedSearching(NetCalendarClient netCalendarClient) { + super("Advanced searching", netCalendarClient); + initComponents(); + pack(); + setVisible(true); + } + + /** + * Initializes all the GUI components. + */ + protected void initComponents() { + super.initComponents(); + //Create and populate the panel. + JPanel jPanel = new JPanel(new SpringLayout()); + + ActionListener actionListenerFields = new ActionListener() { + public void actionPerformed(ActionEvent event) { + submit(); + } + }; + + vecFields = new Vector(); + for (int i = 0; i < iNumPairs; ++i) { + JLabel jLable = new JLabel(labels[i], JLabel.TRAILING); + jPanel.add(jLable); + JComponent jComponent = null; + + if (i < iTextFields) { + JTextField jTextField = new JTextField(InputForm.TEXTFIELD_LENGTH); + jTextField.addActionListener(actionListenerFields); + jComponent = jTextField; + + } else if (i < iCheckBoxes) { + jComponent = new JCheckBox(); + + } else { + jComponent = new DateSpinner(); + } + + jLable.setLabelFor(jComponent); + jPanel.add(jComponent); + + vecFields.add(jComponent); + } + + //Lay out the panel. + GUIHelper.makeCompactGrid(jPanel, + iNumPairs, 2, // iRows, iCols + 6, 6, // iInitX, iInitY + 6, 6); // iXPad, iYPad + + JButton jButtonGetAll = new JButton(BUTTON_GET_ALL); + + ActionListener actionListenerButtons = new ActionListener() { + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(BUTTON_CLEAR)) + for (int i = 0; i < iTextFields; ++i) + ((JTextField) vecFields.get(i)).setText(""); + + else if (event.getActionCommand().equals(BUTTON_GET_ALL)) + netCalendarClient.update(new ClientRequest(ClientRequest.REQUEST_ALL_EVENTS)); + + } + }; + + jButtonClear.addActionListener(actionListenerButtons); + jButtonGetAll.addActionListener(actionListenerButtons); + jPanelButtons.add(jButtonGetAll); + + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setTopComponent(jPanel); + jSplitPane.setBottomComponent(jPanelButtons); + jSplitPane.setDividerSize(0); + + setContentPane(jSplitPane); + } + + /** + * This method is invoked if the enter key is pressed or if the submit button + * has been pressed. It starts a client request relating to the user's input of + * the text fields. + */ + protected void submit() { + ClientRequest clientRequest = new ClientRequest(); + clientRequest.setRegexpDate(((JTextField) vecFields.get(0)).getText()); + clientRequest.setRegexpDescription(((JTextField) vecFields.get(1)).getText()); + clientRequest.setRegexpCategory(((JTextField) vecFields.get(2)).getText()); + clientRequest.setRegexpPlace(((JTextField) vecFields.get(3)).getText()); + + JCheckBox jCheckBox = (JCheckBox) vecFields.get(4); + if (jCheckBox.isSelected()) { + Date dateRangeFrom = ((DateSpinner) vecFields.get(5)).getDate(); + Date dateRangeTo = ((DateSpinner) vecFields.get(6)).getDate(); + clientRequest.setDateRange(dateRangeFrom, dateRangeTo); + } + + netCalendarClient.update(clientRequest); + } +} diff --git a/sources/client/inputforms/CreateNewEvent.java b/sources/client/inputforms/CreateNewEvent.java new file mode 100644 index 0000000..430f982 --- /dev/null +++ b/sources/client/inputforms/CreateNewEvent.java @@ -0,0 +1,122 @@ +package client.inputforms; + +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import client.NetCalendarClient; +import client.ServerRequester; +import client.helper.DateSpinner; +import client.helper.GUIHelper; + + +import shared.*; +import shared.remotecall.*; + +/** + * This class contains all the GUI components of the create new event dialog. + * Its used for adding new calendar events to the database. + * @author buetow + * + */ +public class CreateNewEvent extends InputForm { + private final static long serialVersionUID = 1L; + + // Static elements which are the same on all AdvancedSearching objects! + private final static String[] labels = + { "Description: ", "Category: ", "Place: ", "Yearly: ", "Date: "}; + private final static int iNumPairs = labels.length; + private final static int iTextFields = iNumPairs - 2; + private final static int iCheckBoxes = iNumPairs - 1; + + /** + * Create the input form window and show it. + * @param netCalendarClient Specifies the current calendar client session window. * + */ + public CreateNewEvent(NetCalendarClient netCalendarClient) { + super("Create new event", netCalendarClient); + initComponents(); + pack(); + setVisible(true); + } + + /** + * Initializes all the GUI components. + */ + protected void initComponents() { + super.initComponents(); + JPanel jPanel = new JPanel(new SpringLayout()); + + ActionListener actionListenerTextFields = new ActionListener() { + public void actionPerformed(ActionEvent event) { + submit(); + } + }; + + vecFields = new Vector(); + for (int i = 0; i < iNumPairs; ++i) { + JLabel jLable = new JLabel(labels[i], JLabel.TRAILING); + jPanel.add(jLable); + JComponent jComponent = null; + if ( i < iTextFields) { + JTextField textField = new JTextField(InputForm.TEXTFIELD_LENGTH); + textField.addActionListener(actionListenerTextFields); + jComponent = textField; + + } else if (i < iCheckBoxes) { + jComponent = new JCheckBox(); + + } else { + jComponent = new DateSpinner(); + } + + jLable.setLabelFor(jComponent); + jPanel.add(jComponent); + vecFields.add(jComponent); + } + + //Lay out the panel. + GUIHelper.makeCompactGrid(jPanel, + iNumPairs, 2, // iRows, iCols + 6, 6, // iInitX, iInitY + 6, 6); // iXPad, iYPad + + ActionListener actionListenerButtons = new ActionListener() { + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(BUTTON_CLEAR)) + for (int i = 0; i < iNumPairs -2; ++i) + ((JTextField) vecFields.get(i)).setText(""); + } + }; + + jButtonClear.addActionListener(actionListenerButtons); + + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setTopComponent(jPanel); + jSplitPane.setBottomComponent(jPanelButtons); + jSplitPane.setDividerSize(0); + + setContentPane(jSplitPane); + } + + /** + * This method is invoked if the enter key is pressed or if the submit button + * has been pressed. It starts a client request relating to the user's input of + * the text fields. + */ + protected void submit() { + String sCategoryName = ((JTextField) vecFields.get(1)).getText(); + CalendarEvent calendarEvent = new CalendarEvent(sCategoryName); + calendarEvent.setDescription(((JTextField) vecFields.get(0)).getText()); + calendarEvent.setPlace(((JTextField) vecFields.get(2)).getText()); + calendarEvent.setYearly(((JCheckBox) vecFields.get(3)).isSelected()); + calendarEvent.setDate(((DateSpinner) vecFields.get(4)).getDate()); + + ClientRequest clientRequest = new ClientRequest(ClientRequest.ADD_EVENT); + clientRequest.setEvent(calendarEvent); + + ServerRequester.sendClientRequest(clientRequest); + netCalendarClient.updateLast(); + } +} diff --git a/sources/client/inputforms/EditExistingEvent.java b/sources/client/inputforms/EditExistingEvent.java new file mode 100644 index 0000000..6c65aeb --- /dev/null +++ b/sources/client/inputforms/EditExistingEvent.java @@ -0,0 +1,156 @@ +package client.inputforms; + +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import client.NetCalendarClient; +import client.ServerRequester; +import client.helper.DateSpinner; +import client.helper.GUIHelper; + + +import shared.*; +import shared.remotecall.*; + +/** + * This class contains all the GUI components of the edit event dialog. + * Its used for editing existing events of the calendar database. + * @author buetow + * + */ +public class EditExistingEvent extends InputForm { + private final static long serialVersionUID = 1L; + + // Static elements which are the same on all AdvancedSearching objects! + private final static String BUTTON_DELETE = "Delete"; + private final static String[] labels = + { "Event ID: ", "Description: ", "Category: ", "Place: ", "Yearly: ", "Date: "}; + private final static int iNumPairs = labels.length; + private final static int iTextFields = iNumPairs - 2; + private final static int iCheckBoxes = iNumPairs - 1; + + private CalendarEvent originalCalendarEvent; + private Date date; + + /** + * Create the input form window and show it. + * @param netCalendarClient Specifies the current calendar client session window. + * @param originalCalendarEvent Specifies the calendar event to modify. + */ + public EditExistingEvent(NetCalendarClient netCalendarClient, CalendarEvent originalCalendarEvent) { + super("Edit event", netCalendarClient); + this.originalCalendarEvent = originalCalendarEvent; + this.date = originalCalendarEvent.getDate(); + initComponents(); + setFieldValues(); + pack(); + setVisible(true); + } + + /** + * Initializes all the GUI components. + */ + protected void initComponents() { + super.initComponents(); + + JPanel jPanel = new JPanel(new SpringLayout()); + + ActionListener actionListenerTextFields = new ActionListener() { + public void actionPerformed(ActionEvent event) { + submit(); + } + }; + + vecFields = new Vector(); + for (int i = 0; i < iNumPairs; ++i) { + JLabel jLable = new JLabel(labels[i], JLabel.TRAILING); + jPanel.add(jLable); + JComponent jComponent = null; + if ( i < iTextFields) { + JTextField textField = new JTextField(InputForm.TEXTFIELD_LENGTH); + textField.addActionListener(actionListenerTextFields); + jComponent = textField; + + } else if (i < iCheckBoxes) { + jComponent = new JCheckBox(); + + } else { + jComponent = new DateSpinner(date); + } + + jLable.setLabelFor(jComponent); + jPanel.add(jComponent); + vecFields.add(jComponent); + } + + //Lay out the panel. + GUIHelper.makeCompactGrid(jPanel, + iNumPairs, 2, // iRows, iCols + 6, 6, // iInitX, iInitY + 6, 6); // iXPad, iYPad + + JButton jButtonDelete = new JButton(BUTTON_DELETE); + + ActionListener actionListenerButtons = new ActionListener() { + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(BUTTON_CLEAR)) { + for (int i = 1; i < iNumPairs -2; ++i) + ((JTextField) vecFields.get(i)).setText(""); + + } else if (event.getActionCommand().equals(BUTTON_DELETE)) { + netCalendarClient.deleteEvent(originalCalendarEvent); + dispose(); + } + } + }; + + jButtonDelete.addActionListener(actionListenerButtons); + jButtonClear.addActionListener(actionListenerButtons); + jPanelButtons.add(jButtonDelete); + + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setTopComponent(jPanel); + jSplitPane.setBottomComponent(jPanelButtons); + jSplitPane.setDividerSize(0); + + setContentPane(jSplitPane); + } + + /** + * This method sets the fields of the edit frame according to the originalCalendarEvent object. + * The date is not set by this method. Its done by the initComponents method. + */ + private void setFieldValues() { + JTextField jTextFieldEventID = (JTextField) vecFields.get(0); + jTextFieldEventID.setText(""+originalCalendarEvent.getEventID()); + jTextFieldEventID.setEditable(false); + + ((JTextField) vecFields.get(1)).setText(originalCalendarEvent.getDescription()); + ((JTextField) vecFields.get(2)).setText(originalCalendarEvent.getCategoryName()); + ((JTextField) vecFields.get(3)).setText(originalCalendarEvent.getPlace()); + ((JCheckBox) vecFields.get(4)).setSelected(originalCalendarEvent.isYearly()); + } + + /** + * This method is invoked if the enter key is pressed or if the submit button + * has been pressed. It starts a client request relating to the user's input of + * the text fields. + */ + protected void submit() { + String sCategoryName = ((JTextField) vecFields.get(2)).getText(); + CalendarEvent calendarEvent = new CalendarEvent(sCategoryName); + calendarEvent.setDescription(((JTextField) vecFields.get(1)).getText()); + calendarEvent.setPlace(((JTextField) vecFields.get(3)).getText()); + calendarEvent.setYearly(((JCheckBox) vecFields.get(4)).isSelected()); + calendarEvent.setDate(((DateSpinner) vecFields.get(5)).getDate()); + calendarEvent.setEventID(originalCalendarEvent.getEventID()); + + ClientRequest clientRequest = new ClientRequest(ClientRequest.MODIFY_EVENT); + clientRequest.setEvent(calendarEvent); + + ServerRequester.sendClientRequest(clientRequest); + netCalendarClient.updateLast(); + } +} diff --git a/sources/client/inputforms/InputForm.java b/sources/client/inputforms/InputForm.java new file mode 100644 index 0000000..41004fa --- /dev/null +++ b/sources/client/inputforms/InputForm.java @@ -0,0 +1,93 @@ +package client.inputforms; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.*; +import javax.swing.*; + +import client.*; + +/** + * This abstract class is the base class of all other classes of the same package. + * It contains some common members using by all other (specialized) input form classes. + * @author buetow + * + */ +public abstract class InputForm extends SubWindow { + protected final static long serialVersionUID = 1L; + protected Vector vecFields; + protected JPanel jPanelButtons; + protected JButton jButtonClear; + protected JButton jButtonApply; + protected JButton jButtonCancel; + protected JButton jButtonOK; + private boolean bApplyHasBeenPressed = false; + + protected final static String BUTTON_CANCEL = "Cancel"; + protected final static String BUTTON_CLEAR = "Clear"; + protected final static String BUTTON_APPLY = "Apply"; + protected final static String BUTTON_OK = "OK"; + + protected final static int TEXTFIELD_LENGTH = 20; + + /** + * Creates the input form window and show it. + * @param sTitleText Specifies the title text of this JFrame. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public InputForm(String sTitleText, NetCalendarClient netCalendarClient) { + super(sTitleText, netCalendarClient); + } + + /** + * Initializes the input form + * @param sTitleText Specifies the title text of this JFrame. + * @param netCalendarClient Specifies the calendar client session object to use. + */ + public void init(String sTitleText, NetCalendarClient netCalendarClient) { + super.init(sTitleText, netCalendarClient); + } + + /** + * Initializes all the GUI components of the implementating class. + */ + protected void initComponents() { + jButtonClear = new JButton(BUTTON_CLEAR); + jButtonApply = new JButton(BUTTON_APPLY); + jButtonCancel = new JButton(BUTTON_CANCEL); + jButtonOK = new JButton(BUTTON_OK); + + ActionListener actionListenerButtons = new ActionListener() { + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(BUTTON_CANCEL)) { + dispose(); + + } else if (event.getActionCommand().equals(BUTTON_APPLY)) { + bApplyHasBeenPressed = true; + submit(); + + } else if (event.getActionCommand().equals(BUTTON_OK)) { + if (!bApplyHasBeenPressed) + submit(); + dispose(); + } + } + }; + + jButtonCancel.addActionListener(actionListenerButtons); + jButtonClear.addActionListener(actionListenerButtons); + jButtonApply.addActionListener(actionListenerButtons); + jButtonOK.addActionListener(actionListenerButtons); + + jPanelButtons = new JPanel(); + jPanelButtons.add(jButtonOK); + jPanelButtons.add(jButtonCancel); + jPanelButtons.add(jButtonApply); + jPanelButtons.add(jButtonClear); + } + + /** + * Submits the input form of the implementating class. + */ + protected abstract void submit(); +} diff --git a/sources/client/inputforms/Preferences.java b/sources/client/inputforms/Preferences.java new file mode 100644 index 0000000..cefc192 --- /dev/null +++ b/sources/client/inputforms/Preferences.java @@ -0,0 +1,99 @@ +package client.inputforms; + +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import client.NetCalendarClient; +import client.helper.GUIHelper; + + +import shared.*; +/** + * This class contains all the GUI components of the preferences/options/config dialog. + * Its used for editing the current config values of the config.txt file. + * @author buetow + * + */ +public class Preferences extends InputForm { + private final static long serialVersionUID = 1L; + + private String[] labels = null; + private int iNumPairs = -1; + + /** + * Create the input form window and show it. + * @param netCalendarClient Specifies the current calendar client session window. + */ + public Preferences(NetCalendarClient netCalendarClient) { + super("Preferences", netCalendarClient); + initComponents(); + setFieldValues(); + pack(); + setVisible(true); + } + + /** + * Initializes all the GUI components. + */ + protected void initComponents() { + super.initComponents(); + setFieldValues(); + JPanel jPanel = new JPanel(new SpringLayout()); + + labels = Config.getSortedKeyArray(); + iNumPairs = labels.length; + + ActionListener actionListenerTextFields = new ActionListener() { + public void actionPerformed(ActionEvent event) { + submit(); + } + }; + + vecFields = new Vector(); + for (int i = 0; i < iNumPairs; ++i) { + JLabel jLable = new JLabel(labels[i], JLabel.TRAILING); + jPanel.add(jLable); + JTextField textField = new JTextField(InputForm.TEXTFIELD_LENGTH); + textField.addActionListener(actionListenerTextFields); + jLable.setLabelFor(textField); + jPanel.add(textField); + vecFields.add(textField); + } + + //Lay out the panel. + GUIHelper.makeCompactGrid(jPanel, + iNumPairs, 2, // iRows, iCols + 6, 6, // iInitX, iInitY + 6, 6); // iXPad, iYPad + + jPanelButtons.remove(jButtonClear); + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setTopComponent(jPanel); + jSplitPane.setBottomComponent(jPanelButtons); + jSplitPane.setDividerSize(0); + + setContentPane(jSplitPane); + } + + /** + * This method sets the fields of the edit frame according to the current configuration options. + */ + private void setFieldValues() { + for (int i = 0; i < iNumPairs; ++i) + ((JTextField) vecFields.get(i)).setText(Config.getStringValue(labels[i])); + } + + /** + * This method is invoked if the enter key is pressed or if the submit button + * has been pressed. It starts a client request relating to the user's input of + * the text fields. It will write all changes to the config.txt file. + */ + protected void submit() { + for (int i = 0; i < iNumPairs; ++i) + Config.setValue(labels[i], ((JTextField) vecFields.get(i)).getText()); + + Config.writeConfigToFile(); + } +} diff --git a/sources/client/inputforms/RenameCategory.java b/sources/client/inputforms/RenameCategory.java new file mode 100644 index 0000000..90c6750 --- /dev/null +++ b/sources/client/inputforms/RenameCategory.java @@ -0,0 +1,123 @@ +package client.inputforms; + +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import client.NetCalendarClient; +import client.ServerRequester; +import client.helper.DateSpinner; +import client.helper.GUIHelper; + + +import shared.*; +import shared.remotecall.*; + +/** + * This class contains all the GUI components of the edit event dialog. + * Its used for editing existing events of the calendar database. + * @author buetow + * + */ +public class RenameCategory extends InputForm { + private final static long serialVersionUID = 1L; + + // Static elements which are the same on all AdvancedSearching objects! + private final static String[] labels = { "Category name: " }; + private final static int iNumPairs = labels.length; + + private CalendarEvent calendarEvent; + + /** + * Create the input form window and show it. + * @param netCalendarClient Specifies the current calendar client session window. + * @param originalCalendarEvent Specifies the calendar event to modify. + */ + public RenameCategory(NetCalendarClient netCalendarClient, CalendarEvent calendarEvent) { + super("Rename whole category", netCalendarClient); + this.calendarEvent = calendarEvent; + initComponents(); + setFieldValues(); + pack(); + setVisible(true); + } + + /** + * Initializes all the GUI components. + */ + protected void initComponents() { + super.initComponents(); + + JPanel jPanel = new JPanel(new SpringLayout()); + + ActionListener actionListenerTextFields = new ActionListener() { + public void actionPerformed(ActionEvent event) { + submit(); + } + }; + + vecFields = new Vector(); + + for (int i = 0; i < iNumPairs; ++i) { + JLabel jLable = new JLabel(labels[i], JLabel.TRAILING); + jPanel.add(jLable); + JComponent jComponent = null; + JTextField textField = new JTextField(InputForm.TEXTFIELD_LENGTH); + textField.addActionListener(actionListenerTextFields); + jComponent = textField; + jLable.setLabelFor(jComponent); + jPanel.add(jComponent); + vecFields.add(jComponent); + } + + //Lay out the panel. + GUIHelper.makeCompactGrid(jPanel, + iNumPairs, 2, // iRows, iCols + 6, 6, // iInitX, iInitY + 6, 6); // iXPad, iYPad + + ActionListener actionListenerButtons = new ActionListener() { + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals(BUTTON_CLEAR)) { + for (int i = 1; i < iNumPairs; ++i) + ((JTextField) vecFields.get(i)).setText(""); + } + } + }; + + jButtonClear.addActionListener(actionListenerButtons); + jPanelButtons.remove(jButtonClear); + + JSplitPane jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + jSplitPane.setTopComponent(jPanel); + jSplitPane.setBottomComponent(jPanelButtons); + jSplitPane.setDividerSize(0); + + setContentPane(jSplitPane); + } + + /** + * This method sets the fields of the edit frame according to the originalCalendarEvent object. + * The date is not set by this method. Its done by the initComponents method. + */ + private void setFieldValues() { + ((JTextField) vecFields.get(0)).setText(calendarEvent.getCategoryName()); + } + + /** + * This method is invoked if the enter key is pressed or if the submit button + * has been pressed. It starts a client request relating to the user's input of + * the text fields. + */ + protected void submit() { + String sNewCategoryName = ((JTextField) vecFields.get(0)).getText(); + + ClientRequest clientRequest = new ClientRequest(ClientRequest.RENAME_CATEGORY); + clientRequest.setEvent(calendarEvent); + clientRequest.setString(sNewCategoryName); + ServerRequester.sendClientRequest(clientRequest); + netCalendarClient.updateLast(); + calendarEvent.setCategoryName(sNewCategoryName); + } +} |
