Added initial support for tasks!!! :-)

This commit is contained in:
gamosoft_cp 2015-03-12 18:45:29 +00:00
parent aa2a81cc02
commit e371703148
12 changed files with 341 additions and 45 deletions

View File

@ -31,6 +31,7 @@
this.components = new System.ComponentModel.Container();
this.ctxMenuAppointments = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuItemReplyAllEmail = new System.Windows.Forms.ToolStripMenuItem();
this.mnuItemDeleteAppointment = new System.Windows.Forms.ToolStripMenuItem();
this.panel1 = new System.Windows.Forms.Panel();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.lstAppointments = new System.Windows.Forms.ListView();
@ -41,7 +42,7 @@
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.panelCalendar = new System.Windows.Forms.Panel();
this.apptCalendar = new Outlook2013TodoAddIn.CustomCalendar();
this.mnuItemDeleteAppointment = new System.Windows.Forms.ToolStripMenuItem();
this.ctxMenuTasks = new System.Windows.Forms.ContextMenuStrip(this.components);
this.ctxMenuAppointments.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
@ -57,7 +58,7 @@
this.mnuItemReplyAllEmail,
this.mnuItemDeleteAppointment});
this.ctxMenuAppointments.Name = "ctxMenuAppointments";
this.ctxMenuAppointments.Size = new System.Drawing.Size(225, 80);
this.ctxMenuAppointments.Size = new System.Drawing.Size(225, 52);
//
// mnuItemReplyAllEmail
//
@ -66,6 +67,13 @@
this.mnuItemReplyAllEmail.Text = "Reply All With Email";
this.mnuItemReplyAllEmail.Click += new System.EventHandler(this.mnuItemReplyAllEmail_Click);
//
// mnuItemDeleteAppointment
//
this.mnuItemDeleteAppointment.Name = "mnuItemDeleteAppointment";
this.mnuItemDeleteAppointment.Size = new System.Drawing.Size(224, 24);
this.mnuItemDeleteAppointment.Text = "Delete appointment/s";
this.mnuItemDeleteAppointment.Click += new System.EventHandler(this.mnuItemDeleteAppointment_Click);
//
// panel1
//
this.panel1.Controls.Add(this.splitContainer1);
@ -134,7 +142,7 @@
this.lstTasks.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader3,
this.columnHeader4});
this.lstTasks.ContextMenuStrip = this.ctxMenuAppointments;
this.lstTasks.ContextMenuStrip = this.ctxMenuTasks;
this.lstTasks.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstTasks.FullRowSelect = true;
this.lstTasks.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
@ -148,6 +156,8 @@
this.lstTasks.TileSize = new System.Drawing.Size(300, 38);
this.lstTasks.UseCompatibleStateImageBehavior = false;
this.lstTasks.View = System.Windows.Forms.View.Tile;
this.lstTasks.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.lstTasks_DrawItem);
this.lstTasks.DoubleClick += new System.EventHandler(this.lstTasks_DoubleClick);
//
// columnHeader3
//
@ -192,12 +202,10 @@
this.apptCalendar.SelectedDateChanged += new System.EventHandler(this.apptCalendar_SelectedDateChanged);
this.apptCalendar.ConfigurationButtonClicked += new System.EventHandler(this.apptCalendar_ConfigurationButtonClicked);
//
// mnuItemDeleteAppointment
// ctxMenuTasks
//
this.mnuItemDeleteAppointment.Name = "mnuItemDeleteAppointment";
this.mnuItemDeleteAppointment.Size = new System.Drawing.Size(224, 24);
this.mnuItemDeleteAppointment.Text = "Delete appointment/s";
this.mnuItemDeleteAppointment.Click += new System.EventHandler(this.mnuItemDeleteAppointment_Click);
this.ctxMenuTasks.Name = "ctxMenuTasks";
this.ctxMenuTasks.Size = new System.Drawing.Size(61, 4);
//
// AppointmentsControl
//
@ -232,6 +240,7 @@
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.Panel panelCalendar;
private System.Windows.Forms.ToolStripMenuItem mnuItemDeleteAppointment;
private System.Windows.Forms.ContextMenuStrip ctxMenuTasks;
}

