summaryrefslogtreecommitdiff
path: root/sources/client
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2009-02-18 17:33:22 +0000
committerPaul Buetow <paul@buetow.org>2009-02-18 17:33:22 +0000
commit4722100cba287b164957c658c2e035783e20c963 (patch)
tree35733fd3e50aeeb493e38ceaea83521a4710f0ac /sources/client
parent61f7175cc3e51c0afaf63e380d03824a77464ba8 (diff)
moved sources
Diffstat (limited to 'sources/client')
-rw-r--r--sources/client/AboutWindow.java50
-rw-r--r--sources/client/CalendarTableCellRenderer.java135
-rw-r--r--sources/client/CalendarTableModel.java481
-rw-r--r--sources/client/InfoWindow.java57
-rw-r--r--sources/client/LicenseWindow.java33
-rw-r--r--sources/client/NetCalendarClient.java731
-rw-r--r--sources/client/ServerRequester.java82
-rw-r--r--sources/client/SplashScreen.java42
-rw-r--r--sources/client/SubWindow.java101
-rw-r--r--sources/client/helper/DateSpinner.java57
-rw-r--r--sources/client/helper/GUIHelper.java189
-rw-r--r--sources/client/inputforms/AdvancedSearching.java141
-rw-r--r--sources/client/inputforms/CreateNewEvent.java122
-rw-r--r--sources/client/inputforms/EditExistingEvent.java156
-rw-r--r--sources/client/inputforms/InputForm.java93
-rw-r--r--sources/client/inputforms/Preferences.java99
-rw-r--r--sources/client/inputforms/RenameCategory.java123
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);
+ }
+}