2013-06-27 20:30:15 +02:00
|
|
|
|
using Outlook2013TodoAddIn.Forms;
|
|
|
|
|
using System;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
using System.Collections.Generic;
|
2013-07-18 20:16:35 +02:00
|
|
|
|
using System.Collections.Specialized;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
using System.Drawing;
|
2013-07-12 16:54:46 +02:00
|
|
|
|
using System.Drawing.Drawing2D;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using Outlook = Microsoft.Office.Interop.Outlook;
|
|
|
|
|
|
|
|
|
|
namespace Outlook2013TodoAddIn
|
|
|
|
|
{
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// User control to hold the calendar, etc...
|
|
|
|
|
/// </summary>
|
2013-03-29 17:00:07 +01:00
|
|
|
|
public partial class AppointmentsControl : UserControl
|
|
|
|
|
{
|
2013-03-29 19:03:00 +01:00
|
|
|
|
#region "Properties"
|
2013-06-27 20:30:15 +02:00
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Number of days (including today) to retrieve appointments from in the future
|
|
|
|
|
/// </summary>
|
2013-06-27 20:30:15 +02:00
|
|
|
|
public decimal NumDays { get; set; }
|
2013-03-29 17:00:07 +01:00
|
|
|
|
|
2013-05-01 22:22:27 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets whether mail notifications are enabled or not
|
|
|
|
|
/// </summary>
|
2013-06-27 20:30:15 +02:00
|
|
|
|
public bool MailAlertsEnabled { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets whether to show past appointments in the current day or not
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool ShowPastAppointments { get; set; }
|
2013-05-01 22:22:27 +02:00
|
|
|
|
|
2013-07-18 20:16:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets a list of all stores/accounts to retrieve information from
|
|
|
|
|
/// </summary>
|
|
|
|
|
public StringCollection Accounts { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets whether to show friendly group headers (yesterday, today, tomorrow)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool ShowFriendlyGroupHeaders { get; set; }
|
|
|
|
|
|
2013-05-03 16:27:19 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets the selected calendar date
|
|
|
|
|
/// </summary>
|
|
|
|
|
public DateTime SelectedDate
|
|
|
|
|
{
|
|
|
|
|
get { return this.apptCalendar.SelectedDate; }
|
|
|
|
|
set { this.apptCalendar.SelectedDate = value; }
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-22 22:12:10 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets whether to show the tasks list
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool ShowTasks { get; set; }
|
|
|
|
|
|
2013-07-24 17:51:16 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets/sets the first day of the week for the calendar
|
|
|
|
|
/// </summary>
|
|
|
|
|
public System.DayOfWeek FirstDayOfWeek { get; set; }
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
#endregion "Properties"
|
|
|
|
|
|
|
|
|
|
#region "Methods"
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Default constructor
|
|
|
|
|
/// </summary>
|
2013-03-29 17:00:07 +01:00
|
|
|
|
public AppointmentsControl()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Respond to calendar changes
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">DateRangeEventArgs</param>
|
2013-04-26 17:32:14 +02:00
|
|
|
|
private void apptCalendar_SelectedDateChanged(object sender, EventArgs e)
|
2013-07-22 22:12:10 +02:00
|
|
|
|
{
|
|
|
|
|
this.RetrieveData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieves appointments and tasks if configured
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void RetrieveData()
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-24 17:51:16 +02:00
|
|
|
|
this.apptCalendar.FirstDayOfWeek = this.FirstDayOfWeek;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
this.RetrieveAppointments();
|
2013-07-22 22:12:10 +02:00
|
|
|
|
if (this.ShowTasks)
|
|
|
|
|
{
|
2013-07-24 18:38:54 +02:00
|
|
|
|
this.splitContainer1.Panel2Collapsed = false;
|
|
|
|
|
this.splitContainer1.SplitterDistance = Properties.Settings.Default.SplitterDistance;
|
2013-07-22 22:12:10 +02:00
|
|
|
|
// this.RetrieveTasks();
|
|
|
|
|
}
|
2013-07-24 18:38:54 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.splitContainer1.Panel2Collapsed = true;
|
|
|
|
|
}
|
2013-03-29 17:00:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
2013-07-22 22:12:10 +02:00
|
|
|
|
/// Retrieves tasks for all selected stores
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// </summary>
|
2013-07-22 22:12:10 +02:00
|
|
|
|
private void RetrieveTasks()
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-22 22:12:10 +02:00
|
|
|
|
List<Outlook.TaskItem> tasks = new List<Outlook.TaskItem>();
|
|
|
|
|
foreach (Outlook.Store store in Globals.ThisAddIn.Application.Session.Stores)
|
|
|
|
|
{
|
|
|
|
|
if (Properties.Settings.Default.Accounts != null && Properties.Settings.Default.Accounts.Contains(store.DisplayName))
|
|
|
|
|
{
|
|
|
|
|
Outlook.Folder todoFolder = store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderToDo) as Outlook.Folder;
|
|
|
|
|
tasks.AddRange(this.RetrieveTasksForFolder(todoFolder));
|
|
|
|
|
// TODO: Shared calendars?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// We need to sort them because they may come from different accounts already ordered
|
|
|
|
|
// tasks.Sort(CompareTasks);
|
|
|
|
|
|
|
|
|
|
//Outlook.Folder todoFolder =
|
|
|
|
|
// Globals.ThisAddIn.Application.Session.GetDefaultFolder(
|
|
|
|
|
// Outlook.OlDefaultFolders.olFolderToDo)
|
|
|
|
|
// as Outlook.Folder;
|
|
|
|
|
//this.RetrieveTasksForFolder(todoFolder);
|
2013-03-29 17:00:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-01 22:22:27 +02:00
|
|
|
|
/// <summary>
|
2013-06-27 20:30:15 +02:00
|
|
|
|
/// Retrieves to-do tasks for the folder on the specified store
|
2013-05-01 22:22:27 +02:00
|
|
|
|
/// </summary>
|
2013-06-27 20:30:15 +02:00
|
|
|
|
/// <param name="todoFolder">Outlook folder</param>
|
2013-07-22 22:12:10 +02:00
|
|
|
|
private List<Outlook.TaskItem> RetrieveTasksForFolder(Outlook.Folder todoFolder)
|
2013-05-01 22:22:27 +02:00
|
|
|
|
{
|
2013-07-22 22:12:10 +02:00
|
|
|
|
List<Outlook.TaskItem> tasks = new List<Outlook.TaskItem>();
|
2013-06-27 20:30:15 +02:00
|
|
|
|
foreach (object item in todoFolder.Items)
|
|
|
|
|
{
|
|
|
|
|
if (item is Outlook.MailItem)
|
|
|
|
|
{
|
|
|
|
|
Outlook.MailItem mail = item as Outlook.MailItem;
|
|
|
|
|
//mail.Categories
|
|
|
|
|
//mail.TaskCompletedDate;
|
|
|
|
|
MessageBox.Show(String.Format("Mail Task: {0}, Due: {1}", mail.TaskSubject, mail.TaskDueDate.ToShortDateString()));
|
|
|
|
|
}
|
|
|
|
|
else if (item is Outlook.ContactItem)
|
|
|
|
|
{
|
|
|
|
|
Outlook.ContactItem contact = item as Outlook.ContactItem;
|
|
|
|
|
//contact.Categories
|
|
|
|
|
//contact.TaskCompletedDate
|
|
|
|
|
MessageBox.Show(String.Format("Contact Task: {0}, Due: {1}", contact.TaskSubject, contact.TaskDueDate.ToShortDateString()));
|
|
|
|
|
}
|
|
|
|
|
else if (item is Outlook.TaskItem)
|
|
|
|
|
{
|
|
|
|
|
Outlook.TaskItem task = item as Outlook.TaskItem;
|
|
|
|
|
//task.Categories
|
|
|
|
|
//task.DateCompleted
|
|
|
|
|
MessageBox.Show(String.Format("Task Task: {0}, Due: {1}", task.Subject, task.DueDate.ToShortDateString()));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Unknown type");
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-22 22:12:10 +02:00
|
|
|
|
return tasks;
|
2013-05-01 22:22:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
2013-07-18 20:16:35 +02:00
|
|
|
|
/// Retrieve all appointments for the current configurations for all selected stores
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// </summary>
|
2013-07-22 22:12:10 +02:00
|
|
|
|
private void RetrieveAppointments()
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-18 20:16:35 +02:00
|
|
|
|
List<Outlook.AppointmentItem> appts = new List<Outlook.AppointmentItem>();
|
|
|
|
|
foreach (Outlook.Store store in Globals.ThisAddIn.Application.Session.Stores)
|
|
|
|
|
{
|
|
|
|
|
if (Properties.Settings.Default.Accounts != null && Properties.Settings.Default.Accounts.Contains(store.DisplayName))
|
|
|
|
|
{
|
|
|
|
|
Outlook.Folder calFolder = store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
|
|
|
|
|
appts.AddRange(this.RetrieveAppointmentsForFolder(calFolder));
|
|
|
|
|
// TODO: Shared calendars?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// We need to sort them because they may come from different accounts already ordered
|
|
|
|
|
appts.Sort(CompareAppointments);
|
|
|
|
|
|
2013-03-29 17:00:07 +01:00
|
|
|
|
// Get the Outlook folder for the calendar to retrieve the appointments
|
2013-07-18 20:16:35 +02:00
|
|
|
|
//Outlook.Folder calFolder =
|
|
|
|
|
// Globals.ThisAddIn.Application.Session.GetDefaultFolder(
|
|
|
|
|
// Outlook.OlDefaultFolders.olFolderCalendar)
|
|
|
|
|
// as Outlook.Folder;
|
|
|
|
|
//List<Outlook.AppointmentItem> appts = this.RetrieveAppointmentsForFolder(calFolder);
|
2013-03-29 17:00:07 +01:00
|
|
|
|
|
|
|
|
|
// Highlight dates with appointments in the current calendar
|
2013-04-26 17:32:14 +02:00
|
|
|
|
this.apptCalendar.BoldedDates = appts.Select<Outlook.AppointmentItem, DateTime>(a => a.Start.Date).Distinct().ToArray();
|
2013-03-29 17:00:07 +01:00
|
|
|
|
|
|
|
|
|
// Now display the actual appointments below the calendar
|
2013-04-26 17:32:14 +02:00
|
|
|
|
DateTime startRange = this.apptCalendar.SelectedDate;
|
2013-06-27 20:30:15 +02:00
|
|
|
|
if (!this.ShowPastAppointments)
|
|
|
|
|
{
|
|
|
|
|
startRange = startRange.Add(DateTime.Now.TimeOfDay);
|
|
|
|
|
}
|
|
|
|
|
DateTime endRange = startRange.AddDays((int)this.NumDays);
|
2013-03-29 17:00:07 +01:00
|
|
|
|
|
|
|
|
|
// Get items in range
|
|
|
|
|
var lstItems = appts.Where(a => a.Start >= startRange && a.Start <= endRange);
|
|
|
|
|
|
|
|
|
|
int sameDay = -1; // startRange.Day;
|
|
|
|
|
|
|
|
|
|
List<ListViewItem> lstCol = new List<ListViewItem>();
|
2013-04-30 23:00:02 +02:00
|
|
|
|
ListViewGroup grp = null;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
lstItems.ToList().ForEach(i =>
|
|
|
|
|
{
|
|
|
|
|
if (i.Start.Day != sameDay)
|
|
|
|
|
{
|
2013-07-18 20:16:35 +02:00
|
|
|
|
string groupHeaderText = i.Start.ToShortDateString();
|
|
|
|
|
if (this.ShowFriendlyGroupHeaders)
|
|
|
|
|
{
|
|
|
|
|
int daysDiff = (int)(i.Start.Date - DateTime.Today).TotalDays;
|
|
|
|
|
switch (daysDiff)
|
|
|
|
|
{
|
|
|
|
|
case -1:
|
|
|
|
|
groupHeaderText = Constants.Yesterday + ": " + groupHeaderText;
|
|
|
|
|
break;
|
|
|
|
|
case 0:
|
|
|
|
|
groupHeaderText = Constants.Today + ": " + groupHeaderText;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
groupHeaderText = Constants.Tomorrow + ": " + groupHeaderText;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
grp = new ListViewGroup(groupHeaderText, HorizontalAlignment.Left);
|
2013-07-24 18:38:54 +02:00
|
|
|
|
this.lstAppointments.Groups.Add(grp); // TODO: Style it?
|
2013-03-29 17:00:07 +01:00
|
|
|
|
sameDay = i.Start.Day;
|
|
|
|
|
};
|
2013-04-30 23:00:02 +02:00
|
|
|
|
string loc = "-"; // TODO: If no second line is specified, the tile is stretched to only one line
|
|
|
|
|
if (!String.IsNullOrEmpty(i.Location)) loc = i.Location;
|
|
|
|
|
ListViewItem current = new ListViewItem(new string[] { String.Format("{0} {1}", i.Start.ToShortTimeString(), i.Subject), loc });
|
2013-03-29 17:00:07 +01:00
|
|
|
|
current.SubItems.Add(i.Subject);
|
|
|
|
|
|
2013-04-30 23:00:02 +02:00
|
|
|
|
// current.Font = new Font(this.Font, FontStyle.Bold);
|
|
|
|
|
// current.UseItemStyleForSubItems = false;
|
|
|
|
|
|
2013-03-29 17:00:07 +01:00
|
|
|
|
current.ToolTipText = String.Format("{0} - {1} {2}", i.Start.ToShortTimeString(), i.End.ToShortTimeString(), i.Subject);
|
|
|
|
|
current.Tag = i;
|
2013-04-30 23:00:02 +02:00
|
|
|
|
current.Group = grp;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
switch (i.BusyStatus)
|
|
|
|
|
{
|
|
|
|
|
case Outlook.OlBusyStatus.olBusy:
|
|
|
|
|
current.ForeColor = Color.Purple;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olFree:
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olOutOfOffice:
|
|
|
|
|
current.ForeColor = Color.Brown;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olTentative:
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olWorkingElsewhere:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lstCol.Add(current);
|
|
|
|
|
});
|
|
|
|
|
|
2013-07-24 18:38:54 +02:00
|
|
|
|
this.lstAppointments.Items.Clear();
|
|
|
|
|
this.lstAppointments.Items.AddRange(lstCol.ToArray());
|
2013-04-26 17:32:14 +02:00
|
|
|
|
|
|
|
|
|
this.apptCalendar.UpdateCalendar();
|
2013-03-29 17:00:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-18 20:16:35 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Comparer method to sort appointments based on start date/time
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="x">First appointment</param>
|
|
|
|
|
/// <param name="y">Second appointment</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static int CompareAppointments(Outlook.AppointmentItem x, Outlook.AppointmentItem y)
|
|
|
|
|
{
|
|
|
|
|
return x.Start.CompareTo(y.Start);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-27 20:30:15 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Retrieve all appointments for the current configurations for a specific folder
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="calFolder">Outlook folder</param>
|
|
|
|
|
/// <returns>List of appointments</returns>
|
|
|
|
|
private List<Outlook.AppointmentItem> RetrieveAppointmentsForFolder(Outlook.Folder calFolder)
|
|
|
|
|
{
|
|
|
|
|
int selectedMonth = this.apptCalendar.SelectedDate.Month;
|
|
|
|
|
int selectedYear = this.apptCalendar.SelectedDate.Year;
|
|
|
|
|
|
|
|
|
|
// To get all the appointments for the current month (so it displays nicely bolded even for past events)
|
|
|
|
|
DateTime start = new DateTime(selectedYear, selectedMonth, 1); // MM-01-YYYY
|
|
|
|
|
DateTime end = start.AddMonths(1).AddDays(-1); // Last day of the month
|
|
|
|
|
end = end.AddDays((int)this.NumDays); // So we get appointments for the "possible" first days of the next month
|
|
|
|
|
|
|
|
|
|
// Get all the appointments
|
|
|
|
|
Outlook.Items rangeAppts = GetAppointmentsInRange(calFolder, start, end);
|
|
|
|
|
|
|
|
|
|
// Get a more manageable list
|
|
|
|
|
List<Outlook.AppointmentItem> appts = new List<Outlook.AppointmentItem>();
|
|
|
|
|
if (rangeAppts != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (Outlook.AppointmentItem appt in rangeAppts)
|
|
|
|
|
{
|
|
|
|
|
appts.Add(appt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return appts;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 17:00:07 +01:00
|
|
|
|
/// <summary>
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// Get recurring appointments in a date range.
|
2013-03-29 17:00:07 +01:00
|
|
|
|
/// </summary>
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <param name="folder">Outlook folder</param>
|
|
|
|
|
/// <param name="startTime">Start time</param>
|
|
|
|
|
/// <param name="endTime">End time</param>
|
2013-03-29 17:00:07 +01:00
|
|
|
|
/// <returns>Outlook.Items</returns>
|
|
|
|
|
private Outlook.Items GetAppointmentsInRange(Outlook.Folder folder, DateTime startTime, DateTime endTime)
|
|
|
|
|
{
|
|
|
|
|
string filter = "[Start] >= '"
|
|
|
|
|
+ startTime.ToString("g")
|
|
|
|
|
+ "' AND [End] <= '"
|
|
|
|
|
+ endTime.ToString("g") + "'";
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Outlook.Items calItems = folder.Items;
|
|
|
|
|
calItems.IncludeRecurrences = true;
|
|
|
|
|
calItems.Sort("[Start]", Type.Missing);
|
|
|
|
|
Outlook.Items restrictItems = calItems.Restrict(filter);
|
|
|
|
|
if (restrictItems.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
return restrictItems;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch { return null; }
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Open the appointment, having in mind it might be a recurring event
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">EventArgs</param>
|
2013-07-24 18:38:54 +02:00
|
|
|
|
private void lstAppointments_DoubleClick(object sender, EventArgs e)
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-24 18:38:54 +02:00
|
|
|
|
if (this.lstAppointments.SelectedIndices.Count != 0)
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-24 18:38:54 +02:00
|
|
|
|
Outlook.AppointmentItem appt = this.lstAppointments.SelectedItems[0].Tag as Outlook.AppointmentItem;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
if (appt != null)
|
|
|
|
|
{
|
|
|
|
|
if (appt.IsRecurring)
|
|
|
|
|
{
|
|
|
|
|
FormRecurringOpen f = new FormRecurringOpen();
|
|
|
|
|
if (f.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
if (f.OpenRecurring)
|
|
|
|
|
{
|
|
|
|
|
// Open up the master appointment in a new window
|
|
|
|
|
// If we open the current instance then there is an error: "This item is no longer valid because it has been closed"
|
|
|
|
|
// One workaround is to refresh the appointments list to get new instances...
|
|
|
|
|
Outlook.AppointmentItem masterAppt = appt.Parent; // Get the master appointment item
|
|
|
|
|
masterAppt.Display(true); // Will modify ALL instances
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Open up the appointment in a new window
|
|
|
|
|
appt.Display(true); // Modal yes/no
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Open up the appointment in a new window
|
|
|
|
|
appt.Display(true); // Modal yes/no
|
|
|
|
|
}
|
2013-07-22 22:12:10 +02:00
|
|
|
|
// At the end, synchronously "refresh" appointments in case they have changed
|
2013-03-29 17:00:07 +01:00
|
|
|
|
this.RetrieveAppointments();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a new mail item to reply all recipients of an appointment (except the current user)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">EventArgs</param>
|
2013-03-29 17:00:07 +01:00
|
|
|
|
private void mnuItemReplyAllEmail_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2013-07-24 18:38:54 +02:00
|
|
|
|
if (this.lstAppointments.SelectedIndices.Count != 0)
|
2013-03-29 17:00:07 +01:00
|
|
|
|
{
|
2013-07-24 18:38:54 +02:00
|
|
|
|
Outlook.AppointmentItem appt = this.lstAppointments.SelectedItems[0].Tag as Outlook.AppointmentItem;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
if (appt != null)
|
|
|
|
|
{
|
|
|
|
|
Outlook.MailItem mail = Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem) as Outlook.MailItem;
|
2013-06-18 22:52:05 +02:00
|
|
|
|
string curUserAddress = OutlookHelper.GetEmailAddress(Globals.ThisAddIn.Application.Session.CurrentUser);
|
2013-03-29 17:00:07 +01:00
|
|
|
|
foreach (Outlook.Recipient rcpt in appt.Recipients)
|
|
|
|
|
{
|
2013-06-18 22:52:05 +02:00
|
|
|
|
string smtpAddress = OutlookHelper.GetEmailAddress(rcpt);
|
2013-03-29 17:00:07 +01:00
|
|
|
|
if (curUserAddress != smtpAddress)
|
|
|
|
|
{
|
|
|
|
|
mail.Recipients.Add(smtpAddress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mail.Body = Environment.NewLine + Environment.NewLine + appt.Body;
|
2013-07-18 20:16:35 +02:00
|
|
|
|
mail.Subject = Constants.SubjectRE + ": " + appt.Subject;
|
2013-03-29 17:00:07 +01:00
|
|
|
|
mail.Display();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-03-29 19:03:00 +01:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Switch to the calendar view when double-clicking a date
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">EventArgs</param>
|
2013-04-26 17:32:14 +02:00
|
|
|
|
private void apptCalendar_CellDoubleClick(object sender, EventArgs e)
|
2013-03-29 19:03:00 +01:00
|
|
|
|
{
|
2013-03-30 00:31:49 +01:00
|
|
|
|
// Clicking in days outside of the current month will cause the calendar to refresh to that day
|
2013-03-29 23:52:47 +01:00
|
|
|
|
// reposition all days and select the wrong one
|
|
|
|
|
Outlook.Folder f = Globals.ThisAddIn.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
|
|
|
|
|
Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder = f;
|
|
|
|
|
Outlook.CalendarView cv = (Outlook.CalendarView)(Globals.ThisAddIn.Application.ActiveExplorer().CurrentView);
|
|
|
|
|
cv.CalendarViewMode = Outlook.OlCalendarViewMode.olCalendarViewDay;
|
2013-04-26 17:32:14 +02:00
|
|
|
|
cv.GoToDate(this.apptCalendar.SelectedDate);
|
2013-03-29 19:03:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-27 20:30:15 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// New method to show the configuration form
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">EventArgs</param>
|
|
|
|
|
private void apptCalendar_ConfigurationButtonClicked(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
using (FormConfiguration cfg = new FormConfiguration())
|
|
|
|
|
{
|
|
|
|
|
if (cfg.ShowDialog() == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
this.NumDays = cfg.NumDays;
|
|
|
|
|
this.MailAlertsEnabled = cfg.MailAlertsEnabled;
|
|
|
|
|
this.ShowPastAppointments = cfg.ShowPastAppointments;
|
2013-07-18 20:16:35 +02:00
|
|
|
|
this.Accounts = cfg.Accounts;
|
|
|
|
|
this.ShowFriendlyGroupHeaders = cfg.ShowFriendlyGroupHeaders;
|
2013-07-22 22:12:10 +02:00
|
|
|
|
this.ShowTasks = cfg.ShowTasks;
|
2013-07-24 17:51:16 +02:00
|
|
|
|
this.FirstDayOfWeek = cfg.FirstDayOfWeek;
|
2013-07-22 22:12:10 +02:00
|
|
|
|
this.RetrieveData();
|
2013-06-27 20:30:15 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 16:54:46 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Method to custom draw the list items
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">DrawListViewItemEventArgs</param>
|
2013-07-24 18:38:54 +02:00
|
|
|
|
private void lstAppointments_DrawItem(object sender, DrawListViewItemEventArgs e)
|
2013-07-12 16:54:46 +02:00
|
|
|
|
{
|
|
|
|
|
e.DrawBackground(); // To avoid repainting (making font "grow")
|
|
|
|
|
Outlook.AppointmentItem appt = e.Item.Tag as Outlook.AppointmentItem;
|
|
|
|
|
|
|
|
|
|
Color catColor = Color.Empty;
|
|
|
|
|
|
|
|
|
|
Font itemFont = this.Font;
|
|
|
|
|
if (!String.IsNullOrEmpty(appt.Categories))
|
|
|
|
|
{
|
|
|
|
|
string[] allCats = appt.Categories.Split(new char[] { ',' });
|
|
|
|
|
if (allCats != null && allCats.Length != 0)
|
|
|
|
|
{
|
|
|
|
|
List<string> cs = allCats.Select(cat => cat.Trim()).ToList();
|
|
|
|
|
cs.ForEach(cat =>
|
|
|
|
|
{
|
|
|
|
|
Outlook.Category c = Globals.ThisAddIn.Application.Session.Categories[cat] as Outlook.Category;
|
|
|
|
|
if (c != null)
|
|
|
|
|
{
|
|
|
|
|
catColor = TranslateCategoryColor(c.Color);
|
|
|
|
|
}
|
|
|
|
|
// TODO: Check if more than one
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int startRectangleWidth = 65;
|
|
|
|
|
int horizontalSpacing = 5;
|
|
|
|
|
|
|
|
|
|
Rectangle totalRectangle = e.Bounds;
|
|
|
|
|
Rectangle startRectangle = totalRectangle; startRectangle.Width = startRectangleWidth;
|
|
|
|
|
Rectangle statusRectangle = totalRectangle; statusRectangle.Width = horizontalSpacing * 2; statusRectangle.Offset(startRectangleWidth + horizontalSpacing, 0);
|
|
|
|
|
Rectangle subjectRectangle = totalRectangle; subjectRectangle.Height = this.FontHeight; subjectRectangle.Offset(startRectangleWidth + horizontalSpacing * 4, 0);
|
|
|
|
|
Rectangle locationRectangle = totalRectangle; locationRectangle.Height = this.FontHeight; locationRectangle.Offset(startRectangleWidth + horizontalSpacing * 4, this.FontHeight);
|
|
|
|
|
bool selected = e.State.HasFlag(ListViewItemStates.Selected);
|
|
|
|
|
Color back = Color.Empty;
|
|
|
|
|
if (selected) back = Color.LightCyan;
|
|
|
|
|
using (Brush br = new SolidBrush(back))
|
|
|
|
|
e.Graphics.FillRectangle(br, totalRectangle);
|
|
|
|
|
|
|
|
|
|
StringFormat rightFormat = new StringFormat();
|
|
|
|
|
rightFormat.Alignment = StringAlignment.Far;
|
|
|
|
|
rightFormat.LineAlignment = StringAlignment.Near;
|
|
|
|
|
StringFormat leftFormat = new StringFormat();
|
|
|
|
|
leftFormat.Alignment = StringAlignment.Near;
|
|
|
|
|
leftFormat.LineAlignment = StringAlignment.Near;
|
|
|
|
|
|
|
|
|
|
Brush colorBrush = new SolidBrush(this.ForeColor);
|
|
|
|
|
e.Graphics.DrawString(appt.Start.ToShortTimeString(), this.Font, colorBrush, startRectangle, rightFormat);
|
|
|
|
|
|
|
|
|
|
Color statusColor = Color.LightBlue;
|
|
|
|
|
Brush statusBrush = new SolidBrush(Color.Transparent);
|
|
|
|
|
switch (appt.BusyStatus)
|
|
|
|
|
{
|
|
|
|
|
case Outlook.OlBusyStatus.olBusy:
|
|
|
|
|
statusBrush = new SolidBrush(statusColor);
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olFree:
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olOutOfOffice:
|
|
|
|
|
statusBrush = new SolidBrush(Color.Purple); // TODO: Figure this out
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olTentative:
|
|
|
|
|
statusBrush = new HatchBrush(HatchStyle.BackwardDiagonal, statusColor, this.BackColor);
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlBusyStatus.olWorkingElsewhere:
|
|
|
|
|
statusBrush = new HatchBrush(HatchStyle.DottedDiamond, statusColor, this.BackColor);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// Let's draw the status with a custom brush
|
|
|
|
|
e.Graphics.FillRectangle(statusBrush, statusRectangle);
|
|
|
|
|
e.Graphics.DrawRectangle(new Pen(statusColor), statusRectangle);
|
|
|
|
|
|
|
|
|
|
e.Graphics.FillRectangle(new SolidBrush(catColor), subjectRectangle);
|
|
|
|
|
e.Graphics.DrawString(appt.Subject, new Font(this.Font, FontStyle.Bold), colorBrush, subjectRectangle, leftFormat);
|
|
|
|
|
e.Graphics.FillRectangle(new SolidBrush(catColor), locationRectangle);
|
|
|
|
|
e.Graphics.DrawString(appt.Location, this.Font, colorBrush, locationRectangle, leftFormat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Color TranslateCategoryColor(Outlook.OlCategoryColor col)
|
|
|
|
|
{
|
|
|
|
|
Color result = Color.Black;
|
|
|
|
|
switch (col)
|
|
|
|
|
{
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorNone:
|
|
|
|
|
// Nothing
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorRed:
|
|
|
|
|
result = Color.Red;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorOrange:
|
|
|
|
|
result = Color.Orange;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorPeach:
|
|
|
|
|
result = Color.PeachPuff;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorYellow:
|
|
|
|
|
result = Color.Yellow;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorGreen:
|
|
|
|
|
result = Color.Green;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorTeal:
|
|
|
|
|
result = Color.Teal;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorOlive:
|
|
|
|
|
result = Color.Olive;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorBlue:
|
|
|
|
|
result = Color.Blue;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorPurple:
|
|
|
|
|
result = Color.Purple;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorMaroon:
|
|
|
|
|
result = Color.Maroon;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorSteel:
|
|
|
|
|
result = Color.LightSteelBlue;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkSteel:
|
|
|
|
|
result = Color.SteelBlue;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorGray:
|
|
|
|
|
result = Color.Gray;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkGray:
|
|
|
|
|
result = Color.DarkGray;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorBlack:
|
|
|
|
|
result = Color.Black;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkRed:
|
|
|
|
|
result = Color.DarkRed;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkOrange:
|
|
|
|
|
result = Color.DarkOrange;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkPeach:
|
|
|
|
|
result = Color.DarkSalmon;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkYellow:
|
|
|
|
|
result = Color.DarkGoldenrod;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkGreen:
|
|
|
|
|
result = Color.DarkGreen;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkTeal:
|
|
|
|
|
result = Color.DarkCyan;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkOlive:
|
|
|
|
|
result = Color.DarkOliveGreen;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkBlue:
|
|
|
|
|
result = Color.DarkBlue;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkPurple:
|
|
|
|
|
result = Color.DarkViolet;
|
|
|
|
|
break;
|
|
|
|
|
case Outlook.OlCategoryColor.olCategoryColorDarkMaroon:
|
|
|
|
|
result = Color.DarkKhaki;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-24 18:38:54 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Save the splitter distance to restore upon reloading the plugin
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">Sender</param>
|
|
|
|
|
/// <param name="e">SplitterEventArgs</param>
|
|
|
|
|
private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Properties.Settings.Default.SplitterDistance = this.splitContainer1.SplitterDistance;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-29 19:03:00 +01:00
|
|
|
|
#endregion "Methods"
|
2013-03-29 17:00:07 +01:00
|
|
|
|
}
|
|
|
|
|
}
|