View File

@ -109,6 +109,7 @@ namespace Outlook2013TodoAddIn
this.RetrieveAppointments();
if (this.ShowTasks)
{
this.RetrieveTasks();
this.splitContainer1.Panel2Collapsed = false;
}
else
@ -122,7 +123,7 @@ namespace Outlook2013TodoAddIn
/// </summary>
private void RetrieveTasks()
{
List<Outlook.TaskItem> tasks = new List<Outlook.TaskItem>();
List<OLTaskItem> tasks = new List<OLTaskItem>();
foreach (Outlook.Store store in Globals.ThisAddIn.Application.Session.Stores)
{
if (Properties.Settings.Default.Accounts != null && Properties.Settings.Default.Accounts.Contains(store.DisplayName))
@ -133,51 +134,105 @@ namespace Outlook2013TodoAddIn
}
}
// We need to sort them because they may come from different accounts already ordered
// tasks.Sort(CompareTasks);
// Applies sorting by due date
tasks.Sort(CompareTasks);
//Outlook.Folder todoFolder =
// Globals.ThisAddIn.Application.Session.GetDefaultFolder(
// Outlook.OlDefaultFolders.olFolderToDo)
// as Outlook.Folder;
//this.RetrieveTasksForFolder(todoFolder);
int sameDay = -1; // startRange.Day;
List<ListViewItem> lstCol = new List<ListViewItem>();
ListViewGroup grp = null;
tasks.ForEach(t =>
{
if (t.DueDate.Day != sameDay)
{
string groupHeaderText = t.DueDate.ToShortDateString();
if (t.DueDate.Year == Constants.NullYear) groupHeaderText = "No due date";
if (this.ShowFriendlyGroupHeaders)
{
int daysDiff = (int)(t.DueDate.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;
}
}
if (this.ShowDayNames && t.DueDate.Year != Constants.NullYear)
{
groupHeaderText += " (" + t.DueDate.ToString("dddd") + ")";
}
grp = new ListViewGroup(groupHeaderText, HorizontalAlignment.Left);
this.lstTasks.Groups.Add(grp);
sameDay = t.DueDate.Day;
};
ListViewItem current = new ListViewItem(new string[] { String.Format("{0} {1}", t.DueDate.ToShortTimeString(), t.TaskSubject), "***" });
current.SubItems.Add(t.TaskSubject);
// current.Font = new Font(this.Font, FontStyle.Bold);
// current.UseItemStyleForSubItems = false;
current.ToolTipText = String.Format("Task Subject: {0}", t.TaskSubject);
if (t.StartDate.Year != Constants.NullYear)
{
current.ToolTipText += Environment.NewLine + String.Format("Start Date: {0}", t.StartDate.ToShortDateString());
}
if (t.Reminder.Year != Constants.NullYear)
{
current.ToolTipText += Environment.NewLine + String.Format("Reminder Time: {0}", t.Reminder.ToString());
}
if (t.DueDate.Year != Constants.NullYear)
{
current.ToolTipText += Environment.NewLine + String.Format("Due Date: {0}", t.DueDate.ToShortDateString());
}
current.ToolTipText += Environment.NewLine + String.Format("In Folder: {0}", t.FolderName);
t.Categories.ForEach(cat =>
{
Outlook.Category c = Globals.ThisAddIn.Application.Session.Categories[cat] as Outlook.Category;
if (c != null)
{
current.ToolTipText += Environment.NewLine + " - " + c.Name;
}
});
current.Tag = t;
current.Group = grp;
lstCol.Add(current);
});
this.lstTasks.Items.Clear();
this.lstTasks.Items.AddRange(lstCol.ToArray());
}
/// <summary>
/// Retrieves to-do tasks for the folder on the specified store
/// </summary>
/// <param name="todoFolder">Outlook folder</param>
private List<Outlook.TaskItem> RetrieveTasksForFolder(Outlook.Folder todoFolder)
private List<OLTaskItem> RetrieveTasksForFolder(Outlook.Folder todoFolder)
{
List<Outlook.TaskItem> tasks = new List<Outlook.TaskItem>();
List<OLTaskItem> tasks = new List<OLTaskItem>();
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");
}
tasks.Add(new OLTaskItem(item));
}
return tasks;
return tasks.Where(t => t.ValidTaskItem).ToList(); // Filter out invalid ones
}
/// <summary>
@ -251,7 +306,7 @@ namespace Outlook2013TodoAddIn
groupHeaderText += " (" + i.Start.ToString("dddd") + ")";
}
grp = new ListViewGroup(groupHeaderText, HorizontalAlignment.Left);
this.lstAppointments.Groups.Add(grp); // TODO: Style it?
this.lstAppointments.Groups.Add(grp);
sameDay = i.Start.Day;
};
string loc = "-"; // TODO: If no second line is specified, the tile is stretched to only one line
@ -281,7 +336,6 @@ namespace Outlook2013TodoAddIn
}
}
current.Tag = i;
current.Group = grp;
switch (i.BusyStatus)
@ -312,6 +366,17 @@ namespace Outlook2013TodoAddIn
this.apptCalendar.UpdateCalendar();
}
/// <summary>
/// Comparer method to sort tasks based on due date/time
/// </summary>
/// <param name="x">First task</param>
/// <param name="y">Second task</param>
/// <returns></returns>
private static int CompareTasks(OLTaskItem x, OLTaskItem y)
{
return x.DueDate.CompareTo(y.DueDate);
}
/// <summary>
/// Comparer method to sort appointments based on start date/time
/// </summary>
@ -385,6 +450,43 @@ namespace Outlook2013TodoAddIn
catch { return null; }
}
/// <summary>
/// Open the task
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">EventArgs</param>
private void lstTasks_DoubleClick(object sender, EventArgs e)
{
if (this.lstTasks.SelectedIndices.Count != 0)
{
OLTaskItem task = this.lstTasks.SelectedItems[0].Tag as OLTaskItem;
if (task != null)
{
if (task.OriginalItem is Outlook.MailItem)
{
Outlook.MailItem mail = task.OriginalItem as Outlook.MailItem;
mail.Display(true);
}
else if (task.OriginalItem is Outlook.ContactItem)
{
Outlook.ContactItem contact = task.OriginalItem as Outlook.ContactItem;
contact.Display(true);
}
else if (task.OriginalItem is Outlook.TaskItem)
{
Outlook.TaskItem t = task.OriginalItem as Outlook.TaskItem;
t.Display(true);
}
else
{
// Do nothing
}
// At the end, synchronously "refresh" tasks in case they have changed
this.RetrieveTasks();
}
}
}
/// <summary>
/// Open the appointment, having in mind it might be a recurring event
/// </summary>
@ -543,6 +645,75 @@ namespace Outlook2013TodoAddIn
}
}
private void lstTasks_DrawItem(object sender, DrawListViewItemEventArgs e)
{
e.DrawBackground(); // To avoid repainting (making font "grow")
OLTaskItem task = e.Item.Tag as OLTaskItem;
// Color catColor = Color.Empty;
List<Color> catColors = new List<Color>();
Font itemFont = this.Font;
task.Categories.ForEach(cat =>
{
Outlook.Category c = Globals.ThisAddIn.Application.Session.Categories[cat] as Outlook.Category;
if (c != null)
{
catColors.Add(TranslateCategoryColor(c.Color));
}
});
int categoriesRectangleWidth = 30;
int horizontalSpacing = 2;
Rectangle totalRectangle = e.Bounds;
Rectangle subjectRectangle = totalRectangle; subjectRectangle.Height = this.FontHeight;
Rectangle categoriesRectangle = totalRectangle; categoriesRectangle.Width = categoriesRectangleWidth; categoriesRectangle.Height = this.FontHeight; categoriesRectangle.Offset(10, this.FontHeight);
Rectangle reminderRectangle = totalRectangle; reminderRectangle.Height = this.FontHeight; reminderRectangle.Offset(0, this.FontHeight);
if (task.Categories.Count != 0) reminderRectangle.Offset(categoriesRectangleWidth + horizontalSpacing * 4, 0);
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);
if (catColors.Count != 0)
{
int catWidth = categoriesRectangle.Width / catColors.Count;
// int catWidth = categoriesRectangle.Width / 3; // TODO: This looks nicer, but more than 3 won't fit
Rectangle catRect = categoriesRectangle; catRect.Width = catWidth;
// catColors.ForEach(cc =>
catColors.Take(3).ToList().ForEach(cc =>
{
// e.Graphics.FillEllipse(new SolidBrush(cc), catRect);
e.Graphics.FillRectangle(new SolidBrush(cc), catRect);
// e.Graphics.FillRectangle(new SolidBrush(cc), catRect.Left, catRect.Top, catWidth, this.FontHeight);
catRect.Offset(catWidth, 0);
});
}
e.Graphics.DrawString(task.TaskSubject, new Font(this.Font, FontStyle.Bold), colorBrush, subjectRectangle, leftFormat);
if (task.Reminder.Year != Constants.NullYear)
{
e.Graphics.DrawImage(Properties.Resources.Alert_16xSM, reminderRectangle.Left, reminderRectangle.Top);
e.Graphics.DrawString(task.Reminder.ToString(), this.Font, colorBrush, reminderRectangle.Left + Properties.Resources.Alert_16xSM.Width + horizontalSpacing, reminderRectangle.Top, leftFormat);
}
else if (task.StartDate.Year != Constants.NullYear)
{
e.Graphics.DrawImage(Properties.Resources.CurrentRow_15x14, reminderRectangle.Left, reminderRectangle.Top);
e.Graphics.DrawString(task.StartDate.ToShortDateString(), this.Font, colorBrush, reminderRectangle.Left + Properties.Resources.CurrentRow_15x14.Width + horizontalSpacing, reminderRectangle.Top, leftFormat);
}
}
/// <summary>
/// Method to custom draw the list items
/// </summary>
@ -633,7 +804,6 @@ namespace Outlook2013TodoAddIn
catColors.Take(3).ToList().ForEach(cc =>
{
e.Graphics.FillEllipse(new SolidBrush(cc), catRect);
//e.Graphics.FillRectangle(new SolidBrush(cc), catRect);
catRect.Offset(catWidth, 0);
});

View File

@ -120,4 +120,7 @@
<metadata name="ctxMenuAppointments.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="ctxMenuTasks.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>225, 17</value>
</metadata>
</root>

View File

@ -47,6 +47,11 @@ namespace Outlook2013TodoAddIn
/// </summary>
public const int WS_EX_TOPMOST = 0x00000008;
/// <summary>
/// Outlook represents a null date with 1/1/4501
/// </summary>
public const int NullYear = 4501;
#endregion "Variables"
}
}

View File

@ -160,7 +160,6 @@
this.chkShowTasks.TabIndex = 16;
this.chkShowTasks.Text = "Show Tasks";
this.chkShowTasks.UseVisualStyleBackColor = true;
this.chkShowTasks.Visible = false;
//
// cboFirstDayOfWeek
//

View File

@ -120,7 +120,4 @@
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,84 @@
using Outlook = Microsoft.Office.Interop.Outlook;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Outlook;
namespace Outlook2013TodoAddIn
{
public class OLTaskItem
{
#region "Properties"
public bool ValidTaskItem { get; set; }
public string TaskType { get; set; }
public string TaskSubject { get; set; }
public DateTime StartDate { get; set; }
public DateTime Reminder { get; set; }
public DateTime DueDate { get; set; }
public string FolderName { get; set; }
public object OriginalItem { get; set; }
public List<string> Categories { get; set; }
#endregion "Properties"
#region "Methods"
/// <summary>
/// Default constructor
/// </summary>
/// <param name="item">Outlook item in the tasks folder</param>
public OLTaskItem(object item)
{
// TODO: Priority, status, % complete
this.ValidTaskItem = true;
this.OriginalItem = item;
this.Categories = new List<string>();
if (item is Outlook.MailItem)
{
Outlook.MailItem mail = item as Outlook.MailItem;
this.TaskType = "Mail";
this.TaskSubject = mail.TaskSubject;
this.StartDate = mail.TaskStartDate;
this.Reminder = mail.ReminderTime;
this.DueDate = mail.TaskDueDate;
MAPIFolder f = (MAPIFolder)mail.Parent;
this.FolderName = f.Name;
if (!String.IsNullOrEmpty(mail.Categories)) this.Categories.AddRange(mail.Categories.Split(new char[] { ',' }));
}
else if (item is Outlook.ContactItem)
{
Outlook.ContactItem contact = item as Outlook.ContactItem;
this.TaskType = "Contact";
this.TaskSubject = contact.TaskSubject;
this.StartDate = contact.TaskStartDate;
this.Reminder = contact.ReminderTime;
this.DueDate = contact.TaskDueDate;
MAPIFolder f = (MAPIFolder)contact.Parent;
this.FolderName = f.Name;
if (!String.IsNullOrEmpty(contact.Categories)) this.Categories.AddRange(contact.Categories.Split(new char[] { ',' }));
}
else if (item is Outlook.TaskItem)
{
Outlook.TaskItem task = item as Outlook.TaskItem;
this.TaskType = "Task";
this.TaskSubject = task.Subject;
this.StartDate = task.StartDate;
this.Reminder = task.ReminderTime;
this.DueDate = task.DueDate;
MAPIFolder f = (MAPIFolder)task.Parent;
this.FolderName = f.Name;
if (!String.IsNullOrEmpty(task.Categories)) this.Categories.AddRange(task.Categories.Split(new char[] { ',' }));
}
else
{
// Unhandled type
this.ValidTaskItem = false; // So we don't add to the collection later
}
this.Categories = this.Categories.Select(cat => cat.Trim()).Where(cat => !String.IsNullOrEmpty(cat)).ToList();
}
#endregion "Methods"
}
}

View File

@ -208,6 +208,7 @@
<Compile Include="Forms\NewMailAlert.Designer.cs">
<DependentUpon>NewMailAlert.cs</DependentUpon>
</Compile>
<Compile Include="OLTaskItem.cs" />
<Compile Include="OutlookHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
@ -288,7 +289,9 @@
<None Include="Images\Envelope.png" />
</ItemGroup>
<ItemGroup>
<Content Include="Images\Alert_16xSM.png" />
<Content Include="Images\buy-me-a-beer-small.png" />
<None Include="Images\CurrentRow_15x14.png" />
<Content Include="Images\gear.png" />
</ItemGroup>
<PropertyGroup>

View File

@ -60,6 +60,16 @@ namespace Outlook2013TodoAddIn.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Alert_16xSM {
get {
object obj = ResourceManager.GetObject("Alert_16xSM", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -70,6 +80,16 @@ namespace Outlook2013TodoAddIn.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap CurrentRow_15x14 {
get {
object obj = ResourceManager.GetObject("CurrentRow_15x14", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -136,4 +136,10 @@
<data name="todoIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Images\2012-11-20_1546.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Alert_16xSM" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Images\Alert_16xSM.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CurrentRow_15x14" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Images\CurrentRow_15x14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>