diff --git a/TestHarness/Form1.Designer.cs b/TestHarness/Form1.Designer.cs new file mode 100644 index 0000000..8d672c0 --- /dev/null +++ b/TestHarness/Form1.Designer.cs @@ -0,0 +1,125 @@ +namespace TestHarness +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose( bool disposing ) + { + if( disposing && ( components != null ) ) + { + components.Dispose(); + } + base.Dispose( disposing ); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.monthView1 = new WindowsFormsCalendar.MonthView(); + this.calendar1 = new WindowsFormsCalendar.Calendar(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.monthView1); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.AutoScroll = true; + this.splitContainer1.Panel2.AutoScrollMargin = new System.Drawing.Size(5, 5); + this.splitContainer1.Panel2.Controls.Add(this.calendar1); + this.splitContainer1.Size = new System.Drawing.Size(784, 562); + this.splitContainer1.SplitterDistance = 260; + this.splitContainer1.TabIndex = 0; + // + // monthView1 + // + this.monthView1.ArrowsColor = System.Drawing.SystemColors.Window; + this.monthView1.ArrowsSelectedColor = System.Drawing.Color.Gold; + this.monthView1.DayBackgroundColor = System.Drawing.Color.Empty; + this.monthView1.DayGrayedText = System.Drawing.SystemColors.GrayText; + this.monthView1.DaySelectedBackgroundColor = System.Drawing.SystemColors.Highlight; + this.monthView1.DaySelectedColor = System.Drawing.SystemColors.WindowText; + this.monthView1.DaySelectedTextColor = System.Drawing.SystemColors.HighlightText; + this.monthView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.monthView1.ItemPadding = new System.Windows.Forms.Padding(2); + this.monthView1.Location = new System.Drawing.Point(0, 0); + this.monthView1.MonthTitleColor = System.Drawing.SystemColors.ActiveCaption; + this.monthView1.MonthTitleColorInactive = System.Drawing.SystemColors.InactiveCaption; + this.monthView1.MonthTitleTextColor = System.Drawing.SystemColors.ActiveCaptionText; + this.monthView1.MonthTitleTextColorInactive = System.Drawing.SystemColors.InactiveCaptionText; + this.monthView1.Name = "monthView1"; + this.monthView1.SelectionMode = WindowsFormsCalendar.MonthViewSelection.Week; + this.monthView1.Size = new System.Drawing.Size(260, 562); + this.monthView1.TabIndex = 0; + this.monthView1.Text = "monthView1"; + this.monthView1.TodayBorderColor = System.Drawing.Color.Maroon; + this.monthView1.SelectionChanged += new System.EventHandler(this.monthView1_SelectionChanged); + // + // calendar1 + // + this.calendar1.AllowDrop = true; + this.calendar1.Dock = System.Windows.Forms.DockStyle.Fill; + this.calendar1.Font = new System.Drawing.Font("Segoe UI", 9F); + this.calendar1.ItemsBackgroundColor = System.Drawing.Color.Red; + this.calendar1.ItemsFont = new System.Drawing.Font("Monotype Corsiva", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.calendar1.ItemsForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(192))))); + this.calendar1.Location = new System.Drawing.Point(0, 0); + this.calendar1.Name = "calendar1"; + this.calendar1.Size = new System.Drawing.Size(520, 562); + this.calendar1.TabIndex = 0; + this.calendar1.Text = "calendar1"; + this.calendar1.LoadItems += new WindowsFormsCalendar.Calendar.CalendarLoadEventHandler(this.calendar1_LoadItems); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(784, 562); + this.Controls.Add(this.splitContainer1); + this.MinimumSize = new System.Drawing.Size(800, 600); + this.Name = "Form1"; + this.Text = "Test Harness"; + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private WindowsFormsCalendar.MonthView monthView1; + private WindowsFormsCalendar.Calendar calendar1; + private System.Windows.Forms.ToolTip toolTip1; + } +} + diff --git a/TestHarness/Form1.cs b/TestHarness/Form1.cs new file mode 100644 index 0000000..61ddad5 --- /dev/null +++ b/TestHarness/Form1.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +using WindowsFormsCalendar; + +namespace TestHarness +{ + public partial class Form1 : Form + { + #region Fields + + private List _items = new List(); + + #endregion + + /// + /// Initializes a new instance of the class. + /// + public Form1() + { + InitializeComponent(); + + CalendarItem item = new CalendarItem( this.calendar1, DateTime.Now, DateTime.Now, "TEST" ); + + _items.Add( item ); + + } + + #region Calendar Methods + + /// + /// Handles the LoadItems event of the calendar1 control. + /// + /// The source of the event. + /// The instance containing the event data. + private void calendar1_LoadItems( object sender, CalendarLoadEventArgs e ) + { + foreach( CalendarItem calendarItem in _items ) + { + if( this.calendar1.ViewIntersects( calendarItem ) ) + { + this.calendar1.Items.Add( calendarItem ); + } + } + } + + #endregion + + #region Month View Methods + + /// + /// Handles the SelectionChanged event of the monthView1 control. + /// + /// The source of the event. + /// The instance containing the event data. + private void monthView1_SelectionChanged( object sender, EventArgs e ) + { + this.calendar1.SetViewRange( this.monthView1.SelectionStart.Date, this.monthView1.SelectionEnd.Date); + } + + #endregion + + } +} \ No newline at end of file diff --git a/TestHarness/Form1.resx b/TestHarness/Form1.resx new file mode 100644 index 0000000..7734f57 --- /dev/null +++ b/TestHarness/Form1.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 54 + + \ No newline at end of file diff --git a/TestHarness/Program.cs b/TestHarness/Program.cs new file mode 100644 index 0000000..45daddf --- /dev/null +++ b/TestHarness/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace TestHarness +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault( false ); + Application.Run( new Form1() ); + } + } +} diff --git a/TestHarness/Properties/AssemblyInfo.cs b/TestHarness/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..20364db --- /dev/null +++ b/TestHarness/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "TestHarness" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "HP" )] +[assembly: AssemblyProduct( "TestHarness" )] +[assembly: AssemblyCopyright( "Copyright © HP 2012" )] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid( "734b7e11-5f67-4701-ae69-c7e558ebdb14" )] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/TestHarness/Properties/Resources.Designer.cs b/TestHarness/Properties/Resources.Designer.cs new file mode 100644 index 0000000..f77f918 --- /dev/null +++ b/TestHarness/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.269 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TestHarness.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0" )] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if( ( resourceMan == null ) ) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager( "TestHarness.Properties.Resources", typeof( Resources ).Assembly ); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/TestHarness/Properties/Resources.resx b/TestHarness/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/TestHarness/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TestHarness/Properties/Settings.Designer.cs b/TestHarness/Properties/Settings.Designer.cs new file mode 100644 index 0000000..8e1c388 --- /dev/null +++ b/TestHarness/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.269 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace TestHarness.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0" )] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ( (Settings)( global::System.Configuration.ApplicationSettingsBase.Synchronized( new Settings() ) ) ); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/TestHarness/Properties/Settings.settings b/TestHarness/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/TestHarness/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/TestHarness/TestHarness.csproj b/TestHarness/TestHarness.csproj new file mode 100644 index 0000000..d048f0d --- /dev/null +++ b/TestHarness/TestHarness.csproj @@ -0,0 +1,93 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {C3A1985B-E396-4125-A176-61C2AEE5A41F} + WinExe + Properties + TestHarness + TestHarness + v4.0 + Client + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {25649F08-3046-4891-ADB8-7EA787B57063} + WindowsFormsCalendar + + + + + \ No newline at end of file diff --git a/WindowsFormsCalendar.sln b/WindowsFormsCalendar.sln new file mode 100644 index 0000000..d17a878 --- /dev/null +++ b/WindowsFormsCalendar.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsCalendar", "WindowsFormsCalendar\WindowsFormsCalendar.csproj", "{25649F08-3046-4891-ADB8-7EA787B57063}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestHarness", "TestHarness\TestHarness.csproj", "{C3A1985B-E396-4125-A176-61C2AEE5A41F}" + ProjectSection(ProjectDependencies) = postProject + {25649F08-3046-4891-ADB8-7EA787B57063} = {25649F08-3046-4891-ADB8-7EA787B57063} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9A09091C-9031-48EA-8EB5-C40716E28351}" + ProjectSection(SolutionItems) = preProject + WindowsFormsCalendar\GPL v3.txt = WindowsFormsCalendar\GPL v3.txt + WindowsFormsCalendar\ReadMe.txt = WindowsFormsCalendar\ReadMe.txt + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {25649F08-3046-4891-ADB8-7EA787B57063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Debug|x86.ActiveCfg = Debug|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Release|Any CPU.Build.0 = Release|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {25649F08-3046-4891-ADB8-7EA787B57063}.Release|x86.ActiveCfg = Release|Any CPU + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Debug|Any CPU.ActiveCfg = Debug|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Debug|x86.ActiveCfg = Debug|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Debug|x86.Build.0 = Debug|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|Any CPU.ActiveCfg = Release|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|Any CPU.Build.0 = Release|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|Mixed Platforms.Build.0 = Release|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|x86.ActiveCfg = Release|x86 + {C3A1985B-E396-4125-A176-61C2AEE5A41F}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WindowsFormsCalendar/CalendarColorTable.cs b/WindowsFormsCalendar/CalendarColorTable.cs new file mode 100644 index 0000000..dbb91ab --- /dev/null +++ b/WindowsFormsCalendar/CalendarColorTable.cs @@ -0,0 +1,271 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Provides color information of calendar graphical elements + /// + public class CalendarColorTable + { + #region Static + + /// + /// Returns the result of combining the specified colors + /// + /// First color to combine + /// Second olor to combine + /// Average of both colors + public static Color Combine(Color c1, Color c2) + { + return Color.FromArgb( + (c1.R + c2.R) / 2, + (c1.G + c2.G) / 2, + (c1.B + c2.B) / 2 + ); + } + + /// + /// Converts the hex formatted color to a + /// + /// + /// + public static Color FromHex(string hex) + { + if (hex.StartsWith("#")) + hex = hex.Substring(1); + + if (hex.Length != 6) throw new Exception("Color not valid"); + + return Color.FromArgb( + int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber), + int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber), + int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber)); + } + + #endregion + + #region Colors + + /// + /// Background color of calendar + /// + public Color Background = SystemColors.Control; + + /// + /// Background color of days in even months + /// + public Color DayBackgroundEven = SystemColors.Control; + + /// + /// Background color of days in odd months + /// + public Color DayBackgroundOdd = SystemColors.ControlLight; + + /// + /// Background color of selected days + /// + public Color DayBackgroundSelected = SystemColors.Highlight; + + /// + /// Border of + /// + public Color DayBorder = SystemColors.ControlDark; + + /// + /// Background color of day headers. + /// + public Color DayHeaderBackground = Combine(SystemColors.ControlDark, SystemColors.Control); + + /// + /// Color of text of day headers + /// + public Color DayHeaderText = SystemColors.GrayText; + + /// + /// Color of secondary text in headers + /// + public Color DayHeaderSecondaryText = SystemColors.GrayText; + + /// + /// Color of border of the top part of the days + /// + /// + /// The DayTop is the zone of the calendar where items that lasts all or more are placed. + /// + public Color DayTopBorder = SystemColors.ControlDark; + + /// + /// Color of border of the top parth of the days when selected + /// + /// + /// The DayTop is the zone of the calendar where items that lasts all or more are placed. + /// + public Color DayTopSelectedBorder = SystemColors.ControlDark; + + /// + /// Background color of day tops. + /// + /// + /// The DayTop is the zone of the calendar where items that lasts all or more are placed. + /// + public Color DayTopBackground = SystemColors.ControlLight; + + /// + /// Background color of selected day tops. + /// + /// + /// The DayTop is the zone of the calendar where items that lasts all or more are placed. + /// + public Color DayTopSelectedBackground = SystemColors.Highlight; + + /// + /// Color of items borders + /// + public Color ItemBorder = SystemColors.ControlText; + + /// + /// Background color of items + /// + public Color ItemBackground = SystemColors.Window; + + /// + /// Forecolor of items + /// + public Color ItemText = SystemColors.WindowText; + + /// + /// Color of secondary text on items (Dates and times) + /// + public Color ItemSecondaryText = SystemColors.GrayText; + + /// + /// Color of items shadow + /// + public Color ItemShadow = Color.FromArgb(50, Color.Black); + + /// + /// Color of items selected border + /// + public Color ItemSelectedBorder = SystemColors.Highlight; + + /// + /// Background color of selected items + /// + public Color ItemSelectedBackground = Combine(SystemColors.Highlight, SystemColors.HighlightText); + + /// + /// Forecolor of selected items + /// + public Color ItemSelectedText = SystemColors.WindowText; + + /// + /// Background color of week headers + /// + public Color WeekHeaderBackground = Combine(SystemColors.ControlDark, SystemColors.Control); + + /// + /// Border color of week headers + /// + public Color WeekHeaderBorder = SystemColors.ControlDark; + + /// + /// Forecolor of week headers + /// + public Color WeekHeaderText = SystemColors.ControlText; + + /// + /// Forecolor of day names + /// + public Color WeekDayName = SystemColors.ControlText; + + /// + /// Border color of today day + /// + public Color TodayBorder = Color.Orange; + + /// + /// Background color of today's DayTop + /// + public Color TodayTopBackground = Color.Orange; + + /// + /// Color of lines in timescale + /// + public Color TimeScaleLine = SystemColors.ControlDark; + + /// + /// Color of text representing hours on the timescale + /// + public Color TimeScaleHours = SystemColors.GrayText; + + /// + /// Color of text representing minutes on the timescale + /// + public Color TimeScaleMinutes = SystemColors.GrayText; + + /// + /// Background color of time units + /// + public Color TimeUnitBackground = SystemColors.Control; + + /// + /// Background color of highlighted time units + /// + public Color TimeUnitHighlightedBackground = Combine(SystemColors.Control, SystemColors.ControlLightLight); + + /// + /// Background color of selected time units + /// + public Color TimeUnitSelectedBackground = SystemColors.Highlight; + + /// + /// Color of light border of time units + /// + public Color TimeUnitBorderLight = SystemColors.ControlDark; + + /// + /// Color of dark border of time units + /// + public Color TimeUnitBorderDark = SystemColors.ControlDarkDark; + + /// + /// Border color of the overflow indicators + /// + public Color DayOverflowBorder = Color.White; + + /// + /// Background color of the overflow indicators + /// + public Color DayOverflowBackground = SystemColors.ControlLight; + + /// + /// Background color of selected overflow indicators + /// + public Color DayOverflowSelectedBackground = Color.Orange; + + #endregion + } +} + diff --git a/WindowsFormsCalendar/CalendarDay.cs b/WindowsFormsCalendar/CalendarDay.cs new file mode 100644 index 0000000..663fc22 --- /dev/null +++ b/WindowsFormsCalendar/CalendarDay.cs @@ -0,0 +1,335 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a day present on the control's view. + /// + public class CalendarDay + : CalendarSelectableElement + { + #region Static + + private Size overflowSize = new Size(16, 16); + private Padding overflowPadding = new Padding(5); + + #endregion + + #region Events + + #endregion + + #region Fields + private List _containedItems; + private Calendar _calendar; + private DateTime _date; + private CalendarDayTop _dayTop; + private int _index; + private bool _overflowStart; + private bool _overflowEnd; + private bool _overflowStartSelected; + private bool _overlowEndSelected; + private CalendarTimeScaleUnit[] _timeUnits; + #endregion + + #region Properties + + /// + /// Gets a list of items contained on the day + /// + internal List ContainedItems + { + get { return _containedItems; } + } + + /// + /// Gets the DayTop of the day, the place where multi-day and all-day items are placed + /// + public CalendarDayTop DayTop + { + get { return _dayTop; } + } + + /// + /// Gets the bounds of the body of the day (where time-based CalendarItems are placed) + /// + public Rectangle BodyBounds + { + get + { + return Rectangle.FromLTRB(Bounds.Left, DayTop.Bounds.Bottom, Bounds.Right, Bounds.Bottom); + } + } + + /// + /// Gets the date this day represents + /// + public override DateTime Date + { + get { return _date; } + } + + /// + /// Gets the bounds of the header of the day + /// + public Rectangle HeaderBounds + { + get + { + return new Rectangle(Bounds.Left, Bounds.Top, Bounds.Width, Calendar.Renderer.DayHeaderHeight); + } + } + + /// + /// Gets the index of this day on the calendar + /// + public int Index + { + get { return _index; } + } + + /// + /// Gets a value indicating if the day is specified on the view (See remarks). + /// + /// + /// A day may not be specified on the view, but still present to make up a square calendar. + /// This days should be drawn in a way that indicates it's necessary but unrequested presence. + /// + public bool SpecifiedOnView + { + get + { + return Date.CompareTo(Calendar.ViewStart) >= 0 && Date.CompareTo(Calendar.ViewEnd) <= 0; + } + } + + /// + /// Gets the time units contained on the day + /// + public CalendarTimeScaleUnit[] TimeUnits + { + get { return _timeUnits; } + } + + /// + /// /// + /// Gets a value indicating if the day contains items not shown through the start of the day + /// + /// + public bool OverflowStart + { + get { return _overflowStart; } + } + + /// + /// Gets the bounds of the indicator + /// + public virtual Rectangle OverflowStartBounds + { + get { return new Rectangle(new Point(Bounds.Right - overflowPadding.Right - overflowSize.Width, Bounds.Top + overflowPadding.Top), overflowSize); } + } + + /// + /// Gets a value indicating if the indicator is currently selected + /// + /// + /// This value set to true when user hovers the mouse on the area + /// + public bool OverflowStartSelected + { + get { return _overflowStartSelected; } + } + + /// + /// Gets a value indicating if the day contains items not shown through the end of the day + /// + public bool OverflowEnd + { + get { return _overflowEnd; } + } + + /// + /// Gets the bounds of the indicator + /// + public virtual Rectangle OverflowEndBounds + { + get { return new Rectangle(new Point(Bounds.Right - overflowPadding.Right - overflowSize.Width, Bounds.Bottom - overflowPadding.Bottom - overflowSize.Height), overflowSize); } + } + + /// + /// Gets a value indicating if the indicator is currently selected + /// + /// + /// This value set to true when user hovers the mouse on the area + /// + public bool OverflowEndSelected + { + get { return _overlowEndSelected; } + } + + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + /// The date. + /// The index. + internal CalendarDay(Calendar calendar, DateTime date, int index) + : base(calendar) + { + _containedItems = new List(); + _calendar = calendar; + _dayTop = new CalendarDayTop(this); + _date = date; + _index = index; + + UpdateUnits(); + } + + #region Public Methods + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return Date.ToShortDateString(); + } + + #endregion + + #region Private Methods + + /// + /// Adds an item to the list if not in yet + /// + /// + internal void AddContainedItem(CalendarItem item) + { + if (!ContainedItems.Contains(item)) + { + ContainedItems.Add(item); + } + } + + /// + /// Sets the value of he property + /// + /// Value of the property + internal void SetOverflowEnd(bool overflow) + { + _overflowEnd = overflow; + } + + /// + /// Sets the value of the property + /// + /// Value to pass to the property + internal void SetOverflowEndSelected(bool selected) + { + _overlowEndSelected= selected; + } + + /// + /// Sets the value of he property + /// + /// Value of the property + internal void SetOverflowStart(bool overflow) + { + _overflowStart = overflow; + } + + /// + /// Sets the value of the property + /// + /// Value to pass to the property + internal void SetOverflowStartSelected(bool selected) + { + _overflowStartSelected = selected; + } + + /// + /// Updates the value of property + /// + internal void UpdateUnits() + { + int factor = 0; + + switch (Calendar.TimeScale) + { + case CalendarTimeScale.SixtyMinutes: factor = 1; break; + case CalendarTimeScale.ThirtyMinutes: factor = 2; break; + case CalendarTimeScale.FifteenMinutes: factor = 4; break; + case CalendarTimeScale.TenMinutes: factor = 6; break; + case CalendarTimeScale.SixMinutes: factor = 10; break; + case CalendarTimeScale.FiveMinutes: factor = 12; break; + default: throw new NotImplementedException("TimeScale not supported"); + } + + _timeUnits = new CalendarTimeScaleUnit[24 * factor]; + + int hourSum = 0; + int minSum = 0; + + for (int i = 0; i < _timeUnits.Length; i++) + { + _timeUnits[i] = new CalendarTimeScaleUnit(this, i, hourSum, minSum); + + minSum += 60 / factor; + + if (minSum >= 60) + { + minSum = 0; + hourSum++; + } + } + + UpdateHighlights(); + } + + /// + /// Updates the highlights of the units + /// + internal void UpdateHighlights() + { + if (TimeUnits == null) + return; + + for (int i = 0; i < TimeUnits.Length; i++) + { + TimeUnits[i].SetHighlighted(TimeUnits[i].CheckHighlighted()); + } + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/CalendarDayTop.cs b/WindowsFormsCalendar/CalendarDayTop.cs new file mode 100644 index 0000000..97305e0 --- /dev/null +++ b/WindowsFormsCalendar/CalendarDayTop.cs @@ -0,0 +1,106 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Represents the top area of a day, where multiday and all day items are stored + /// + public class CalendarDayTop + : CalendarSelectableElement + { + #region Events + + #endregion + + #region Fields + private CalendarDay _day; + private List _passingItems; + #endregion + + #region Properties + + /// + /// Gets the date. + /// + public override DateTime Date + { + get + { + return new DateTime(Day.Date.Year, Day.Date.Month, Day.Date.Day); + } + } + + /// + /// Gets the Day of this DayTop + /// + public CalendarDay Day + { + get { return _day; } + } + + + /// + /// Gets the list of items passing on this daytop + /// + public List PassingItems + { + get { return _passingItems; } + } + + #endregion + + /// + /// Creates a new DayTop for the specified day + /// + /// + public CalendarDayTop(CalendarDay day) + : base(day.Calendar) + { + _day = day; + _passingItems = new List(); + } + + #region Public Methods + + #endregion + + #region Private Methods + + /// + /// Adds the passing item. + /// + /// The item. + internal void AddPassingItem(CalendarItem item) + { + if (!PassingItems.Contains(item)) + { + PassingItems.Add(item); + } + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/CalendarHighlightRange.cs b/WindowsFormsCalendar/CalendarHighlightRange.cs new file mode 100644 index 0000000..8401b9c --- /dev/null +++ b/WindowsFormsCalendar/CalendarHighlightRange.cs @@ -0,0 +1,132 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a range of time that is highlighted as work-time + /// + public class CalendarHighlightRange + { + #region Events + + #endregion + + #region Fields + private Calendar _calendar; + private DayOfWeek _dayOfWeek; + private TimeSpan _startTime; + private TimeSpan _endTime; + #endregion + + #region Properties + + /// + /// Gets the calendar that this range is assigned to. (If any) + /// + public Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets or sets the day of the week for this range + /// + public DayOfWeek DayOfWeek + { + get { return _dayOfWeek; } + set { _dayOfWeek = value; Update(); } + } + + /// + /// Gets or sets the start time of the range + /// + public TimeSpan StartTime + { + get { return _startTime; } + set { _startTime = value; Update(); } + } + + /// + /// Gets or sets the end time of the range + /// + public TimeSpan EndTime + { + get { return _endTime; } + set { _endTime = value; Update(); } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + public CalendarHighlightRange() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// The day. + /// The start time. + /// The end time. + public CalendarHighlightRange( DayOfWeek day, TimeSpan startTime, TimeSpan endTime ) + : this() + { + _dayOfWeek = day; + _startTime = startTime; + _endTime = endTime; + } + + #region Public Methods + + #endregion + + #region Private Methods + + /// + /// Tells the calendar to update the highligts + /// + private void Update() + { + if (Calendar != null) + { + Calendar.UpdateHighlights(); + } + } + + /// + /// Sets the value of the property + /// + /// Calendar that this range belongs to + internal void SetCalendar(Calendar calendar) + { + _calendar = calendar; + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/CalendarItem.cs b/WindowsFormsCalendar/CalendarItem.cs new file mode 100644 index 0000000..5b91cf7 --- /dev/null +++ b/WindowsFormsCalendar/CalendarItem.cs @@ -0,0 +1,891 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace WindowsFormsCalendar +{ + /// + /// Represents an item of the calendar with a date and timespan + /// + /// + /// CalendarItem provides a graphical representation of tasks within a date range. + /// + public class CalendarItem + : CalendarSelectableElement + { + #region Static + + /// + /// Compares the bounds. + /// + /// The r1. + /// The r2. + /// + private static int CompareBounds( Rectangle r1, Rectangle r2 ) + { + return r1.Top.CompareTo( r2.Top ); + } + + #endregion + + #region Events + + #endregion + + #region Fields + + private Rectangle[] _additionalBounds; + + private Color _backgroundColor; + private Color _backgroundColorLighter; + private Color _borderColor; + + private DateTime _startDate; + private DateTime _endDate; + + private Color _foreColor; + + private bool _locked; + + private TimeSpan _duration; + + private Image _image; + + private CalendarItemImageAlign _imageAlign; + + private bool _isDragging; + private bool _isEditing; + private bool _isResizingStartDate; + private bool _isResizingEndDate; + private bool _isOnView; + + private int _minuteStartTop; + private int _minuteEndTop; + + private HatchStyle _pattern; + + private Color _patternColor; + + private List _unitsPassing; + + private List _topsPassing; + + private object _tag; + + private string _text; + + private Font _font; + + #endregion + + #region Properties + + /// + /// Gets or sets an array of rectangles containing bounds additional to Bounds property. + /// + /// + /// Items may contain additional bounds because of several graphical occourences, mostly when in + /// mode, due to the duration of the item; e.g. when an all day item lasts several weeks, + /// one rectangle for week must be drawn to indicate the presence of the item. + /// + public virtual Rectangle[] AditionalBounds + { + get { return _additionalBounds; } + set { _additionalBounds = value; } + } + + /// + /// Gets or sets the a background color for the object. If Color.Empty, renderer default's will be used. + /// + public Color BackgroundColor + { + get { return _backgroundColor; } + set { _backgroundColor = value; } + } + + /// + /// Gets or sets the lighter background color of the item + /// + public Color BackgroundColorLighter + { + get { return _backgroundColorLighter; } + set { _backgroundColorLighter = value; } + } + + /// + /// Gets or sets the bordercolor of the item. If Color.Empty, renderer default's will be used. + /// + public Color BorderColor + { + get { return _borderColor; } + set { _borderColor = value; } + } + + /// + /// Gets the StartDate of the item. Implemented + /// + public override DateTime Date + { + get + { + return StartDate; + } + } + + /// + /// Gets the day on the where this item ends + /// + /// + /// This day is not necesarily the day corresponding to the day on , + /// since this date can be out of the range of the current view. + /// If Item is not on view date range this property will return null. + /// + public CalendarDay DayEnd + { + get + { + if( !IsOnViewDateRange ) + { + return null; + } + else if( IsOpenEnd ) + { + return Calendar.Days[Calendar.Days.Length - 1]; + } + else + { + return Calendar.FindDay( EndDate ); + } + } + } + + /// + /// Gets the day on the where this item starts + /// + /// + /// This day is not necesarily the day corresponding to the day on , + /// since start date can be out of the range of the current view. + /// If Item is not on view date range this property will return null. + /// + public CalendarDay DayStart + { + get + { + if( !IsOnViewDateRange ) + { + return null; + } + else if( IsOpenStart ) + { + return Calendar.Days[0]; + } + else + { + return Calendar.FindDay( StartDate ); + } + } + } + + /// + /// Gets the duration of the item + /// + public TimeSpan Duration + { + get + { + if( _duration.TotalMinutes == 0 ) + { + _duration = EndDate.Subtract( StartDate ); + } + return _duration; + } + } + + /// + /// Gets or sets the end time of the item + /// + public DateTime EndDate + { + get { return _endDate; } + set + { + _endDate = value; + _duration = new TimeSpan( 0, 0, 0 ); + ClearPassings(); + } + } + + /// + /// Gets the text of the end date + /// + public virtual string EndDateText + { + get + { + string date = string.Empty; + string time = string.Empty; + + if( IsOpenEnd ) + { + date = EndDate.ToString( Calendar.ItemsDateFormat ); + } + + if( ShowEndTime && !EndDate.TimeOfDay.Equals( new TimeSpan( 23, 59, 59 ) ) ) + { + time = EndDate.ToString( Calendar.ItemsTimeFormat ); + } + + return string.Format( "{0} {1}", date, time ).Trim(); + } + } + + /// + /// Gets or sets the forecolor of the item. If Color.Empty, renderer default's will be used. + /// + public Color ForeColor + { + get { return _foreColor; } + set + { + _foreColor = value; + } + } + + /// + /// Gets or sets an image for the item + /// + public Image Image + { + get { return _image; } + set { _image = value; } + } + + /// + /// Gets or sets the alignment of the image relative to the text + /// + public CalendarItemImageAlign ImageAlign + { + get { return _imageAlign; } + set { _imageAlign = value; } + } + + /// + /// Gets a value indicating if the item is being dragged + /// + public bool IsDragging + { + get { return _isDragging; } + } + + /// + /// Gets a value indicating if the item is currently being edited by the user + /// + public bool IsEditing + { + get { return _isEditing; } + } + + /// + /// Gets a value indicating if the item goes on the DayTop area of the + /// + public bool IsOnDayTop + { + get + { + return StartDate.Day != EndDate.AddSeconds( 1 ).Day; + } + } + + /// + /// Gets a value indicating if the item is currently on view. + /// + /// + /// The item may not be on view because of scrolling + /// + public bool IsOnView + { + get { return _isOnView; } + } + + /// + /// Gets a value indicating if the item is on the range specified by and + /// + public bool IsOnViewDateRange + { + get + { + //Checks for an intersection of item's dates against calendar dates + DateTime fd = Calendar.Days[0].Date; + DateTime ld = Calendar.Days[Calendar.Days.Length - 1].Date.Add( new TimeSpan( 23, 59, 59 ) ); + DateTime sd = StartDate; + DateTime ed = EndDate; + return sd < ld && fd < ed; + } + } + + /// + /// Gets a value indicating if the item's is before the date. + /// + public bool IsOpenStart + { + get + { + return StartDate.CompareTo( Calendar.Days[0].Date ) < 0; + } + } + + /// + /// Gets a value indicating if the item's is aftter the date. + /// + public bool IsOpenEnd + { + get + { + return EndDate.CompareTo( Calendar.Days[Calendar.Days.Length - 1].Date.Add( new TimeSpan( 23, 59, 59 ) ) ) > 0; + } + } + + /// + /// Gets a value indicating if item is being resized by the + /// + public bool IsResizingStartDate + { + get { return _isResizingStartDate; } + } + + /// + /// Gets a value indicating if item is being resized by the + /// + public bool IsResizingEndDate + { + get { return _isResizingEndDate; } + } + + /// + /// Gets a value indicating if this item is locked. + /// + /// + /// When an item is locked, the user can't drag it or change it's text + /// + public bool Locked + { + get { return _locked; } + set { _locked = value; } + } + + /// + /// Gets the top correspoinding to the ending minute + /// + public int MinuteEndTop + { + get { return _minuteEndTop; } + } + + /// + /// Gets the top corresponding to the starting minute + /// + public int MinuteStartTop + { + get { return _minuteStartTop; } + } + + /// + /// Gets or sets the units that this item passes by + /// + internal List UnitsPassing + { + get { return _unitsPassing; } + set { _unitsPassing = value; } + } + + /// + /// Gets or sets the pattern style to use in the background of item. + /// + public HatchStyle Pattern + { + get { return _pattern; } + set { _pattern = value; } + } + + /// + /// Gets or sets the pattern's color + /// + public Color PatternColor + { + get { return _patternColor; } + set { _patternColor = value; } + } + + /// + /// Gets the list of DayTops that this item passes thru + /// + internal List TopsPassing + { + get { return _topsPassing; } + } + + /// + /// Gets a value indicating if the item should show the time of the + /// + public bool ShowStartTime + { + get + { + return IsOpenStart || ( ( this.IsOnDayTop || Calendar.DaysMode == CalendarDaysMode.Short ) && !StartDate.TimeOfDay.Equals( new TimeSpan( 0, 0, 0 ) ) ); + } + } + + /// + /// Gets a value indicating if the item should show the time of the + /// + public virtual bool ShowEndTime + { + get + { + return ( IsOpenEnd || + ( ( this.IsOnDayTop || Calendar.DaysMode == CalendarDaysMode.Short ) && !EndDate.TimeOfDay.Equals( new TimeSpan( 23, 59, 59 ) ) ) ) && + !( Calendar.DaysMode == CalendarDaysMode.Short && StartDate.Date == EndDate.Date ); + } + } + + /// + /// Gets the text of the start date + /// + public virtual string StartDateText + { + get + { + string date = string.Empty; + string time = string.Empty; + + if( IsOpenStart ) + { + date = StartDate.ToString( Calendar.ItemsDateFormat ); + } + + if( ShowStartTime && !StartDate.TimeOfDay.Equals( new TimeSpan( 0, 0, 0 ) ) ) + { + time = StartDate.ToString( Calendar.ItemsTimeFormat ); + } + + return string.Format( "{0} {1}", date, time ).Trim(); + } + } + + /// + /// Gets or sets the start time of the item + /// + public virtual DateTime StartDate + { + get { return _startDate; } + set + { + _startDate = value; + _duration = new TimeSpan( 0, 0, 0 ); + ClearPassings(); + } + } + + /// + /// Gets or sets a tag object for the item + /// + public object Tag + { + get { return _tag; } + set { _tag = value; } + } + + /// + /// Gets or sets the text of the item + /// + public virtual string Text + { + get { return _text; } + set { _text = value; } + } + + /// + /// Gets or sets the font. + /// + /// + /// The font. + /// + public Font Font + { + get { return _font; } + set { _font = value; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// + public CalendarItem( Calendar calendar ) + : base( calendar ) + { + _unitsPassing = new List(); + _topsPassing = new List(); + _backgroundColor = Color.Empty; + _borderColor = Color.Empty; + _foreColor = Color.Empty; + _backgroundColorLighter = Color.Empty; + _imageAlign = CalendarItemImageAlign.West; + _font = calendar.ItemsFont; + _backgroundColor = calendar.ItemsBackgroundColor; + _foreColor = calendar.ItemsForeColor; + + } + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + /// The start date. + /// The end date. + /// The text. + public CalendarItem( Calendar calendar, DateTime startDate, DateTime endDate, string text ) + : this( calendar ) + { + StartDate = startDate; + EndDate = endDate; + Text = text; + } + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + /// The start date. + /// The duration. + /// The text. + public CalendarItem( Calendar calendar, DateTime startDate, TimeSpan duration, string text ) + : this( calendar, startDate, startDate.Add( duration ), text ) + { } + + #region Public Methods + + /// + /// Applies color to background, border, and forecolor, from the specified color. + /// + /// The color. + public void ApplyColor( Color color ) + { + BackgroundColor = color; + BackgroundColorLighter = Color.FromArgb( + color.R + ( 255 - color.R ) / 2 + ( 255 - color.R ) / 3, + color.G + ( 255 - color.G ) / 2 + ( 255 - color.G ) / 3, + color.B + ( 255 - color.B ) / 2 + ( 255 - color.B ) / 3 ); + + BorderColor = Color.FromArgb( + Convert.ToInt32( Convert.ToSingle( color.R ) * .8f ), + Convert.ToInt32( Convert.ToSingle( color.G ) * .8f ), + Convert.ToInt32( Convert.ToSingle( color.B ) * .8f ) ); + + int avg = ( color.R + color.G + color.B ) / 3; + + if( avg > 255 / 2 ) + { + ForeColor = Color.Black; + } + else + { + ForeColor = Color.White; + } + } + + /// + /// Gets all the bounds related to the item. + /// + /// + /// + /// Items that are broken on two or more weeks may have more than one rectangle bounds. + /// + public IEnumerable GetAllBounds() + { + List r = new List( AditionalBounds == null ? new Rectangle[] { } : AditionalBounds ); + r.Add( Bounds ); + + r.Sort( CompareBounds ); + + return r; + } + + /// + /// Removes all specific coloring for the item. + /// + public void RemoveColors() + { + BackgroundColor = Color.Empty; + ForeColor = Color.Empty; + BorderColor = Color.Empty; + } + + /// + /// Gets a value indicating if the specified point is in a resize zone of + /// + /// The point. + /// + public bool ResizeStartDateZone( Point point ) + { + int margin = 4; + + List rects = new List( GetAllBounds() ); + Rectangle first = rects[0]; + Rectangle last = rects[rects.Count - 1]; + + if( IsOnDayTop || Calendar.DaysMode == CalendarDaysMode.Short ) + { + return Rectangle.FromLTRB( first.Left, first.Top, first.Left + margin, first.Bottom ).Contains( point ); + } + else + { + return Rectangle.FromLTRB( first.Left, first.Top, first.Right, first.Top + margin ).Contains( point ); + } + } + + /// + /// Gets a value indicating if the specified point is in a resize zone of + /// + /// The point. + /// + public bool ResizeEndDateZone( Point point ) + { + int margin = 4; + + List rects = new List( GetAllBounds() ); + Rectangle first = rects[0]; + Rectangle last = rects[rects.Count - 1]; + + if( IsOnDayTop || Calendar.DaysMode == CalendarDaysMode.Short ) + { + return Rectangle.FromLTRB( last.Right - margin, last.Top, last.Right, last.Bottom ).Contains( point ); + } + else + { + return Rectangle.FromLTRB( last.Left, last.Bottom - margin, last.Right, last.Bottom ).Contains( point ); + } + } + + /// + /// Sets the bounds of the item + /// + /// The rectangle. + public new void SetBounds( Rectangle rectangle ) + { + base.SetBounds( rectangle ); + } + + /// + /// Indicates if the time of the item intersects with the provided time + /// + /// The start time. + /// The end time. + /// + public bool IntersectsWith( TimeSpan startTime, TimeSpan endTime ) + { + Rectangle r1 = Rectangle.FromLTRB( 0, Convert.ToInt32( StartDate.TimeOfDay.TotalMinutes ), 5, Convert.ToInt32( EndDate.TimeOfDay.TotalMinutes ) ); + Rectangle r2 = Rectangle.FromLTRB( 0, Convert.ToInt32( startTime.TotalMinutes ), 5, Convert.ToInt32( endTime.TotalMinutes - 1 ) ); + return r1.IntersectsWith( r2 ); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format( "{0} - {1}", StartDate.ToShortTimeString(), EndDate.ToShortTimeString() ); + } + + #endregion + + #region Private Methods + + /// + /// Adds bounds for the item + /// + /// + internal void AddBounds( Rectangle r ) + { + if( r.IsEmpty ) throw new ArgumentException( "r can't be empty" ); + + if( Bounds.IsEmpty ) + { + SetBounds( r ); + } + else + { + List rs = new List( AditionalBounds == null ? new Rectangle[] { } : AditionalBounds ); + rs.Add( r ); + AditionalBounds = rs.ToArray(); + } + } + + /// + /// Adds the specified unit as a passing unit + /// + /// + internal void AddUnitPassing( CalendarTimeScaleUnit calendarTimeScaleUnit ) + { + if( !UnitsPassing.Contains( calendarTimeScaleUnit ) ) + { + UnitsPassing.Add( calendarTimeScaleUnit ); + } + } + + /// + /// Adds the specified as a passing one + /// + /// + internal void AddTopPassing( CalendarDayTop top ) + { + if( !TopsPassing.Contains( top ) ) + { + TopsPassing.Add( top ); + } + } + + /// + /// Clears the item's existance off passing units and tops + /// + internal void ClearPassings() + { + foreach( CalendarTimeScaleUnit unit in UnitsPassing ) + { + unit.ClearItemExistance( this ); + } + + UnitsPassing.Clear(); + TopsPassing.Clear(); + } + + /// + /// Clears all bounds of the item + /// + internal void ClearBounds() + { + SetBounds( Rectangle.Empty ); + AditionalBounds = new Rectangle[] { }; + SetMinuteStartTop( 0 ); + SetMinuteEndTop( 0 ); + } + + /// + /// It pushes the left and the right to the center of the item + /// to visually indicate start and end time + /// + internal void FirstAndLastRectangleGapping() + { + if( !IsOpenStart ) + SetBounds( Rectangle.FromLTRB( Bounds.Left + Calendar.Renderer.ItemsPadding, + Bounds.Top, Bounds.Right, Bounds.Bottom ) ); + + if( !IsOpenEnd ) + { + if( AditionalBounds != null && AditionalBounds.Length > 0 ) + { + Rectangle r = AditionalBounds[AditionalBounds.Length - 1]; + AditionalBounds[AditionalBounds.Length - 1] = Rectangle.FromLTRB( + r.Left, r.Top, r.Right - Calendar.Renderer.ItemsPadding, r.Bottom ); + } + else + { + Rectangle r = Bounds; + SetBounds( Rectangle.FromLTRB( + r.Left, r.Top, r.Right - Calendar.Renderer.ItemsPadding, r.Bottom ) ); + } + } + } + + /// + /// Sets the value of the IsDragging property + /// + /// Value indicating if the item is currently being dragged + internal void SetIsDragging( bool dragging ) + { + _isDragging = dragging; + } + + /// + /// Sets the value of the property + /// + /// Value indicating if user is currently being editing + internal void SetIsEditing( bool editing ) + { + _isEditing = editing; + } + + /// + /// Sets the value of the property + /// + /// Indicates if the item is currently on view + internal void SetIsOnView( bool onView ) + { + _isOnView = onView; + } + + /// + /// Sets the value of the property + /// + /// + internal void SetIsResizingStartDate( bool resizing ) + { + _isResizingStartDate = resizing; + } + + /// + /// Sets the value of the property + /// + /// + internal void SetIsResizingEndDate( bool resizing ) + { + _isResizingEndDate = resizing; + } + + /// + /// Sets the value of the property + /// + /// + internal void SetMinuteStartTop( int top ) + { + _minuteStartTop = top; + } + + /// + /// Sets the value of the property + /// + /// + internal void SetMinuteEndTop( int top ) + { + _minuteEndTop = top; + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/CalendarItemCollection.cs b/WindowsFormsCalendar/CalendarItemCollection.cs new file mode 100644 index 0000000..49d11d5 --- /dev/null +++ b/WindowsFormsCalendar/CalendarItemCollection.cs @@ -0,0 +1,176 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// A collection of calendar items + /// + public class CalendarItemCollection + : List + { + #region Events + + #endregion + + #region Fields + private Calendar _calendar; + #endregion + + #region Properties + + /// + /// Gets the calendar. + /// + public Calendar Calendar + { + get { return _calendar; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The c. + internal CalendarItemCollection( Calendar c ) + { + _calendar = c; + } + + #region Public Methods + + /// + /// Adds an item to the end of the list + /// + /// The object to be added to the end of the collection. The value can be null for reference types. + public new void Add( CalendarItem item ) + { + base.Add( item ); CollectionChanged(); + } + + /// + /// Adds the items of the specified collection to the end of the list. + /// + /// The items whose elements should be added to the end of the collection. The collection itself cannont be null, but it can contain elements that are null. + public new void AddRange( IEnumerable items ) + { + base.AddRange( items ); CollectionChanged(); + } + + /// + /// Removes all elements from the collection. + /// + public new void Clear() + { + base.Clear(); CollectionChanged(); + } + + /// + /// Inserts an item into the collection at the specified index. + /// + /// The zero-based index at which item should be inserted. + /// The object to insert. The value can be null for reference types. + public new void Insert( int index, CalendarItem item ) + { + base.Insert( index, item ); CollectionChanged(); + } + + /// + /// Inserts the items of a collection into this collection at the specified index. + /// + /// The zero-based index at which the new elements should be inserted. + /// + public new void InsertRange( int index, IEnumerable items ) + { + base.InsertRange( index, items ); CollectionChanged(); + } + + /// + /// Removes the first occurrence of a specific object from the collection. + /// + /// The item to remove from the collection. The value can be null for reference types. + /// true if item is successfully removed; otherwise, false. This method also returns false if item was not found in the collection. + public new bool Remove( CalendarItem item ) + { + bool result = base.Remove( item ); + + CollectionChanged(); + + return result; + } + + /// + /// Removes the item at the specified index of the collection + /// + /// The zero-based index of the item to remove. + /// is less than 0. + /// -or- + /// is equal to or greater than . + /// + public new void RemoveAt( int index ) + { + base.RemoveAt( index ); CollectionChanged(); + } + + /// + /// Removes the all the items that match the conditions defined by the specified predicate. + /// + /// The Predicate delegate that defines the conditions of the items to remove. + /// The number of items removed from the collection. + public new int RemoveAll( Predicate match ) + { + int result = base.RemoveAll( match ); + + CollectionChanged(); + + return result; + } + + /// + /// Removes a range of elements from the collection + /// + /// The zero-based starting index of the range of items to remove. + /// The number of items to remove + public new void RemoveRange( int index, int count ) + { + base.RemoveRange( index, count ); CollectionChanged(); + } + + #endregion + + #region Private Methods + + /// + /// Handles what to do when this collection changes + /// + private void CollectionChanged() + { + Calendar.Renderer.PerformItemsLayout(); + Calendar.Invalidate(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/CalendarSelectableElement.cs b/WindowsFormsCalendar/CalendarSelectableElement.cs new file mode 100644 index 0000000..398bc58 --- /dev/null +++ b/WindowsFormsCalendar/CalendarSelectableElement.cs @@ -0,0 +1,130 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Implements a basic + /// + public abstract class CalendarSelectableElement + : ICalendarSelectableElement + { + #region Fields + + private Calendar _calendar; + + private Rectangle _bounds; + + private DateTime _date; + + private bool _selected; + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + public CalendarSelectableElement(Calendar calendar) + { + if (calendar == null) throw new ArgumentNullException("calendar"); + + _calendar = calendar; + } + + #region ICalendarSelectableElement Members + + /// + /// Gets the calendar + /// + public virtual DateTime Date + { + get { return _date; } + } + + /// + /// Gets the Calendar this element belongs to + /// + public virtual Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets the Bounds of the element on the window + /// + public virtual Rectangle Bounds + { + get { return _bounds; } + } + + /// + /// Gets a value indicating if the element is currently selected + /// + public virtual bool Selected + { + get + { + return _selected; + } + } + + /// + /// Compares this element with other using date as comparer + /// + /// + /// + public virtual int CompareTo(ICalendarSelectableElement element) + { + return this.Date.CompareTo(element.Date); + } + + #endregion + + #region Internal Methods + + /// + /// Sets the value of the property + /// + /// Bounds of the element + internal virtual void SetBounds(Rectangle bounds) + { + _bounds = bounds; + } + + /// + /// Sets the value of the property + /// + /// Value indicating if the element is currently selected + internal virtual void SetSelected(bool selected) + { + _selected = selected; + + //Calendar.Invalidate(Bounds); + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/CalendarTimeScaleUnit.cs b/WindowsFormsCalendar/CalendarTimeScaleUnit.cs new file mode 100644 index 0000000..f21816a --- /dev/null +++ b/WindowsFormsCalendar/CalendarTimeScaleUnit.cs @@ -0,0 +1,252 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a selectable timescale unit on a + /// + public class CalendarTimeScaleUnit + : CalendarSelectableElement + { + #region Events + + #endregion + + #region Fields + private DateTime _date; + private CalendarDay _day; + private bool _highlighted; + private int _hours; + private int _index; + private int _minutes; + private List _passingItems; + private bool _visible; + #endregion + + #region Properties + + + + /// + /// Gets the exact date when the unit starts + /// + public override DateTime Date + { + get + { + if( _date.Equals( DateTime.MinValue ) ) + { + _date = new DateTime( Day.Date.Year, Day.Date.Month, Day.Date.Day, Hours, Minutes, 0 ); + } + + return _date; + } + } + + /// + /// Gets the this unit belongs to + /// + public CalendarDay Day + { + get { return _day; } + } + + /// + /// Gets the duration of the unit. + /// + public TimeSpan Duration + { + get + { + return new TimeSpan( 0, (int)Calendar.TimeScale, 0 ); + } + } + + /// + /// Gets if the unit is highlighted because it fits in some of the calendar's highlight ranges + /// + public bool Highlighted + { + get { return _highlighted; } + } + + /// + /// Gets the hour when this unit starts + /// + public int Hours + { + get { return _hours; } + } + + /// + /// Gets the index of the unit relative to the day + /// + public int Index + { + get { return _index; } + } + + /// + /// Gets the minute when this unit starts + /// + public int Minutes + { + get { return _minutes; } + set { _minutes = value; } + } + + /// + /// Gets or sets the amount of items that pass over the unit + /// + internal List PassingItems + { + get { return _passingItems; } + set { _passingItems = value; } + } + + /// + /// Gets a value indicating if the unit is currently visible on viewport + /// + public bool Visible + { + get { return _visible; } + } + + #endregion + + /// + /// Creates a new + /// + /// this unit belongs to + /// Index of the unit relative to the container day + /// Hour of the unit + /// Minutes of the unit + internal CalendarTimeScaleUnit( CalendarDay day, int index, int hours, int minutes ) + : base( day.Calendar ) + { + _day = day; + _index = index; + _hours = hours; + _minutes = minutes; + + _passingItems = new List(); + } + + #region Public Methods + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format( "[{0}] - {1}", Index, Date.ToShortTimeString() ); + } + + #endregion + + #region Private Methods + + /// + /// Gets a value indicating if the unit should be higlighted + /// + /// + internal bool CheckHighlighted() + { + for( int i = 0; i < Day.Calendar.HighlightRanges.Length; i++ ) + { + CalendarHighlightRange range = Day.Calendar.HighlightRanges[i]; + + if( range.DayOfWeek != Date.DayOfWeek ) + continue; + + if( Date.TimeOfDay.CompareTo( range.StartTime ) >= 0 + && Date.TimeOfDay.CompareTo( range.EndTime ) < 0 ) + { + return true; + } + + } + return false; + } + + /// + /// Sets the value of the property + /// + /// Value of the property + internal void SetHighlighted( bool highlighted ) + { + _highlighted = highlighted; + } + + /// + /// Sets the value of the property + /// + /// Value indicating if the unit is currently visible on viewport + internal void SetVisible( bool visible ) + { + _visible = visible; + } + + #endregion + + #region Internal Methods + + /// + /// Adds the passing item. + /// + /// The item. + internal void AddPassingItem( CalendarItem item ) + { + if( !PassingItems.Contains( item ) ) + { + PassingItems.Add( item ); + Day.AddContainedItem( item ); + } + } + + /// + /// Clears existance of item from this unit and it's corresponding day. + /// + /// + internal void ClearItemExistance( CalendarItem item ) + { + if( PassingItems.Contains( item ) ) + { + PassingItems.Remove( item ); + } + + if( Day.ContainedItems.Contains( item ) ) + { + Day.ContainedItems.Remove( item ); + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/CalendarWeek.cs b/WindowsFormsCalendar/CalendarWeek.cs new file mode 100644 index 0000000..18d3667 --- /dev/null +++ b/WindowsFormsCalendar/CalendarWeek.cs @@ -0,0 +1,174 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a week displayed on the + /// + public class CalendarWeek + { + #region Events + + #endregion + + #region Fields + private Rectangle _bounds; + private Calendar _calendar; + private DateTime _firstDay; + #endregion + + #region Properties + + /// + /// Gets the bounds of the week + /// + public Rectangle Bounds + { + get { return _bounds; } + } + + /// + /// Gets the calendar this week belongs to + /// + public Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets the bounds of the week header + /// + public Rectangle HeaderBounds + { + get + { + return new Rectangle( + Bounds.Left, + Bounds.Top + Calendar.Renderer.DayHeaderHeight, + Calendar.Renderer.WeekHeaderWidth, + Bounds.Height - Calendar.Renderer.DayHeaderHeight ); + } + } + + /// + /// Gets the sunday that starts the week + /// + public DateTime StartDate + { + get { return _firstDay; } + } + + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + /// The first day. + internal CalendarWeek(Calendar calendar, DateTime firstDay) + { + _calendar = calendar; + _firstDay = firstDay; + } + + #region Public Methods + + /// + /// Gets the short version of week's string representation + /// + /// + public string ToStringShort() + { + DateTime saturday = StartDate.AddDays(6); + + if (saturday.Month != StartDate.Month) + { + return string.Format("{0} - {1}", + StartDate.ToString("d/M"), + saturday.ToString("d/M") + ); + } + else + { + return string.Format("{0} - {1}", + StartDate.Day, + saturday.ToString("d/M") + ); + } + } + + /// + /// Gets the large version of string representation + /// + /// The week in a string format + public string ToStringLarge() + { + DateTime saturday = StartDate.AddDays(6); + + if (saturday.Month != StartDate.Month) + { + return string.Format("{0} - {1}", + StartDate.ToString("d MMM"), + saturday.ToString("d MMM") + ); + } + else + { + return string.Format("{0} - {1}", + StartDate.Day, + saturday.ToString("d MMM") + ); + } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return ToStringLarge(); + } + + #endregion + + #region Private Methods + + /// + /// Sets the value of the property + /// + /// + internal void SetBounds(Rectangle r) + { + _bounds = r; + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/Enums/CalendarDaysMode.cs b/WindowsFormsCalendar/Enums/CalendarDaysMode.cs new file mode 100644 index 0000000..9367e91 --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarDaysMode.cs @@ -0,0 +1,41 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Enumerates the possible modes of the days visualization on the + /// + public enum CalendarDaysMode + { + /// + /// A short version of the day is visible without time scale. + /// + Short, + + /// + /// The day is fully visible with time scale. + /// + Expanded + } +} diff --git a/WindowsFormsCalendar/Enums/CalendarItemImageAlign.cs b/WindowsFormsCalendar/Enums/CalendarItemImageAlign.cs new file mode 100644 index 0000000..59cba1c --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarItemImageAlign.cs @@ -0,0 +1,51 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Possible alignment for images + /// + public enum CalendarItemImageAlign + { + /// + /// Image is drawn at north of text + /// + North, + + /// + /// Image is drawn at south of text + /// + South, + + /// + /// Image is drawn at east of text + /// + East, + + /// + /// Image is drawn at west of text + /// + West, + } +} diff --git a/WindowsFormsCalendar/Enums/CalendarScrollBars.cs b/WindowsFormsCalendar/Enums/CalendarScrollBars.cs new file mode 100644 index 0000000..fccbb3a --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarScrollBars.cs @@ -0,0 +1,52 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Enumeration for the different type of scroll bars + /// + public enum CalendarScrollBars + { + /// + /// No scroll bars + /// + None, + + /// + /// Vertical and Horizontal scrollbars + /// + Both, + + /// + /// Only vertical scrollbars + /// + Vertical, + + /// + /// Only horizontal scrollbars + /// + Horizontal + } +} diff --git a/WindowsFormsCalendar/Enums/CalendarState.cs b/WindowsFormsCalendar/Enums/CalendarState.cs new file mode 100644 index 0000000..4427091 --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarState.cs @@ -0,0 +1,57 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Possible states of the calendar + /// + public enum CalendarState + { + /// + /// Nothing happening + /// + Idle, + + /// + /// User is currently dragging on view to select a time range + /// + DraggingTimeSelection, + + /// + /// User is currently dragging an item among the view + /// + DraggingItem, + + /// + /// User is editing an item's Text + /// + EditingItemText, + + /// + /// User is currently resizing an item + /// + ResizingItem + } +} diff --git a/WindowsFormsCalendar/Enums/CalendarTimeFormat.cs b/WindowsFormsCalendar/Enums/CalendarTimeFormat.cs new file mode 100644 index 0000000..d231525 --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarTimeFormat.cs @@ -0,0 +1,42 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// An enumeration that represents the time format of the calendar + /// + public enum CalendarTimeFormat + { + /// + /// A twelve hour clock + /// + TwelveHour, + + /// + /// A twenty four hour clock + /// + TwentyFourHour + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/Enums/CalendarTimeScale.cs b/WindowsFormsCalendar/Enums/CalendarTimeScale.cs new file mode 100644 index 0000000..e361e8d --- /dev/null +++ b/WindowsFormsCalendar/Enums/CalendarTimeScale.cs @@ -0,0 +1,61 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Enumerates possible timescales for control + /// + public enum CalendarTimeScale + { + /// + /// Makes calendar show intervals of 60 minutes + /// + SixtyMinutes = 60, + + /// + /// Makes calendar show intervals of 30 minutes + /// + ThirtyMinutes = 30, + + /// + /// Makes calendar show intervals of 15 minutes + /// + FifteenMinutes = 15, + + /// + /// Makes calendar show intervals of 10 minutes + /// + TenMinutes = 10, + + /// + /// Makes calendar show intervals of 6 minutes + /// + SixMinutes = 6, + + /// + /// Makes calendar show intervals of 5 minutes + /// + FiveMinutes = 5 + } +} diff --git a/WindowsFormsCalendar/Enums/Corners.cs b/WindowsFormsCalendar/Enums/Corners.cs new file mode 100644 index 0000000..63d3511 --- /dev/null +++ b/WindowsFormsCalendar/Enums/Corners.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Possible corners to pass to the RoundRectangle method + /// + [Flags()] + public enum Corners + { + /// + /// No corners + /// + None = 0, + + /// + /// Northwest corner + /// + NorthWest = 2, + + /// + /// Northeast corner + /// + NorthEast = 4, + + /// + /// Southeast corner + /// + SouthEast = 8, + + /// + /// Southwest corner + /// + SouthWest = 16, + + /// + /// All corners + /// + All = NorthWest | NorthEast | SouthEast | SouthWest, + + /// + /// North corner + /// + North = NorthWest | NorthEast, + + /// + /// South corner + /// + South = SouthEast | SouthWest, + + /// + /// East Corner + /// + East = NorthEast | SouthEast, + + /// + /// West corner + /// + West = NorthWest | SouthWest + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/Enums/MonthViewSelection.cs b/WindowsFormsCalendar/Enums/MonthViewSelection.cs new file mode 100644 index 0000000..ebcb06f --- /dev/null +++ b/WindowsFormsCalendar/Enums/MonthViewSelection.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Represents the different kinds of selection in MonthView + /// + public enum MonthViewSelection + { + /// + /// User can select whatever date available to mouse reach + /// + Manual, + + /// + /// Selection is limited to just one day + /// + Day, + + /// + /// Selecion is limited to weekly ranges + /// + WorkWeek, + + /// + /// Selection is limited to a full week + /// + Week, + + /// + /// Selection is limited to a full month + /// + Month + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/EventArgs/CalendarDayEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarDayEventArgs.cs new file mode 100644 index 0000000..4a51e9e --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarDayEventArgs.cs @@ -0,0 +1,54 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Event data with a element + /// + public class CalendarDayEventArgs + :EventArgs + { + /// + /// Creates a new event with the specified day + /// + /// Day of the event + public CalendarDayEventArgs(CalendarDay day) + { + _calendarDay = day; + } + + #region Props + private CalendarDay _calendarDay; + + /// + /// Gets the day related to the event + /// + public CalendarDay CalendarDay + { + get { return _calendarDay; } + } + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarItemCancelEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarItemCancelEventArgs.cs new file mode 100644 index 0000000..29fd4eb --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarItemCancelEventArgs.cs @@ -0,0 +1,57 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace WindowsFormsCalendar +{ + /// + /// Event arguments for calendar cancel item event + /// + public class CalendarItemCancelEventArgs + : CancelEventArgs + { + /// + /// Creates a new + /// + /// Related Item + public CalendarItemCancelEventArgs( CalendarItem item ) + { + _item = item; + } + + #region Props + + private CalendarItem _item; + + /// + /// Gets the related to the event + /// + public CalendarItem Item + { + get { return _item; } + } + + + #endregion + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/EventArgs/CalendarItemEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarItemEventArgs.cs new file mode 100644 index 0000000..8886d34 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarItemEventArgs.cs @@ -0,0 +1,57 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; + +namespace WindowsFormsCalendar +{ + /// + /// Event arguments for the calendar item events. + /// + public class CalendarItemEventArgs + : EventArgs + { + /// + /// Creates a new + /// + /// Related Item + public CalendarItemEventArgs(CalendarItem item) + { + _item = item; + } + + #region Props + + private CalendarItem _item; + + /// + /// Gets the related to the event + /// + public CalendarItem Item + { + get { return _item; } + } + + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarLoadEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarLoadEventArgs.cs new file mode 100644 index 0000000..074f36f --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarLoadEventArgs.cs @@ -0,0 +1,82 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Holds data of a Calendar Loading Items of certain date range + /// + public class CalendarLoadEventArgs + : EventArgs + { + #region Fields + private Calendar _calendar; + private DateTime _dateStart; + private DateTime _dateEnd; + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The calendar. + /// The date start. + /// The date end. + public CalendarLoadEventArgs(Calendar calendar, DateTime dateStart, DateTime dateEnd) + { + _calendar = calendar; + _dateEnd = dateEnd; + _dateStart = dateStart; + } + + #region Props + + /// + /// Gets the calendar that originated the event + /// + public Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets the start date of the load + /// + public DateTime DateStart + { + get { return _dateStart; } + set { _dateStart = value; } + } + + /// + /// Gets the end date of the load + /// + public DateTime DateEnd + { + get { return _dateEnd; } + } + + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererBoxEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererBoxEventArgs.cs new file mode 100644 index 0000000..86b9494 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererBoxEventArgs.cs @@ -0,0 +1,235 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Contains information about something's bounds and text to draw on the calendar + /// + public class CalendarRendererBoxEventArgs + : CalendarRendererEventArgs + { + #region Fields + private Color _backgroundColor; + private Rectangle _bounds; + private Font _font; + private TextFormatFlags _format; + private string _text; + private Color _textColor; + private Size _textSize; + #endregion + + /// + /// Initializes some fields + /// + private CalendarRendererBoxEventArgs() + { + this.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + this.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + this.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + this.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original) + : base(original) + { + Font = original.Calendar.Font; + Format |= TextFormatFlags.Default | TextFormatFlags.WordBreak | TextFormatFlags.PreserveGraphicsClipping;// | TextFormatFlags.WordEllipsis; + TextColor = SystemColors.ControlText; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds) + : this(original) + { + Bounds = bounds; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + /// The text. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds, string text) + : this(original) + { + Bounds = bounds; + Text = text; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + /// The text. + /// The flags. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds, string text, TextFormatFlags flags) + : this(original) + { + Bounds = bounds; + Text = text; + Format |= flags; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + /// The text. + /// Color of the text. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds, string text, Color textColor) + : this(original) + { + Bounds = bounds; + Text = text; + TextColor = textColor; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + /// The text. + /// Color of the text. + /// The flags. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds, string text, Color textColor, TextFormatFlags flags) + : this(original) + { + Bounds = bounds; + Text = text; + TextColor = TextColor; + Format |= flags; + } + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The bounds. + /// The text. + /// Color of the text. + /// Color of the background. + public CalendarRendererBoxEventArgs(CalendarRendererEventArgs original, Rectangle bounds, string text, Color textColor, Color backgroundColor) + : this(original) + { + Bounds = bounds; + Text = text; + TextColor = TextColor; + BackgroundColor = backgroundColor; + } + + #region Props + + /// + /// Gets or sets the background color of the text + /// + public Color BackgroundColor + { + get { return _backgroundColor; } + set { _backgroundColor = value; } + } + + /// + /// Gets or sets the bounds to draw the text + /// + public Rectangle Bounds + { + get { return _bounds; } + set { _bounds = value; } + } + + /// + /// Gets or sets the font of the text to be rendered + /// + public Font Font + { + get { return _font; } + set { _font = value; _textSize = Size.Empty; } + } + + /// + /// Gets or sets the format to draw the text + /// + public TextFormatFlags Format + { + get { return _format; } + set { _format = value; _textSize = Size.Empty; } + } + + /// + /// Gets or sets the text to draw + /// + public string Text + { + get { return _text; } + set { _text = value; _textSize = Size.Empty; } + } + + /// + /// Gets the result of measuring the text + /// + public Size TextSize + { + get + { + if (_textSize.IsEmpty) + { + _textSize = TextRenderer.MeasureText(Text, Font); + } + return _textSize; + } + } + + + /// + /// Gets or sets the color to draw the text + /// + public Color TextColor + { + get { return _textColor; } + set { _textColor = value; } + } + + + + #endregion + + #region Methods + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererDayEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererDayEventArgs.cs new file mode 100644 index 0000000..cbd1a35 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererDayEventArgs.cs @@ -0,0 +1,60 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Contains information about a day to draw on the calendar + /// + public class CalendarRendererDayEventArgs + : CalendarRendererEventArgs + { + #region Fields + private CalendarDay _day; + #endregion + + /// + /// Creates a new object + /// + /// Orignal object to copy basic paramters + /// Day to render + public CalendarRendererDayEventArgs(CalendarRendererEventArgs original, CalendarDay day) + : base(original) + { + _day = day; + } + + #region Props + + /// + /// Gets the day to paint + /// + public CalendarDay Day + { + get { return _day; } + } + + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererEventArgs.cs new file mode 100644 index 0000000..2a04872 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererEventArgs.cs @@ -0,0 +1,171 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Contains basic information about a drawing event for + /// + public class CalendarRendererEventArgs + : EventArgs + { + #region Events + + #endregion + + #region Fields + + private Calendar _calendar; + + private Rectangle _clip; + + private Graphics _graphics; + + private object _tag; + + #endregion + + #region Properties + + /// + /// Gets the calendar where painting + /// + public Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets the clip of the paint event + /// + public Rectangle ClipRectangle + { + get { return _clip; } + } + + /// + /// Gets the device where to paint + /// + public Graphics Graphics + { + get { return _graphics; } + } + + /// + /// Gets or sets a tag for the event + /// + public object Tag + { + get { return _tag; } + set { _tag = value; } + } + + + #endregion + + /// + /// Use it wisely just to initialize some stuff + /// + protected CalendarRendererEventArgs() + { + this.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + this.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + this.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + this.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + } + + /// + /// Creates a new + /// + /// Calendar where painting + /// The graphics. + /// The clip rectangle. + public CalendarRendererEventArgs( Calendar calendar, Graphics graphics, Rectangle clipRectangle ) + { + _calendar = calendar; + _graphics = graphics; + _clip = clipRectangle; + + if( _graphics != null ) + { + _graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + _graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + _graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + _graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + } + } + + /// + /// Creates a new + /// + /// Calendar where painting + /// The graphics. + /// The clip rectangle. + /// The tag. + public CalendarRendererEventArgs( Calendar calendar, Graphics graphics, Rectangle clipRectangle, object tag ) + { + _calendar = calendar; + _graphics = graphics; + _clip = clipRectangle; + _tag = tag; + + if( _graphics != null ) + { + _graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + _graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + _graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + _graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + } + } + + /// + /// Copies the parameters from the specified + /// + /// The instance containing the event data. + public CalendarRendererEventArgs( CalendarRendererEventArgs original ) + { + _calendar = original.Calendar; + _graphics = original.Graphics; + _clip = original.ClipRectangle; + _tag = original.Tag; + + if( _graphics != null ) + { + _graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + _graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + _graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + _graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + } + } + + #region Public Methods + + #endregion + + #region Private Methods + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererItemBoundsEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererItemBoundsEventArgs.cs new file mode 100644 index 0000000..d1660a1 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererItemBoundsEventArgs.cs @@ -0,0 +1,100 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Event arguments for calendar renter item bounds + /// + public class CalendarRendererItemBoundsEventArgs + : CalendarRendererItemEventArgs + { + #region Fields + private Rectangle _bounds; + private bool _isFirst; + private bool _isLast; + #endregion + + #region Properties + + /// + /// Gets the bounds of the item to be rendered. + /// + /// + /// Items may have more than one bounds due to week segmentation. + /// + public Rectangle Bounds + { + get { return _bounds; } + } + + /// + /// Gets a value indicating if the bounds are the first of the item. + /// + /// + /// Items may have more than one bounds due to week segmentation. + /// + public bool IsFirst + { + get { return _isFirst; } + } + + /// + /// Gets a value indicating if the bounds are the last of the item. + /// + /// + /// Items may have more than one bounds due to week segmentation. + /// + public bool IsLast + { + get { return _isLast; } + set { _isLast = value; } + } + + + #endregion + + /// + /// Creates a new Event + /// + /// + /// + /// + /// + internal CalendarRendererItemBoundsEventArgs(CalendarRendererItemEventArgs original, Rectangle bounds, bool isFirst, bool isLast) + : base(original, original.Item) + { + _isFirst = isFirst; + _isLast = isLast; + _bounds = bounds; + + this.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + this.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + this.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + this.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + + } + + } +} diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererItemEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererItemEventArgs.cs new file mode 100644 index 0000000..102c6e0 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererItemEventArgs.cs @@ -0,0 +1,66 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Contains information to render an item + /// + public class CalendarRendererItemEventArgs + : CalendarRendererEventArgs + { + #region Fields + private CalendarItem _item; + #endregion + + #region Properties + + /// + /// Gets the Item being rendered + /// + public CalendarItem Item + { + get { return _item; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The item. + public CalendarRendererItemEventArgs( CalendarRendererEventArgs original, CalendarItem item ) + : base( original ) + { + _item = item; + + this.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + this.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + this.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + this.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + + } + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/EventArgs/CalendarRendererTimeUnitEventArgs.cs b/WindowsFormsCalendar/EventArgs/CalendarRendererTimeUnitEventArgs.cs new file mode 100644 index 0000000..68a1292 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/CalendarRendererTimeUnitEventArgs.cs @@ -0,0 +1,77 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Contains information about a that is about to be painted + /// + public class CalendarRendererTimeUnitEventArgs + : CalendarRendererEventArgs + { + #region Events + + #endregion + + #region Fields + private CalendarTimeScaleUnit _unit; + #endregion + + #region Properties + + /// + /// Gets the unit that is about to be painted + /// + public CalendarTimeScaleUnit Unit + { + get { return _unit; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The instance containing the event data. + /// The unit. + public CalendarRendererTimeUnitEventArgs(CalendarRendererEventArgs original, CalendarTimeScaleUnit unit) + : base(original) + { + _unit = unit; + + this.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + this.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + this.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + this.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + + } + + #region Public Methods + + #endregion + + #region Private Methods + + #endregion + } +} diff --git a/WindowsFormsCalendar/EventArgs/MonthViewBoxEventArgs.cs b/WindowsFormsCalendar/EventArgs/MonthViewBoxEventArgs.cs new file mode 100644 index 0000000..728353e --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/MonthViewBoxEventArgs.cs @@ -0,0 +1,215 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Holds data about a box of text to be rendered on the month view + /// + public class MonthViewBoxEventArgs + { + #region Fields + private Graphics _graphics; + private Color _textColor; + private Color _backgroundColor; + private string _text; + private Color _borderColor; + private Rectangle _bounds; + private Font _font; + private TextFormatFlags _TextFlags; + #endregion + + #region Properties + + /// + /// Gets or sets the bounds of the box + /// + public Rectangle Bounds + { + get { return _bounds; } + } + + /// + /// Gets or sets the font of the text. If null, default will be used. + /// + public Font Font + { + get { return _font; } + set { _font = value; } + } + + /// + /// Gets or sets the Graphics object where to draw + /// + public Graphics Graphics + { + get { return _graphics; } + } + + /// + /// Gets or sets the border color of the box + /// + public Color BorderColor + { + get { return _borderColor; } + set { _borderColor = value; } + } + + /// + /// Gets or sets the text of the box + /// + public string Text + { + get { return _text; } + set { _text = value; } + } + + /// + /// Gets or sets the background color of the box + /// + public Color BackgroundColor + { + get { return _backgroundColor; } + set { _backgroundColor = value; } + } + + /// + /// Gets or sets the text color of the box + /// + public Color TextColor + { + get { return _textColor; } + set { _textColor = value; } + } + + /// + /// Gets or sets the flags of the text + /// + public TextFormatFlags TextFlags + { + get { return _TextFlags; } + set { _TextFlags = value; } + } + + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The graphics. + /// The bounds. + /// The text. + /// The text align. + /// Color of the text. + /// Color of the back. + /// Color of the border. + internal MonthViewBoxEventArgs( Graphics graphics, Rectangle bounds, string text, StringAlignment textAlign, Color textColor, Color backColor, Color borderColor ) + { + _graphics = graphics; + + _graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + _graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + _graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + _graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; + + _bounds = bounds; + Text = text; + TextColor = textColor; + BackgroundColor = backColor; + BorderColor = borderColor; + + switch( textAlign ) + { + case StringAlignment.Center: + TextFlags |= TextFormatFlags.HorizontalCenter; + break; + + case StringAlignment.Far: + TextFlags |= TextFormatFlags.Right; + break; + + case StringAlignment.Near: + TextFlags |= TextFormatFlags.Left; + break; + + default: + break; + + } + + TextFlags |= TextFormatFlags.VerticalCenter; + } + + /// + /// Initializes a new instance of the class. + /// + /// The graphics. + /// The bounds. + /// The text. + /// Color of the text. + internal MonthViewBoxEventArgs( Graphics graphics, Rectangle bounds, string text, Color textColor ) + : this( graphics, bounds, text, StringAlignment.Center, textColor, Color.Empty, Color.Empty ) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The graphics. + /// The bounds. + /// The text. + /// Color of the text. + /// Color of the back. + internal MonthViewBoxEventArgs( Graphics graphics, Rectangle bounds, string text, Color textColor, Color backColor ) + : this( graphics, bounds, text, StringAlignment.Center, textColor, backColor, Color.Empty ) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The graphics. + /// The bounds. + /// The text. + /// The text align. + /// Color of the text. + /// Color of the back. + internal MonthViewBoxEventArgs( Graphics graphics, Rectangle bounds, string text, StringAlignment textAlign, Color textColor, Color backColor ) + : this( graphics, bounds, text, textAlign, textColor, backColor, Color.Empty ) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The graphics. + /// The bounds. + /// The text. + /// The text align. + /// Color of the text. + internal MonthViewBoxEventArgs( Graphics graphics, Rectangle bounds, string text, StringAlignment textAlign, Color textColor ) + : this( graphics, bounds, text, textAlign, textColor, Color.Empty, Color.Empty ) + { } + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/EventArgs/MonthViewMontEventArgs.cs b/WindowsFormsCalendar/EventArgs/MonthViewMontEventArgs.cs new file mode 100644 index 0000000..6ca8645 --- /dev/null +++ b/WindowsFormsCalendar/EventArgs/MonthViewMontEventArgs.cs @@ -0,0 +1,33 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + /// + /// Month view event argument data + /// + public class MonthViewMontEventArgs + { + + } +} diff --git a/WindowsFormsCalendar/GPL v3.txt b/WindowsFormsCalendar/GPL v3.txt new file mode 100644 index 0000000..20d40b6 --- /dev/null +++ b/WindowsFormsCalendar/GPL v3.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/WindowsFormsCalendar/ICalendarSelectableElement.cs b/WindowsFormsCalendar/ICalendarSelectableElement.cs new file mode 100644 index 0000000..29a88e8 --- /dev/null +++ b/WindowsFormsCalendar/ICalendarSelectableElement.cs @@ -0,0 +1,45 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Interface implemented by every selectable element of the calendar + /// + public interface ICalendarSelectableElement + : ISelectableElement, IComparable + { + + /// + /// Gets the calendar this element belongs to + /// + Calendar Calendar { get; } + + /// + /// Gets the calendar + /// + DateTime Date { get; } + + } +} diff --git a/WindowsFormsCalendar/ISelectableElement.cs b/WindowsFormsCalendar/ISelectableElement.cs new file mode 100644 index 0000000..77a6f81 --- /dev/null +++ b/WindowsFormsCalendar/ISelectableElement.cs @@ -0,0 +1,43 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a clickable element of control + /// + public interface ISelectableElement + { + + /// + /// Gets the bounds of the element + /// + Rectangle Bounds { get; } + + /// + /// Gets if the element is currently selected + /// + bool Selected { get; } + } +} diff --git a/WindowsFormsCalendar/MonthViewDay.cs b/WindowsFormsCalendar/MonthViewDay.cs new file mode 100644 index 0000000..aace914 --- /dev/null +++ b/WindowsFormsCalendar/MonthViewDay.cs @@ -0,0 +1,133 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// A class that represents a month view day + /// + public class MonthViewDay + { + #region Fields + + Rectangle _bounds; + private DateTime _date; + private MonthViewMonth _month; + private MonthView _monthView; + + #endregion + + #region Propserties + + /// + /// Gets the parent MonthView + /// + public MonthView MonthView + { + get { return _monthView; } + set { _monthView = value; } + } + + /// + /// Gets the parent MonthViewMonth + /// + public MonthViewMonth Month + { + get { return _month; } + } + + /// + /// Gets the bounds of the day + /// + public Rectangle Bounds + { + get { return _bounds; } + } + + /// + /// Gets the date this day represents + /// + public DateTime Date + { + get { return _date; } + } + + /// + /// Gets or sets if the day is currently selected + /// + public bool Selected + { + get { return Date >= MonthView.SelectionStart && Date <= MonthView.SelectionEnd; } + } + + /// + /// Gets if the day is grayed + /// + public bool Grayed + { + get { return Month.Date.Month != Date.Month; } + } + + /// + /// Gets a value indicating if the day instance is visible on the calendar + /// + public bool Visible + { + get + { + return !( Grayed && ( Date > MonthView.ViewStart && Date < MonthView.ViewEnd ) ); + } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The month. + /// The date. + internal MonthViewDay(MonthViewMonth month, DateTime date) + { + _month = month; + _monthView = month.MonthView; + _date = date; + + + } + + #region Methods + + /// + /// Sets the value of the property + /// + /// + internal void SetBounds(Rectangle bounds) + { + _bounds = bounds; + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/MonthViewMontEventArgs.cs b/WindowsFormsCalendar/MonthViewMontEventArgs.cs new file mode 100644 index 0000000..650dc3f --- /dev/null +++ b/WindowsFormsCalendar/MonthViewMontEventArgs.cs @@ -0,0 +1,31 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace WindowsFormsCalendar +{ + public class MonthViewMontEventArgs + + { + + } +} diff --git a/WindowsFormsCalendar/MonthViewMonth.cs b/WindowsFormsCalendar/MonthViewMonth.cs new file mode 100644 index 0000000..309543f --- /dev/null +++ b/WindowsFormsCalendar/MonthViewMonth.cs @@ -0,0 +1,231 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace WindowsFormsCalendar +{ + /// + /// Represents a month displayed"/> + /// + public class MonthViewMonth + { + #region Fields + + private DateTime _date; + private Rectangle monthNameBounds; + private Rectangle[] dayNamesBounds; + private MonthViewDay[] days; + private string[] _dayHeaders; + private Size _size = new Size(); + private Point _location; + private MonthView _monthview; + + #endregion + + #region Properties + + /// + /// Gets the bounds. + /// + public Rectangle Bounds + { + get { return new Rectangle( Location, Size ); } + } + + /// + /// Gets the month view. + /// + public MonthView MonthView + { + get { return _monthview; } + } + + /// + /// Gets the location. + /// + public Point Location + { + get { return _location; } + } + + /// + /// Gets the size. + /// + public Size Size + { + get { return MonthView.MonthSize; } + } + + /// + /// Gets or sets the days. + /// + /// + /// The days. + /// + public MonthViewDay[] Days + { + get { return days; } + set { days = value; } + } + + /// + /// Gets or sets the day names bounds. + /// + /// + /// The day names bounds. + /// + public Rectangle[] DayNamesBounds + { + get { return dayNamesBounds; } + set { dayNamesBounds = value; } + } + + /// + /// Gets or sets the day headers. + /// + /// + /// The day headers. + /// + public string[] DayHeaders + { + get { return _dayHeaders; } + set { _dayHeaders = value; } + } + + /// + /// Gets or sets the month name bounds. + /// + /// + /// The month name bounds. + /// + public Rectangle MonthNameBounds + { + get { return monthNameBounds; } + set { monthNameBounds = value; } + } + + /// + /// Gets or sets the date of the first day of the month + /// + public DateTime Date + { + get { return _date; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The month view. + /// The date. + internal MonthViewMonth( MonthView monthView, DateTime date ) + { + if( date.Day != 1 ) + { + date = new DateTime( date.Year, date.Month, 1 ); + } + + + _monthview = monthView; + _date = date; + + int preDays = ( new int[] { 0, 1, 2, 3, 4, 5, 6 } )[(int)date.DayOfWeek] - (int)MonthView.FirstDayOfWeek; + days = new MonthViewDay[6 * 7]; + DateTime curDate = date.AddDays( -preDays ); + DayHeaders = new string[7]; + + for( int i = 0; i < days.Length; i++ ) + { + days[i] = new MonthViewDay( this, curDate ); + + if( i < 7 ) + { + DayHeaders[i] = curDate.ToString( MonthView.DayNamesFormat ).Substring( 0, MonthView.DayNamesLength ); + } + + curDate = curDate.AddDays( 1 ); + } + } + + #region Public Methods + + #endregion + + #region Private Methods + + /// + /// Sets the value of the property + /// + /// + internal void SetLocation( Point location ) + { + + int startX = location.X; + int startY = location.Y; + int curX = startX; + int curY = startY; + + _location = location; + + monthNameBounds = new Rectangle( location, new Size( Size.Width, MonthView.DaySize.Height ) ); + + if( MonthView.DayNamesVisible ) + { + dayNamesBounds = new Rectangle[7]; + curY = location.Y + MonthView.DaySize.Height; + for( int i = 0; i < dayNamesBounds.Length; i++ ) + { + DayNamesBounds[i] = new Rectangle( curX, curY, MonthView.DaySize.Width, MonthView.DaySize.Height ); + + curX += MonthView.DaySize.Width; + } + + } + else + { + dayNamesBounds = new Rectangle[] { }; + } + + curX = startX; + curY = startY + MonthView.DaySize.Height * 2; + + for( int i = 0; i < Days.Length; i++ ) + { + Days[i].SetBounds( new Rectangle( new Point( curX, curY ), MonthView.DaySize ) ); + + curX += MonthView.DaySize.Width; + + if( ( i + 1 ) % 7 == 0 ) + { + curX = startX; + curY += MonthView.DaySize.Height; + } + } + + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/Properties/AssemblyInfo.cs b/WindowsFormsCalendar/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b9a9af3 --- /dev/null +++ b/WindowsFormsCalendar/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsFormsCalendar")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct( "WindowsFormsCalendar" )] +[assembly: AssemblyCopyright("Copyright © 2012 Justin LeCheminant")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("25ba6a13-96fe-4dd9-baae-0656f18fbcd0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.1.*")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/WindowsFormsCalendar/ReadMe.txt b/WindowsFormsCalendar/ReadMe.txt new file mode 100644 index 0000000..44e6f17 --- /dev/null +++ b/WindowsFormsCalendar/ReadMe.txt @@ -0,0 +1,15 @@ +This is the read me file for the WindowsFormsCalendar project. + +This project is a fork of the A Professional Calendar project on codeplex. + +The current version is 1.1 + +1.1 features + - Added Font selection for calendar items + - Added Foreground Color settings for calendar items + - Added Background Color settings for calendar items + - Updated the assembly version information to be correct. + +1.0 features + - Moved the project to the 4.0 framework + - Added a clock format selection to the calendar \ No newline at end of file diff --git a/WindowsFormsCalendar/Renderers/CalendarProfessionalRenderer.cs b/WindowsFormsCalendar/Renderers/CalendarProfessionalRenderer.cs new file mode 100644 index 0000000..4d0e5a2 --- /dev/null +++ b/WindowsFormsCalendar/Renderers/CalendarProfessionalRenderer.cs @@ -0,0 +1,271 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace WindowsFormsCalendar +{ + /// + /// Renders the professional calendar control + /// + public class CalendarProfessionalRenderer + : CalendarSystemRenderer + { + #region Fields + + /// + /// HeaderA + /// + public Color HeaderA = FromHex("#E4ECF6"); + + /// + /// HeaderB + /// + public Color HeaderB = FromHex("#D6E2F1"); + + /// + /// HeaderC + /// + public Color HeaderC = FromHex("#C2D4EB"); + + /// + /// HeaderD + /// + public Color HeaderD = FromHex("#D0DEEF"); + + /// + /// TodayA + /// + public Color TodayA = FromHex("#F8D478"); + + /// + /// TodayB + /// + public Color TodayB = FromHex("#F8D478"); + + /// + /// TodayC + /// + public Color TodayC = FromHex("#F2AA36"); + + /// + /// TodayD + /// + public Color TodayD = FromHex("#F7C966"); + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// The c. + public CalendarProfessionalRenderer(Calendar c) + : base(c) + { + + ColorTable.Background = FromHex("#E3EFFF"); + ColorTable.DayBackgroundEven = FromHex("#A5BFE1"); + ColorTable.DayBackgroundOdd = FromHex("#FFFFFF"); + ColorTable.DayBackgroundSelected = FromHex("#E6EDF7"); + ColorTable.DayBorder = FromHex("#5D8CC9"); + ColorTable.DayHeaderBackground = FromHex("#DFE8F5"); + ColorTable.DayHeaderText = Color.Black; + ColorTable.DayHeaderSecondaryText = Color.Black; + ColorTable.DayTopBorder = FromHex("#5D8CC9"); + ColorTable.DayTopSelectedBorder = FromHex("#5D8CC9"); + ColorTable.DayTopBackground = FromHex("#A5BFE1"); + ColorTable.DayTopSelectedBackground = FromHex("#294C7A"); + ColorTable.ItemBorder = FromHex("#5D8CC9"); + ColorTable.ItemBackground = FromHex("#C0D3EA"); + ColorTable.ItemText = Color.Black; + ColorTable.ItemSecondaryText = FromHex("#294C7A"); + ColorTable.ItemSelectedBorder = Color.Black; + ColorTable.ItemSelectedBackground = FromHex("#C0D3EA"); + ColorTable.ItemSelectedText = Color.Black; + ColorTable.WeekHeaderBackground = FromHex("#DFE8F5"); + ColorTable.WeekHeaderBorder = FromHex("#5D8CC9"); + ColorTable.WeekHeaderText = FromHex("#5D8CC9"); + ColorTable.TodayBorder = FromHex("#EE9311"); + ColorTable.TodayTopBackground = FromHex("#EE9311"); + ColorTable.TimeScaleLine = FromHex("#6593CF"); + ColorTable.TimeScaleHours = FromHex("#6593CF"); + ColorTable.TimeScaleMinutes = FromHex("#6593CF"); + ColorTable.TimeUnitBackground = FromHex("#E6EDF7"); + ColorTable.TimeUnitHighlightedBackground = Color.White; + ColorTable.TimeUnitSelectedBackground = FromHex("#294C7A"); + ColorTable.TimeUnitBorderLight = FromHex("#D5E1F1"); + ColorTable.TimeUnitBorderDark = FromHex("#A5BFE1"); + ColorTable.WeekDayName = FromHex("#6593CF"); + + SelectedItemBorder = 2f; + ItemRoundness = 5; + } + + #region Private Method + + /// + /// Gradients the rect. + /// + /// The g. + /// The bounds. + /// A. + /// The b. + public static void GradientRect(Graphics g, Rectangle bounds, Color a, Color b) + { + using (LinearGradientBrush br = new LinearGradientBrush(bounds, b, a, -90)) + { + g.FillRectangle(br, bounds); + } + } + + /// + /// Glossies the rect. + /// + /// The g. + /// The bounds. + /// A. + /// The b. + /// The c. + /// The d. + public static void GlossyRect(Graphics g, Rectangle bounds, Color a, Color b, Color c, Color d) + { + Rectangle top = new Rectangle(bounds.Left, bounds.Top, bounds.Width, bounds.Height / 2); + Rectangle bot = Rectangle.FromLTRB(bounds.Left, top.Bottom, bounds.Right, bounds.Bottom); + + GradientRect(g, top, a, b); + GradientRect(g, bot, c, d); + + } + + /// + /// Shortcut to one on CalendarColorTable + /// + /// + /// + private static Color FromHex(string color) + { + return CalendarColorTable.FromHex(color); + } + + #endregion + + #region Overrides + + /// + /// Initializes the Calendar + /// + /// + public override void OnInitialize(CalendarRendererEventArgs e) + { + base.OnInitialize(e); + + e.Calendar.Font = SystemFonts.CaptionFont; + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public override void OnDrawDayHeaderBackground(CalendarRendererDayEventArgs e) + { + Rectangle r = e.Day.HeaderBounds; + + if (e.Day.Date == DateTime.Today) + { + GlossyRect(e.Graphics, e.Day.HeaderBounds, TodayA, TodayB, TodayC, TodayD); + } + else + { + GlossyRect(e.Graphics, e.Day.HeaderBounds, HeaderA, HeaderB, HeaderC, HeaderD); + } + + if (e.Calendar.DaysMode == CalendarDaysMode.Short) + { + using (Pen p = new Pen(ColorTable.DayBorder)) + { + e.Graphics.DrawLine(p, r.Left, r.Top, r.Right, r.Top); + e.Graphics.DrawLine(p, r.Left, r.Bottom, r.Right, r.Bottom); + } + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public override void OnDrawItemBorder(CalendarRendererItemBoundsEventArgs e) + { + base.OnDrawItemBorder(e); + + using (Pen p = new Pen(Color.FromArgb(150, Color.White))) + { + e.Graphics.DrawLine(p, e.Bounds.Left + ItemRoundness, e.Bounds.Top + 1, e.Bounds.Right - ItemRoundness, e.Bounds.Top + 1); + } + + if (e.Item.Selected && !e.Item.IsDragging) + { + bool horizontal = false; + bool vertical = false; + Rectangle r1 = new Rectangle(0, 0, 5, 5); + Rectangle r2 = new Rectangle(0, 0, 5, 5); + + horizontal = e.Item.IsOnDayTop; + vertical = !e.Item.IsOnDayTop && e.Calendar.DaysMode == CalendarDaysMode.Expanded; + + if (horizontal) + { + r1.X = e.Bounds.Left - 2; + r2.X = e.Bounds.Right - r1.Width + 2; + r1.Y = e.Bounds.Top + (e.Bounds.Height - r1.Height) / 2; + r2.Y = r1.Y; + } + + if (vertical) + { + r1.Y = e.Bounds.Top - 2; + r2.Y = e.Bounds.Bottom - r1.Height + 2; + r1.X = e.Bounds.Left + (e.Bounds.Width - r1.Width) / 2; + r2.X = r1.X; + } + + if ((horizontal || vertical) && Calendar.AllowItemResize) + { + if (!e.Item.IsOpenStart && e.IsFirst) + { + e.Graphics.FillRectangle(Brushes.White, r1); + e.Graphics.DrawRectangle(Pens.Black, r1); + } + + if (!e.Item.IsOpenEnd && e.IsLast) + { + e.Graphics.FillRectangle(Brushes.White, r2); + e.Graphics.DrawRectangle(Pens.Black, r2); + } + } + } + } + + #endregion + + } +} diff --git a/WindowsFormsCalendar/Renderers/CalendarRenderer.cs b/WindowsFormsCalendar/Renderers/CalendarRenderer.cs new file mode 100644 index 0000000..2b5191e --- /dev/null +++ b/WindowsFormsCalendar/Renderers/CalendarRenderer.cs @@ -0,0 +1,1973 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Base class that renders visual elements of Calendar control + /// + public class CalendarRenderer + { + #region Static + + /// + /// Comparison delegate to sort items + /// + /// + /// + /// + private static int CompareItems(CalendarItem item1, CalendarItem item2) + { + return item1.StartDate.CompareTo(item2.StartDate) * -1; + } + + /// + /// Comparison delegate to sort units + /// + /// + /// + /// + private static int CompareUnits(CalendarTimeScaleUnit item1, CalendarTimeScaleUnit item2) + { + return item1.Date.CompareTo(item2.Date); + } + + /// + /// Compares both items by Date + /// + /// + /// + /// + private static int CompareTops(CalendarDayTop top1, CalendarDayTop top2) + { + return top1.Date.CompareTo(top2.Date); + } + + /// + /// Creates a rectangle with rounded corners + /// + /// + /// + /// + public static GraphicsPath RoundRectangle(Rectangle r, int radius) + { + return RoundRectangle(r, radius, Corners.All); + } + + /// + /// Creates a rectangle with the specified corners rounded + /// + /// + /// + /// + /// + public static GraphicsPath RoundRectangle(Rectangle r, int radius, Corners corners) + { + GraphicsPath path = new GraphicsPath(); if (r.Width <= 0 || r.Height <= 0) return path; + int d = radius * 2; + + int nw = (corners & Corners.NorthWest) == Corners.NorthWest ? d : 0; + int ne = (corners & Corners.NorthEast) == Corners.NorthEast ? d : 0; + int se = (corners & Corners.SouthEast) == Corners.SouthEast ? d : 0; + int sw = (corners & Corners.SouthWest) == Corners.SouthWest ? d : 0; + + path.AddLine(r.Left + nw, r.Top, r.Right - ne, r.Top); + + if (ne > 0) + { + path.AddArc(Rectangle.FromLTRB(r.Right - ne, r.Top, r.Right, r.Top + ne), + -90, 90); + } + + path.AddLine(r.Right, r.Top + ne, r.Right, r.Bottom - se); + + if (se > 0) + { + path.AddArc(Rectangle.FromLTRB(r.Right - se, r.Bottom - se, r.Right, r.Bottom), + 0, 90); + } + + path.AddLine(r.Right - se, r.Bottom, r.Left + sw, r.Bottom); + + if (sw > 0) + { + path.AddArc(Rectangle.FromLTRB(r.Left, r.Bottom - sw, r.Left + sw, r.Bottom), + 90, 90); + } + + path.AddLine(r.Left, r.Bottom - sw, r.Left, r.Top + nw); + + if (nw > 0) + { + path.AddArc(Rectangle.FromLTRB(r.Left, r.Top, r.Left + nw, r.Top + nw), + 180, 90); + } + + path.CloseFigure(); + + return path; + } + + + #endregion + + #region Events + + #endregion + + #region Fields + + private int _allDayItemsPadding; + private int _standardItemHeight; + private int _dayTopHeight; + private int _dayTopMinHeight; + private Calendar _calendar; + private Rectangle[] _dayNameHeaderColumns; + private int _dayHeaderHeight; + private int _dayNameHeadersHeight; + private int _itemInvalidateMargin; + private int _itemsPadding; + private Padding _itemTextMargin; + private int _itemShadowPadding; + private int _itemRoundness; + private Rectangle _timeScaleBounds; + private int _timeScaleUnitHeight; + private int _timeScaleWidth; + private int _weekHeaderWidth; + + #endregion + + #region Properties + + /// + /// Gets or sets the padding of the items that goes on the top part of the days, + /// when in + /// + /// + /// The day top items padding. + /// + public int DayTopItemsPadding + { + get { return _allDayItemsPadding; } + set { _allDayItemsPadding = value; } + } + + /// + /// Gets the current height of the all day items area + /// + /// + /// The height of the day top. + /// + public virtual int DayTopHeight + { + get + { + if( _dayTopHeight == 0 ) + { + _dayTopHeight = DayTopMinHeight; + } + return _dayTopHeight; + } + set + { + _dayTopHeight = value; + } + } + + /// + /// Gets the height of items on day tops + /// + /// + /// The height of the standard item. + /// + public virtual int StandardItemHeight + { + get + { + if( _standardItemHeight == 0 ) + { + _standardItemHeight = TextRenderer.MeasureText( "Ag", Calendar.Font ).Height; + } + + return _standardItemHeight + ItemTextMargin.Vertical; + } + } + + /// + /// Gets the minimum height for day tops + /// + /// + /// The height of the day top min. + /// + public virtual int DayTopMinHeight + { + get + { + if( _dayTopMinHeight == 0 ) + { + _dayTopMinHeight = TextRenderer.MeasureText( "Ag", Calendar.Font ).Height + 16; + } + + return _dayTopMinHeight; + } + } + + /// + /// Gets the this renderer belongs to + /// + public Calendar Calendar + { + get { return _calendar; } + } + + /// + /// Gets the bounds for day name headers + /// + public Rectangle[] DayNameHeaderColumns + { + get { return _dayNameHeaderColumns; } + } + + /// + /// Gets the height of the header of days + /// + /// + /// The height of the day header. + /// + public virtual int DayHeaderHeight + { + get + { + if( _dayHeaderHeight == 0 ) + { + _dayHeaderHeight = TextRenderer.MeasureText( "Ag", Calendar.Font ).Height + 4; + } + + return _dayHeaderHeight; + } + } + + /// + /// Gets a value indicating if the day names headers are visible (e.g. Monday, Tuesday, Wednesday ...) + /// + /// + /// true if [day name headers visible]; otherwise, false. + /// + public bool DayNameHeadersVisible + { + get { return Calendar.DaysMode == CalendarDaysMode.Short; } + } + + /// + /// Gets the height of the day name headers + /// + /// + /// The height of the day name headers. + /// + public virtual int DayNameHeadersHeight + { + get + { + if( _dayNameHeadersHeight == 0 ) + { + _dayNameHeadersHeight = DayHeaderHeight; + } + + return _dayNameHeadersHeight; + } + } + + /// + /// Gets the margin of the text in the items + /// + /// + /// The item text margin. + /// + public virtual Padding ItemTextMargin + { + get { return _itemTextMargin; } + set + { + _itemTextMargin = value; + } + } + + /// + /// Gets or sets the amount of pixels that the item's shadow is dropped + /// + /// + /// The item shadow padding. + /// + public virtual int ItemShadowPadding + { + get { return _itemShadowPadding; } + set { _itemShadowPadding = value; } + } + + /// + /// Gets or sets the extra margin for invalidating and redrawing items + /// + /// + /// The item invalidate margin. + /// + public int ItemInvalidateMargin + { + get { return _itemInvalidateMargin; } + set { _itemInvalidateMargin = value; } + } + + /// + /// Gets or sets the padding of items on expanded mode + /// + /// + /// The items padding. + /// + public int ItemsPadding + { + get { return _itemsPadding; } + set { _itemsPadding = value; } + } + + /// + /// Gets or sets the roundness of the item + /// + /// + /// The item roundness. + /// + public int ItemRoundness + { + get { return _itemRoundness; } + set { _itemRoundness = value; } + } + + /// + /// Gets or sets the bounds of the timescale + /// + /// + /// The time scale bounds. + /// + public Rectangle TimeScaleBounds + { + get { return _timeScaleBounds; } + set { _timeScaleBounds = value; } + } + + /// + /// Gets the height of the time scale unit. + /// + /// + /// The height of the time scale unit. + /// + public virtual int TimeScaleUnitHeight + { + get + { + if( _timeScaleUnitHeight == 0 ) + { + _timeScaleUnitHeight = TextRenderer.MeasureText( "Ag", Calendar.Font ).Height + 10; + } + + return _timeScaleUnitHeight; + } + } + + /// + /// Gets a value indicating whether [time scale visible]. + /// + /// + /// true if [time scale visible]; otherwise, false. + /// + public bool TimeScaleVisible + { + get { return Calendar.DaysMode == CalendarDaysMode.Expanded; } + } + + /// + /// Gets the width of the timescale + /// + /// + /// The width of the time scale. + /// + public virtual int TimeScaleWidth + { + get + { + if( _timeScaleWidth == 0 ) + { + _timeScaleWidth = 60; + } + return _timeScaleWidth; + } + } + + /// + /// Gets the width of the week header. + /// + /// + /// The width of the week header. + /// + public virtual int WeekHeaderWidth + { + get + { + if( _weekHeaderWidth == 0 ) + { + _weekHeaderWidth = TextRenderer.MeasureText( "Ag", Calendar.Font ).Height + 4; + } + + return _weekHeaderWidth; + } + } + + #endregion + + /// + /// Creates a new renderer for the specified calendar + /// + /// + public CalendarRenderer(Calendar calendar) + { + if (calendar == null) + { + throw new ArgumentNullException("calendar"); + } + + _calendar = calendar; + _allDayItemsPadding = 5; + _itemsPadding = 5; + _itemTextMargin = new Padding(3); + _itemShadowPadding = 4; + _itemInvalidateMargin = 0; + } + + #region Public Methods + + /// + /// Gets the exact Y coordinate that corresponds to the specified time. + /// This only works when in Expanded mode. + /// + /// Time of day to get Y coordinate + /// + /// Y coordinate corresponding to the specified time + /// + /// When calendar is not in Expaned mode. + public int GetTimeY(TimeSpan time) + { + if (Calendar.DaysMode != CalendarDaysMode.Expanded) + throw new InvalidOperationException("Can't measure Time's Y when calendar isn't in Expanded mode"); + + //If no days, no Y + if (Calendar.Days == null || Calendar.Days.Length == 0) + return 0; + + CalendarDay fisrtDay = Calendar.Days[0]; + CalendarTimeScaleUnit firstUnit = fisrtDay.TimeUnits[0]; + double duration = Convert.ToDouble(firstUnit.Duration.TotalMinutes); + double totalmins = time.TotalMinutes; + int unitIndex = Convert.ToInt32(Math.Floor(totalmins / duration)); + double module = Convert.ToInt32(Math.Floor(totalmins % duration)); + + CalendarTimeScaleUnit unit = Calendar.Days[0].TimeUnits[unitIndex]; + + int minuteHeight = Convert.ToInt32(Convert.ToDouble(unit.Bounds.Height) / duration); + + return unit.Bounds.Top + minuteHeight * Convert.ToInt32(module); + + } + + /// + /// Creates a rectangle with item roundess + /// + /// The instance containing the event data. + /// The bounds. + /// + public GraphicsPath ItemRectangle(CalendarRendererItemBoundsEventArgs evtData, Rectangle bounds) + { + int pointerPadding = 5; + + + if ((evtData.Item.Bounds.Top != evtData.Item.MinuteStartTop || + evtData.Item.Bounds.Bottom != evtData.Item.MinuteEndTop) && + (evtData.Item.MinuteEndTop != 0 && evtData.Item.MinuteStartTop != 0) && + ! evtData.Item.IsOnDayTop && evtData.Calendar.DaysMode == CalendarDaysMode.Expanded) + { + /* + * Trace pointed item + * + * C--------------------D + * | | + * A---B | + * | | + * H---G | + * | | + * F--------------------E + */ + + int sq = ItemRoundness * 2; + Point a = new Point(bounds.Left, evtData.Item.MinuteStartTop); + Point b = new Point(a.X + pointerPadding, a.Y); + Point c = new Point(b.X, bounds.Top); + Point d = new Point(bounds.Right, c.Y); + Point e = new Point(d.X, bounds.Bottom); + Point f = new Point(b.X, e.Y); + Point g = new Point(b.X, evtData.Item.MinuteEndTop); + Point h = new Point(a.X, g.Y); + + + GraphicsPath path = new GraphicsPath(); + + path.AddLine(a, b); + path.AddLine(b, c); + path.AddLine(c, new Point(d.X - sq, d.Y)); + path.AddArc(new Rectangle(d.X - sq, d.Y, sq, sq), -90, 90); + path.AddLine(new Point(d.X, d.Y + sq), new Point(d.X, e.Y - sq)); + path.AddArc(new Rectangle(e.X - sq, e.Y - sq, sq, sq), 0, 90); + path.AddLine(new Point(e.X - sq, e.Y), f); + path.AddLine(f, g); + path.AddLine(g, h); + path.AddLine(h, a); + + path.CloseFigure(); + + return path; + + } + else + { + Corners crns = Corners.None; + + if (evtData.IsFirst) + { + crns |= Corners.West; + } + + if (evtData.IsLast) + { + crns |= Corners.East; + } + + return RoundRectangle(bounds, ItemRoundness, crns); + } + } + + /// + /// Fills the specified rectangle with item border roundness + /// + /// The instance containing the event data. + /// The bounds. + /// The north. + /// The south. + public void ItemFill(CalendarRendererItemBoundsEventArgs e, Rectangle bounds, Color north, Color south) + { + if (bounds.Width <= 0 || bounds.Height <= 0) + { + return; + } + + using (GraphicsPath r = ItemRectangle(e, bounds)) + { + using (LinearGradientBrush b = new LinearGradientBrush(bounds, north, south, 90)) + { + e.Graphics.FillPath(b, r); + } + } + } + + /// + /// Items the pattern. + /// + /// The instance containing the event data. + /// The bounds. + /// Color of the pattern. + public void ItemPattern(CalendarRendererItemBoundsEventArgs e, Rectangle bounds, Color patternColor) + { + if (bounds.Width <= 0 || bounds.Height <= 0) + { + return; + } + + using (GraphicsPath r = ItemRectangle(e, bounds)) + { + using (Brush b = new HatchBrush(e.Item.Pattern, patternColor, Color.Transparent)) + { + e.Graphics.FillPath(b, r); + } + } + } + + /// + /// Draws the specified rectangle with item border roundnesss + /// + /// The instance containing the event data. + /// The bounds. + /// The color. + /// The width. + public void ItemBorder(CalendarRendererItemBoundsEventArgs e, Rectangle bounds, Color color, float width) + { + using (GraphicsPath r = ItemRectangle(e, bounds)) + { + using (Pen p = new Pen(color, width)) + { + e.Graphics.DrawPath(p, r); + } + } + } + + /// + /// Peform layout of elements and items of the calendar + /// + public void PerformLayout() + { + PerformLayout(true); + } + + /// + /// Updates the bounds of graphical elements. + /// Optionally calls to update bounds of items. + /// + /// + /// This method is called every time the control is resized. + /// + public void PerformLayout(bool performItemsLayout) + { + if (Calendar.Days == null) return; + + int leftStart = 0; + int curLeft = 0; + int curTop = 0; + int dayWidth = 0; + int dayHeight = 0; + int scrollBarWidth = 20; + + TimeScaleBounds = Rectangle.Empty; + + if (Calendar.DaysMode == CalendarDaysMode.Expanded) + { + #region Expanded days + TimeScaleBounds = new Rectangle(0, 0, TimeScaleWidth, Calendar.ClientRectangle.Height); + curLeft = TimeScaleBounds.Right; + dayHeight = Calendar.ClientSize.Height - 1; + dayWidth = (Calendar.ClientSize.Width - TimeScaleBounds.Width - scrollBarWidth) / Calendar.Days.Length; + + for (int i = 0; i < Calendar.Days.Length; i++) + { + CalendarDay day = Calendar.Days[i]; + day.SetBounds(new Rectangle(curLeft, curTop, dayWidth, dayHeight)); + day.DayTop.SetBounds(new Rectangle(curLeft, day.HeaderBounds.Bottom, dayWidth, DayTopHeight)); + curLeft += dayWidth + 1; + //int k = 0; + int utop = day.BodyBounds.Top + Calendar.TimeUnitsOffset * TimeScaleUnitHeight; + + for (int j = 0; j < day.TimeUnits.Length; j++) + { + CalendarTimeScaleUnit unit = day.TimeUnits[j]; + + if (Calendar.TimeUnitsOffset * -1 >= (j + 1)) + { + unit.SetVisible(false); + } + else + { + unit.SetVisible(true); + //unit.SetBounds(new Rectangle(day.Bounds.Left, day.BodyBounds.Top + k++ * TimeScaleUnitHeight, day.Bounds.Width, TimeScaleUnitHeight)); + } + unit.SetBounds(new Rectangle(day.Bounds.Left, utop, day.Bounds.Width, TimeScaleUnitHeight)); + utop += TimeScaleUnitHeight; + } + } + #endregion + } + else + { + #region Short days (Calendar View) + leftStart = WeekHeaderWidth; + curLeft = leftStart; + curTop = DayNameHeadersHeight; + dayWidth = (Calendar.ClientSize.Width - leftStart - scrollBarWidth) / 7; + dayHeight = (Calendar.ClientSize.Height - curTop) / (Calendar.Days.Length / 7) - 1; + _dayNameHeaderColumns = new Rectangle[7]; + int j = 0; + + for (int i = 0; i < Calendar.Days.Length; i++) + { + Calendar.Days[i].SetBounds(new Rectangle(curLeft, curTop, dayWidth, dayHeight)); + curLeft += dayWidth + 1; + + if ((i + 1) % 7 == 0) + { + curTop += dayHeight + 1; + curLeft = leftStart; + } + + if (i < _dayNameHeaderColumns.Length) + { + _dayNameHeaderColumns[i] = new Rectangle(curLeft, 0, dayWidth, DayNameHeadersHeight); + } + + if (Calendar.Days[i].Date.DayOfWeek == Calendar.FirstDayOfWeek) + { + Calendar.Weeks[j++].SetBounds(new Rectangle(0, curTop, Calendar.ClientSize.Width, dayHeight)); + } + } + #endregion + } + + if(performItemsLayout) + PerformItemsLayout(); + } + + /// + /// Updates the bounds of CalendarItems + /// + public void PerformItemsLayout() + { + if (Calendar.Days == null || Calendar.Items.Count == 0) return; + bool alldaychanged = false; + int offset = Math.Abs(Calendar.TimeUnitsOffset); + List itemsOnScene = new List(); + + foreach (CalendarDay day in Calendar.Days) + day.ContainedItems.Clear(); + + if (Calendar.DaysMode == CalendarDaysMode.Expanded) + { + #region Expanded mode algorithm + + #region Assign units and initial coords + + int maxItemsOnDayTop = 0; + + foreach (CalendarItem item in Calendar.Items) + { + item.ClearBounds(); + item.ClearPassings(); + + if (item.IsOnDayTop) + { + #region Among day tops + + CalendarDay dayStart = item.DayStart; + CalendarDay dayEnd = item.DayEnd; + + if (dayStart == null) dayStart = Calendar.Days[0]; + if (dayEnd == null) dayEnd = Calendar.Days[Calendar.Days.Length - 1]; + + for (int i = dayStart.Index; i <= dayEnd.Index; i++) + { + item.AddTopPassing(Calendar.Days[i].DayTop); + Calendar.Days[i].DayTop.AddPassingItem(item); + } + + item.SetBounds(Rectangle.FromLTRB(dayStart.DayTop.Bounds.Left, 0, dayEnd.DayTop.Bounds.Right, 1)); + + #endregion + } + else + { + #region Among time units + + CalendarDay day = item.DayStart; if (day == null) continue; + double unitDurationMinutes = Convert.ToDouble((int)Calendar.TimeScale); + DateTime date1 = item.StartDate; + DateTime date2 = item.EndDate; + + int indexStart = Convert.ToInt32(Math.Floor(date1.TimeOfDay.TotalMinutes / unitDurationMinutes)); + int indexEnd = Convert.ToInt32(Math.Ceiling(date2.TimeOfDay.TotalMinutes / unitDurationMinutes)); + + for (int i = 0; i < day.TimeUnits.Length; i++) + { + if (i >= indexStart && i < indexEnd) + { + day.TimeUnits[i].AddPassingItem(item); + item.AddUnitPassing(day.TimeUnits[i]); + } + } + + item.SetBounds(Rectangle.Empty); + itemsOnScene.Add(item); + + #endregion + } + } + + //Calendar.Items.Sort(CompareItems); + #endregion + + #region Items on DayTops + foreach (CalendarDay day in Calendar.Days) + { + maxItemsOnDayTop = Math.Max(maxItemsOnDayTop, day.DayTop.PassingItems.Count); + } + + int[,] tmatix = new int[Calendar.Days.Length, maxItemsOnDayTop]; + + if (tmatix.GetLength(1) > 0) + { + foreach (CalendarItem item in Calendar.Items) + { + if (!item.IsOnDayTop) continue; + + item.TopsPassing.Sort(CompareTops); + + int topStart = item.TopsPassing[0].Day.Index; + int topEnd = item.TopsPassing[item.TopsPassing.Count - 1].Day.Index; + + PlaceInMatrix(ref tmatix, Calendar.Items.IndexOf(item) + 1, topStart, topEnd); + } + + int dayTopsHeight = tmatix.GetLength(1) * StandardItemHeight + DayTopMinHeight; + + if (DayTopHeight != dayTopsHeight) + { + DayTopHeight = dayTopsHeight; + alldaychanged = true; + } + + int itemHeight = StandardItemHeight;//Convert.ToInt32(Math.Floor(Convert.ToSingle(DayTopHeight) / Convert.ToSingle(tmatix.GetLength(1)))); + + foreach (CalendarItem item in Calendar.Items) + { + if (!item.IsOnDayTop) continue; + + int index = Calendar.Items.IndexOf(item); + + int top, left; + FindInMatrix(tmatix, index + 1, out left, out top); + + Rectangle r = item.Bounds; + r.Y = Calendar.Days[0].DayTop.Bounds.Top + top * itemHeight; + r.Height = itemHeight; + item.SetBounds(r); + item.FirstAndLastRectangleGapping(); + } + } + if (alldaychanged) + PerformLayout(false); + #endregion + + foreach (CalendarDay day in Calendar.Days) + { + #region Create groups + + maxItemsOnDayTop = Math.Max(maxItemsOnDayTop, day.DayTop.PassingItems.Count); + + List> groups = new List>(); + List items = new List(day.ContainedItems); + + while (items.Count > 0) + { + List group = new List(); + + CollectIntersectingGroup(items[0], items, group); + + groups.Add(group); + + foreach (CalendarItem item in group) + items.Remove(item); + } + + #endregion + + foreach (List group in groups) + { + #region Create group matrix + + int maxConcurrent = 0; + int startIndex, endIndex; + GetGroupBoundUnits(group, out startIndex, out endIndex); + + //Get the maximum concurrent items + for (int i = startIndex; i <= endIndex; i++) maxConcurrent = Math.Max(day.TimeUnits[i].PassingItems.Count, maxConcurrent); + + int[,] matix = new int[maxConcurrent, endIndex - startIndex + 1]; + + foreach (CalendarItem item in group) + { + int x = 0; + item.UnitsPassing.Sort(CompareUnits); + int unitStart = item.UnitsPassing[0].Index - startIndex; + int unitEnd = unitStart + item.UnitsPassing.Count - 1; + bool xFound = false; + + //if (startIndex + unitEnd < offset) + //{ + // item.SetIsOnView(false); + // continue; + //} + //else + //{ + // item.SetIsOnView(true); + //} + + while (!xFound) + { + xFound = true; + + for (int i = unitStart; i <= unitEnd; i++) + { + if (matix[x, i] != 0) + { + xFound = false; + break; + } + } + if (!xFound) x++; + } + + for (int i = unitStart; i <= unitEnd; i++) + { + matix[x, i] = group.IndexOf(item) + 1; + } + } + #endregion + + #region Expand Items + foreach (CalendarItem item in group) + { + int index = group.IndexOf(item); + int left, top; + int height = item.UnitsPassing.Count; + int width = 1; + FindInMatrix(matix, index + 1, out left, out top); + + + bool canExpand = left >= 0 && top >= 0; + while (canExpand) + { + for (int i = top; i < top + height; i++) + { + if (matix.GetLength(0) <= left + width || matix[left + width, i] != 0) + { + canExpand = false; + break; + } + } + + if (canExpand) + { + for (int i = top; i < top + height; i++) + { + matix[left + width, i] = index + 1; + } + width++; + } + } + } + #endregion + + #region Matrix to rectangles + + int itemWidth = Convert.ToInt32(Math.Floor(Convert.ToSingle(day.Bounds.Width - ItemsPadding) / Convert.ToSingle(matix.GetLength(0)))); + + foreach (CalendarItem item in group) + { + int index = group.IndexOf(item); + int top, left; + int width = 1; + FindInMatrix(matix, index + 1, out left, out top); + + if (left >= 0 && top >= 0) + { + for (int i = left + 1; i < matix.GetLength(0); i++) + { + if (matix[i, top] == index + 1) + { + width++; + } + else + { + break; + } + } + } + + int rtop = day.TimeUnits[item.UnitsPassing[0].Index].Bounds.Top; + int bottom = day.TimeUnits[item.UnitsPassing[item.UnitsPassing.Count - 1].Index].Bounds.Bottom; + int rleft = day.Bounds.Left + left * itemWidth; + int right = rleft + itemWidth * width; + item.SetBounds(Rectangle.FromLTRB(rleft, rtop, right, bottom)); + item.SetMinuteStartTop(GetTimeY(item.StartDate.TimeOfDay)); + item.SetMinuteEndTop(GetTimeY(item.EndDate.TimeOfDay)); + + } + + #endregion + } + } + #endregion + } + else if (Calendar.DaysMode == CalendarDaysMode.Short) + { + #region Short mode algorithm + + Calendar.Items.Reverse(); + + for (int i = 0; i < Calendar.Days.Length; i++) + { + Calendar.Days[i].ContainedItems.Clear(); + Calendar.Days[i].SetOverflowEnd(false); + Calendar.Days[i].SetOverflowStart(false); + } + + int maxItems = 0; + + foreach (CalendarItem item in Calendar.Items) + { + CalendarDay dayStart = item.DayStart; + CalendarDay dayEnd = item.DayEnd; + item.ClearBounds(); + + for (int i = dayStart.Index; i <= dayEnd.Index; i++) + { + Calendar.Days[i].AddContainedItem(item); + maxItems = Math.Max(maxItems, Calendar.Days[i].ContainedItems.Count); + } + } + + int[,] matix = new int[Calendar.Days.Length, maxItems]; + int curIndex = 0; + foreach (CalendarItem item in Calendar.Items) + { + CalendarDay dayStart = item.DayStart; + CalendarDay dayEnd = item.DayEnd; + + PlaceInMatrix(ref matix, curIndex + 1, dayStart.Index, dayEnd.Index); + curIndex++; + } + + + for (int week = 0; week < Calendar.Weeks.Length; week++) + { + int xStart = week * 7; + int xEnd = xStart + 6; + int index = 0; + int[,] wmatix = new int[7, matix.GetLength(1)]; + CalendarDay sunday = Calendar.FindDay(Calendar.Weeks[week].StartDate); + + #region Fill week matrix + + for (int i = 0; i < wmatix.GetLength(1); i++) + for (int j = 0; j < wmatix.GetLength(0); j++) + wmatix[j, i] = matix[j + xStart, i]; + + #endregion + + foreach (CalendarItem item in Calendar.Items) + { + int left, top, width = 0; + + FindInMatrix(wmatix, ++index, out left, out top); + + if (left < 0 || top < 0) continue; + + for (int i = left; i < wmatix.GetLength(0); i++) + if (wmatix[i, top] == index) + width++; + else + break; + + + CalendarDay dayStart = Calendar.Days[xStart + left]; + CalendarDay dayEnd = Calendar.Days[xStart + left + width - 1]; + Rectangle rStart = dayStart.Bounds; + Rectangle rEnd = dayEnd.Bounds; + int rtop = rStart.Top + DayHeaderHeight + top * StandardItemHeight; + Rectangle r = Rectangle.FromLTRB(rStart.Left, rtop, rEnd.Right, rtop + StandardItemHeight); + + if (r.Bottom <= sunday.Bounds.Bottom) + item.AddBounds(r); + else + for (int i = dayStart.Index; i <= dayEnd.Index; i++) + Calendar.Days[i].SetOverflowEnd(true); + + } + } + + foreach (CalendarItem item in Calendar.Items) + item.FirstAndLastRectangleGapping(); + + Calendar.Items.Reverse(); + + #endregion + } + + Calendar.RaiseItemsPositioned(); + } + + /// + /// Places the specified item in the matrix for the layout engine purposes + /// + /// + /// + /// + /// + private void PlaceInMatrix(ref int[,] m, int index, int startX, int endX) + { + int y = 0; + bool yFound = false; + + while (!yFound && y < m.GetLength(1)) //HACK: && y < m.GetLength(1) //This is Because of some bug, possible item not showing + { + yFound = true; + + for (int i = startX; i <= endX; i++) + { + if (i >= 0 && i < m.GetLength(0) && + m[i, y] != 0) + { + yFound = false; + break; + } + } + + if (!yFound) y++; + } + + + if (y < m.GetLength(1)) //HACK: This if is because of same bug + { + for (int i = startX; i <= endX; i++) + { + m[i, y] = index; + } + } + } + + #endregion + + #region Private Methods + + /// + /// Gets the amout of units that can be displayed on the calendar viewport + /// + internal int GetVisibleTimeUnits() + { + if (Calendar.DaysMode == CalendarDaysMode.Short) + { + return 0; + } + else if (Calendar.Days != null && Calendar.Days.Length > 0) + { + return Convert.ToInt32(Math.Floor( + Convert.ToSingle(Calendar.Days[0].BodyBounds.Height) / Convert.ToSingle(TimeScaleUnitHeight) + )); + } + else + { + return 0; + } + } + + /// + /// Sets the value of the property + /// + /// Height of all elements + protected void SetDayTopHeight(int height) + { + _dayTopHeight = height; + } + + /// + /// Sets the value of the property + /// + /// Height of the day header + protected void SetDayHeaderHeight(int height) + { + _dayHeaderHeight = height; + } + + /// + /// Sets the value of the property + /// + /// Height of the day name headers + protected void SetDayNameHeadersHeight(int height) + { + _dayNameHeadersHeight = height; + } + + /// + /// Sets the value of the property + /// + /// Height of the time scale unit + protected void SetTimeScaleUnitHeight(int height) + { + _timeScaleUnitHeight = height; + } + + /// + /// Sets the value of the property + /// + /// New width for the time scale + protected void SetTimeScaleWidth(int width) + { + _timeScaleWidth = width; + } + + /// + /// Draws text using the information of the + /// + /// + protected virtual void DrawStandarBoxText(CalendarRendererBoxEventArgs e) + { + TextRenderer.DrawText(e.Graphics, e.Text, e.Font, e.Bounds, e.TextColor, e.Format); + } + + /// + /// Outs the location of the specified number in the matrix + /// + /// Matrix to search in + /// Number to find + /// Result left + /// Result top + private void FindInMatrix(int[,] m, int number, out int left, out int top) + { + for (int i = 0; i < m.GetLength(1); i++) + { + for (int j = 0; j < m.GetLength(0); j++) + { + if (m[j, i] == number) + { + left = j; + top = i; + return; + } + } + } + + left = top = -1; + } + + /// + /// Outs the startIndex and the endIndex of units in the group + /// + /// + /// + /// + private void GetGroupBoundUnits(List group, out int startIndex, out int endIndex) + { + startIndex = int.MaxValue; + endIndex = int.MinValue; + + foreach (CalendarItem item in group) + { + foreach (CalendarTimeScaleUnit unit in item.UnitsPassing) + { + startIndex = Math.Min(startIndex, unit.Index); + endIndex = Math.Max(endIndex, unit.Index); + } + } + } + + /// + /// Recursive method that collects items intersecting on time, to graphically represent-them on the layout + /// + /// + /// + /// + private void CollectIntersectingGroup(CalendarItem calendarItem, List items, List grouped) + { + if (!grouped.Contains(calendarItem)) + grouped.Add(calendarItem); + + foreach (CalendarItem item in items) + { + if (!grouped.Contains(item) && + calendarItem.IntersectsWith(item.StartDate.TimeOfDay, item.EndDate.TimeOfDay)) + { + grouped.Add(item); + + CollectIntersectingGroup(item, items, grouped); + } + } + } + + /// + /// Prints the specified matrix on debug + /// + /// + private void PrintMatrix(int[,] m) + { + //return; + Console.WriteLine("--------------------------------"); + for (int i = 0; i < m.GetLength(1); i++) + { + for (int j = 0; j < m.GetLength(0); j++) + { + Console.Write(string.Format(" {0}", m[j, i])); + } + Console.WriteLine(" "); + } + Console.WriteLine("--------------------------------"); + } + + #endregion + + #region Render Methods + + /// + /// Initializes the Calendar + /// + /// + public virtual void OnInitialize(CalendarRendererEventArgs e) + { + + } + + /// + /// Paints the background of the calendar + /// + /// Paint info + public virtual void OnDrawBackground(CalendarRendererEventArgs e) + { + } + + /// + /// Paints the timescale of the calendar + /// + /// Paint info + public virtual void OnDrawTimeScale(CalendarRendererEventArgs e) + { + if (e.Calendar.DaysMode == CalendarDaysMode.Short + || e.Calendar.Days == null + || e.Calendar.Days.Length == 0 + || e.Calendar.Days[0].TimeUnits == null + ) return; + + Font hourFont = new Font(e.Calendar.Font.FontFamily, e.Calendar.Font.Size * (e.Calendar.TimeScale == CalendarTimeScale.SixtyMinutes ? 1f : 1.5f)); + Font minuteFont = e.Calendar.Font; + int hourLeft = TimeScaleBounds.Left; + int hourWidth = TimeScaleBounds.Left + TimeScaleBounds.Width / 2; + int minuteLeft = hourLeft + hourWidth; + int minuteWidth = hourWidth; + int k = 0; + + for (int i = 0; i < e.Calendar.Days[0].TimeUnits.Length; i++) + { + CalendarTimeScaleUnit unit = e.Calendar.Days[0].TimeUnits[i]; + + if (!unit.Visible) continue; + + string hours = unit.Hours.ToString("00"); + string minutes = unit.Minutes == 0 ? "00" : string.Empty; + + if (!string.IsNullOrEmpty(minutes)) + { + switch( _calendar.CalendarTimeFormat ) + { + case CalendarTimeFormat.TwelveHour: + if( Convert.ToInt32( hours ) > 12 ) hours = ( Convert.ToInt32( hours ) - 12 ).ToString(); + break; + + case CalendarTimeFormat.TwentyFourHour: + if( hours == "00" ) hours = "12"; + break; + } + + CalendarRendererBoxEventArgs hevt = new CalendarRendererBoxEventArgs(e, new Rectangle(hourLeft, unit.Bounds.Top, hourWidth, unit.Bounds.Height), hours, TextFormatFlags.Right); + + hevt.Font = hourFont; + + OnDrawTimeScaleHour(hevt); + + if (k++ == 0 || unit.Hours == 0 || unit.Hours == 12 ) minutes = unit.Date.ToString("tt"); + + CalendarRendererBoxEventArgs mevt = new CalendarRendererBoxEventArgs(e, new Rectangle(minuteLeft, unit.Bounds.Top, minuteWidth, unit.Bounds.Height), minutes, TextFormatFlags.Top | TextFormatFlags.Left); + + mevt.Font = minuteFont; + + OnDrawTimeScaleMinutes(mevt); + } + } + } + + /// + /// Paints an hour of a timescale unit + /// + /// Paint Info + public virtual void OnDrawTimeScaleHour(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Paints minutes of a timescale unit + /// + /// Paint Info + public virtual void OnDrawTimeScaleMinutes(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Paints the days on the current calendar view + /// + /// Paint Info + public virtual void OnDrawDays(CalendarRendererEventArgs e) + { + for (int i = 0; i < e.Calendar.Days.Length; i++) + { + CalendarDay day = e.Calendar.Days[i]; + + e.Tag = day; + + OnDrawDay(new CalendarRendererDayEventArgs(e, + day)); + } + } + + /// + /// Paints the specified day on the calendar + /// + /// Paint info + public virtual void OnDrawDay(CalendarRendererDayEventArgs e) + { + CalendarDay day = e.Day; + + CalendarRendererBoxEventArgs hevt = new CalendarRendererBoxEventArgs(e, + day.HeaderBounds, + day.Date.Day.ToString(), + TextFormatFlags.VerticalCenter); + hevt.Font = new Font(Calendar.Font, FontStyle.Bold); + + CalendarRendererBoxEventArgs devt = new CalendarRendererBoxEventArgs(e, + day.HeaderBounds, + day.Date.ToString("dddd"), + TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter); + + OnDrawDayHeaderBackground(e); + + if (Calendar.DaysMode == CalendarDaysMode.Short && (day.Index == 0 || day.Date.Day == 1)) + { + hevt.Text = day.Date.ToString("dd MMM"); + } + + OnDrawDayHeaderText(hevt); + + if (devt.TextSize.Width < day.HeaderBounds.Width - hevt.TextSize.Width * 2 + && e.Calendar.DaysMode == CalendarDaysMode.Expanded) + { + OnDrawDayHeaderText(devt); + } + + + + OnDrawDayTimeUnits(e); + OnDrawDayTop(e); + OnDrawDayBorder(e); + } + + /// + /// Paints the border of the specified day + /// + /// + public virtual void OnDrawDayBorder(CalendarRendererDayEventArgs e) + { + + } + + /// + /// Draws the all day items area + /// + /// Paint Info + public virtual void OnDrawDayTop(CalendarRendererDayEventArgs e) + { + } + + /// + /// Paints the background of the specified day's header + /// + /// + public virtual void OnDrawDayHeaderBackground(CalendarRendererDayEventArgs e) + { + + } + + /// + /// Paints the header of the specified day + /// + /// Paint info + public virtual void OnDrawDayHeaderText(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawDayTimeUnits(CalendarRendererDayEventArgs e) + { + for (int i = 0; i < e.Day.TimeUnits.Length; i++) + { + CalendarTimeScaleUnit unit = e.Day.TimeUnits[i]; + + if(unit.Visible) + OnDrawDayTimeUnit(new CalendarRendererTimeUnitEventArgs(e, unit)); + } + } + + /// + /// Draws a time unit of a day + /// + /// + public virtual void OnDrawDayTimeUnit(CalendarRendererTimeUnitEventArgs e) + { + + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawDayNameHeaders(CalendarRendererEventArgs e) + { + DateTime startDate = DateTime.Now.AddDays(-((int)DateTime.Now.DayOfWeek % 7) + 1 + (int)Calendar.FirstDayOfWeek); + + for (int i = 0; i < DayNameHeaderColumns.Length; i++) + { + OnDrawDayNameHeader(new CalendarRendererBoxEventArgs(e, + DayNameHeaderColumns[i], + startDate.AddDays(i).ToString("dddd"), + TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter)); + + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawDayNameHeader(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Draws the items of the calendar + /// + /// Event info + public virtual void OnDrawItems(CalendarRendererEventArgs e) + { + Rectangle days = e.Calendar.DaysBodyRectangle; days.Inflate(-1, -1); + Region oldclip = e.Graphics.Clip; + bool doClip = e.Calendar.DaysMode == CalendarDaysMode.Expanded; + bool clipped = false; + + #region Shadows + foreach (CalendarItem item in e.Calendar.Items) + { + clipped = false; + + if (doClip && !item.IsOnDayTop && item.Bounds.Top < days.Top) + { + e.Graphics.SetClip(days, CombineMode.Intersect); + clipped = true; + } + + List rects = new List(item.GetAllBounds()); + + for (int i = 0; i < rects.Count; i++) + { + CalendarRendererItemBoundsEventArgs evt = new CalendarRendererItemBoundsEventArgs( + new CalendarRendererItemEventArgs(e, item), + rects[i], + i == 0 && !item.IsOpenStart, + (i == rects.Count - 1) && !item.IsOpenEnd); + OnDrawItemShadow(evt); + } + + if (clipped) + e.Graphics.SetClip(oldclip, CombineMode.Replace); + } + #endregion + + #region Items + foreach (CalendarItem item in e.Calendar.Items) + { + clipped = false; + + if( doClip && !item.IsOnDayTop && item.Bounds.Top < days.Top ) + { + e.Graphics.SetClip( days, CombineMode.Intersect ); + clipped = true; + } + + OnDrawItem(new CalendarRendererItemEventArgs(e, item)); + + if( clipped ) + { + e.Graphics.SetClip( oldclip, CombineMode.Replace ); + } + } + #endregion + + #region Borders of selected items + foreach (CalendarItem item in e.Calendar.Items) + { + if (!item.Selected) continue; + + List rects = new List(item.GetAllBounds()); + + for (int i = 0; i < rects.Count; i++) + { + CalendarRendererItemBoundsEventArgs evt = new CalendarRendererItemBoundsEventArgs( + new CalendarRendererItemEventArgs(e, item), + rects[i], + i == 0 && !item.IsOpenStart, + (i == rects.Count - 1) && !item.IsOpenEnd); + + SmoothingMode smbuff = e.Graphics.SmoothingMode; + e.Graphics.SmoothingMode = SmoothingMode.HighQuality; + + OnDrawItemBorder(evt); + + e.Graphics.SmoothingMode = smbuff; + } + + } + #endregion + } + + /// + /// Draws an item of the calendar + /// + /// Event Info + public virtual void OnDrawItem( CalendarRendererItemEventArgs e ) + { + List rects = new List( e.Item.GetAllBounds() ); + + for( int i = 0; i < rects.Count; i++ ) + { + CalendarRendererItemBoundsEventArgs evt = new CalendarRendererItemBoundsEventArgs( + e, + rects[i], + i == 0 && !e.Item.IsOpenStart, + ( i == rects.Count - 1 ) && !e.Item.IsOpenEnd ); + + OnDrawItemBackground( evt ); + + if( !evt.Item.PatternColor.IsEmpty ) + { + OnDrawItemPattern( evt ); + } + + if( !e.Item.IsEditing ) + { + OnDrawItemContent( evt ); + } + + OnDrawItemBorder( evt ); + + } + } + + /// + /// Draws the background of the specified item + /// + /// Event Info + public virtual void OnDrawItemBackground(CalendarRendererItemBoundsEventArgs e) + { + + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawItemPattern(CalendarRendererItemBoundsEventArgs e) + { + foreach (Rectangle bounds in e.Item.GetAllBounds()) + { + ItemPattern(e, bounds, e.Item.PatternColor); + } + } + + /// + /// Draws the strings of an item. Strings inlude StartTime, EndTime and Text + /// + /// Event Info + public virtual void OnDrawItemContent(CalendarRendererItemBoundsEventArgs e) + { + if (e.Item == e.Calendar.EditModeItem) return; + + List rectangles = new List(e.Item.GetAllBounds()); + + for (int i = 0; i < rectangles.Count; i++) + { + Rectangle bounds = rectangles[i]; + Rectangle imageBounds = Rectangle.Empty; + Rectangle rStartTime = new Rectangle(); + Rectangle rEndTime = new Rectangle(); + string endTime = string.Empty; + string startTime = string.Empty; + Color secondaryForecolor = e.Item.ForeColor; + + if (e.Item.ShowEndTime && i == rectangles.Count - 1) + { + endTime = e.Item.EndDateText; + rEndTime = new Rectangle(Point.Empty, TextRenderer.MeasureText(endTime, e.Calendar.Font)); + rEndTime = Rectangle.FromLTRB(bounds.Right - rEndTime.Width - ItemTextMargin.Right, + bounds.Top + ItemTextMargin.Top, + bounds.Right - ItemTextMargin.Right, + bounds.Bottom - ItemTextMargin.Bottom); + OnDrawItemEndTime(new CalendarRendererBoxEventArgs(e, rEndTime, endTime, secondaryForecolor)); + } + + if (e.Item.ShowStartTime && i == 0) + { + startTime = e.Item.StartDateText; + rStartTime = new Rectangle(Point.Empty, TextRenderer.MeasureText(startTime, e.Calendar.Font)); + rStartTime.X = bounds.Left + ItemTextMargin.Left; + rStartTime.Y = bounds.Top + ItemTextMargin.Top; + rStartTime.Height = bounds.Height - ItemTextMargin.Vertical; + OnDrawItemStartTime(new CalendarRendererBoxEventArgs(e, rStartTime, startTime, secondaryForecolor)); + } + + Rectangle r = Rectangle.FromLTRB( + bounds.Left + ItemTextMargin.Left + rStartTime.Width, + bounds.Top + ItemTextMargin.Top, + bounds.Right - ItemTextMargin.Right - rEndTime.Width, + bounds.Bottom - ItemTextMargin.Bottom); + + CalendarRendererBoxEventArgs evt = new CalendarRendererBoxEventArgs(e, r, e.Item.Text, TextFormatFlags.Left | TextFormatFlags.Top); + + evt.Font = e.Item.Font; + + if( e.Item.ShowStartTime || e.Item.ShowEndTime ) + { + evt.Font = new Font( evt.Font, FontStyle.Bold ); + } + + if( e.Item.IsOnDayTop || Calendar.DaysMode == CalendarDaysMode.Short ) + { + evt.Format |= TextFormatFlags.HorizontalCenter; + } + + if (!e.Item.ForeColor.IsEmpty) + { + evt.TextColor = e.Item.ForeColor; + } + + evt.Tag = e.Item; + + #region Image + + if (e.Item.Image != null) + { + Rectangle tBounds = e.Item.Bounds; + imageBounds.Size = e.Item.Image.Size; + + switch (e.Item.ImageAlign) + { + case CalendarItemImageAlign.North: + tBounds.Height -= imageBounds.Height; + tBounds.Y += imageBounds.Height; + imageBounds.Y = tBounds.Y - imageBounds.Height; + break; + case CalendarItemImageAlign.South: + tBounds.Height -= imageBounds.Height; + imageBounds.Y = tBounds.Bottom; + break; + case CalendarItemImageAlign.East: + tBounds.Width -= imageBounds.Width; + imageBounds.X = tBounds.Right; + break; + case CalendarItemImageAlign.West: + tBounds.Width -= imageBounds.Width; + tBounds.X += imageBounds.Width; + imageBounds.X = tBounds.Left - imageBounds.Width; + break; + } + + switch (e.Item.ImageAlign) + { + case CalendarItemImageAlign.North: + case CalendarItemImageAlign.South: + imageBounds.X = e.Item.Bounds.X + ( ( e.Item.Bounds.Width - imageBounds.Width ) / 2); + break; + case CalendarItemImageAlign.East: + case CalendarItemImageAlign.West: + imageBounds.Y = e.Item.Bounds.Y + ((e.Item.Bounds.Height - imageBounds.Height) / 2); + break; + } + + evt.Bounds = tBounds; + OnDrawItemImage(new CalendarRendererItemBoundsEventArgs(e, imageBounds, false, false)); + } + + #endregion + + OnDrawItemText(evt); + } + } + + /// + /// Draws the text of an item + /// + /// + public virtual void OnDrawItemText(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Draws the image of an item + /// + /// + public virtual void OnDrawItemImage(CalendarRendererItemBoundsEventArgs e) + { + if (e.Item.Image != null) + { + e.Graphics.DrawImage(e.Item.Image, e.Bounds); + } + } + + /// + /// Draws the starttime of the item if applicable + /// + /// Event data + public virtual void OnDrawItemStartTime(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Draws the end time of the item if applicable + /// + /// Event data + public virtual void OnDrawItemEndTime(CalendarRendererBoxEventArgs e) + { + DrawStandarBoxText(e); + } + + /// + /// Draws the border of the specified item + /// + /// Event Info + public virtual void OnDrawItemBorder(CalendarRendererItemBoundsEventArgs e) + { + + } + + /// + /// Draws the shadow of the specified item + /// + /// + public virtual void OnDrawItemShadow(CalendarRendererItemBoundsEventArgs e) + { + + } + + /// + /// Draws the overflows of days + /// + /// + public virtual void OnDrawOverflows(CalendarRendererEventArgs e) + { + for (int i = 0; i < e.Calendar.Days.Length; i++) + { + CalendarDay day = e.Calendar.Days[i]; + + if (day.OverflowStart) + { + OnDrawDayOverflowStart(new CalendarRendererDayEventArgs(e, day)); + } + + if(day.OverflowEnd) + { + OnDrawDayOverflowEnd(new CalendarRendererDayEventArgs(e, day)); + } + } + } + + /// + /// Draws the overflow to start of specified day + /// + /// Event data + public virtual void OnDrawDayOverflowStart(CalendarRendererDayEventArgs e) + { + + } + + /// + /// Draws the overflow to end of specified day + /// + /// + public virtual void OnDrawDayOverflowEnd(CalendarRendererDayEventArgs e) + { + //e.Graphics.FillRectangle(Brushes.Red, e.Day.OverflowEndBounds); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawWeekHeaders(CalendarRendererEventArgs e) + { + if (Calendar.Weeks == null) return; + + for (int i = 0; i < Calendar.Weeks.Length; i++) + { + string str = Calendar.Weeks[i].ToStringLarge(); + SizeF sz = e.Graphics.MeasureString(str, e.Calendar.Font); + + if (sz.Width > Calendar.Weeks[i].HeaderBounds.Height) + { + str = Calendar.Weeks[i].ToStringShort(); + } + + OnDrawWeekHeader(new CalendarRendererBoxEventArgs(e, + Calendar.Weeks[i].HeaderBounds, str, TextFormatFlags.Default)); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public virtual void OnDrawWeekHeader(CalendarRendererBoxEventArgs e) + { + StringFormat sf = new StringFormat(); + sf.FormatFlags = StringFormatFlags.DirectionVertical | StringFormatFlags.DirectionRightToLeft | StringFormatFlags.NoWrap; + sf.LineAlignment = StringAlignment.Center; + sf.Alignment = StringAlignment.Center; + + using (SolidBrush b = new SolidBrush(e.TextColor)) + { + e.Graphics.DrawString(e.Text, e.Font, b, e.Bounds, sf); + } + + e.Graphics.ResetTransform(); + + sf.Dispose(); + } + + + + #endregion + + } +} diff --git a/WindowsFormsCalendar/Renderers/CalendarSystemRenderer.cs b/WindowsFormsCalendar/Renderers/CalendarSystemRenderer.cs new file mode 100644 index 0000000..a1b3fe9 --- /dev/null +++ b/WindowsFormsCalendar/Renderers/CalendarSystemRenderer.cs @@ -0,0 +1,479 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace WindowsFormsCalendar +{ + /// + /// CalendarRenderer that renders low-intensity calendar for slow computers + /// + public class CalendarSystemRenderer + : CalendarRenderer + { + #region Fields + private CalendarColorTable _colorTable; + private float _selectedItemBorder; + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// + public CalendarSystemRenderer( Calendar calendar ) + : base( calendar ) + { + ColorTable = new CalendarColorTable(); + SelectedItemBorder = 1; + } + + #region Properties + + /// + /// Gets or sets the for this renderer + /// + public CalendarColorTable ColorTable + { + get { return _colorTable; } + set { _colorTable = value; } + } + + /// + /// Gets or sets the size of the border of selected items + /// + public float SelectedItemBorder + { + get { return _selectedItemBorder; } + set { _selectedItemBorder = value; } + } + + #endregion + + #region Overrides + + /// + /// Paints the background of the calendar + /// + /// Paint info + public override void OnDrawBackground( CalendarRendererEventArgs e ) + { + e.Graphics.Clear( ColorTable.Background ); + } + + /// + /// Paints the specified day on the calendar + /// + /// Paint info + public override void OnDrawDay( CalendarRendererDayEventArgs e ) + { + Rectangle r = e.Day.Bounds; + + if( e.Day.Selected ) + { + using( Brush b = new SolidBrush( ColorTable.DayBackgroundSelected ) ) + { + e.Graphics.FillRectangle( b, r ); + } + } + else if( e.Day.Date.Month % 2 == 0 ) + { + using( Brush b = new SolidBrush( ColorTable.DayBackgroundEven ) ) + { + e.Graphics.FillRectangle( b, r ); + } + } + else + { + using( Brush b = new SolidBrush( ColorTable.DayBackgroundOdd ) ) + { + e.Graphics.FillRectangle( b, r ); + } + } + + base.OnDrawDay( e ); + } + + /// + /// Paints the border of the specified day + /// + /// + public override void OnDrawDayBorder( CalendarRendererDayEventArgs e ) + { + base.OnDrawDayBorder( e ); + + Rectangle r = e.Day.Bounds; + bool today = e.Day.Date.Date.Equals( DateTime.Today.Date ); + + using( Pen p = new Pen( today ? ColorTable.TodayBorder : ColorTable.DayBorder, today ? 2 : 1 ) ) + { + if( e.Calendar.DaysMode == CalendarDaysMode.Short ) + { + e.Graphics.DrawLine( p, r.Right, r.Top, r.Right, r.Bottom ); + e.Graphics.DrawLine( p, r.Left, r.Bottom, r.Right, r.Bottom ); + + if( e.Day.Date.DayOfWeek == DayOfWeek.Sunday || today ) + { + e.Graphics.DrawLine( p, r.Left, r.Top, r.Left, r.Bottom ); + } + } + else + { + e.Graphics.DrawRectangle( p, r ); + } + } + } + + /// + /// Draws the all day items area + /// + /// Paint Info + public override void OnDrawDayTop( CalendarRendererDayEventArgs e ) + { + bool s = e.Day.DayTop.Selected; + + using( Brush b = new SolidBrush( s ? ColorTable.DayTopSelectedBackground : ColorTable.DayTopBackground ) ) + { + e.Graphics.FillRectangle( b, e.Day.DayTop.Bounds ); + } + + using( Pen p = new Pen( s ? ColorTable.DayTopSelectedBorder : ColorTable.DayTopBorder ) ) + { + e.Graphics.DrawRectangle( p, e.Day.DayTop.Bounds ); + } + + base.OnDrawDayTop( e ); + } + + /// + /// Paints the background of the specified day's header + /// + /// + public override void OnDrawDayHeaderBackground( CalendarRendererDayEventArgs e ) + { + bool today = e.Day.Date.Date.Equals( DateTime.Today.Date ); + + using( Brush b = new SolidBrush( today ? ColorTable.TodayTopBackground : ColorTable.DayHeaderBackground ) ) + { + e.Graphics.FillRectangle( b, e.Day.HeaderBounds ); + } + + base.OnDrawDayHeaderBackground( e ); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public override void OnDrawWeekHeader( CalendarRendererBoxEventArgs e ) + { + using( Brush b = new SolidBrush( ColorTable.WeekHeaderBackground ) ) + { + e.Graphics.FillRectangle( b, e.Bounds ); + } + + using( Pen p = new Pen( ColorTable.WeekHeaderBorder ) ) + { + e.Graphics.DrawRectangle( p, e.Bounds ); + } + + e.TextColor = ColorTable.WeekHeaderText; + + base.OnDrawWeekHeader( e ); + } + + /// + /// Draws a time unit of a day + /// + /// + public override void OnDrawDayTimeUnit( CalendarRendererTimeUnitEventArgs e ) + { + base.OnDrawDayTimeUnit( e ); + + using( SolidBrush b = new SolidBrush( ColorTable.TimeUnitBackground ) ) + { + if( e.Unit.Selected ) + { + b.Color = ColorTable.TimeUnitSelectedBackground; + } + else if( e.Unit.Highlighted ) + { + b.Color = ColorTable.TimeUnitHighlightedBackground; + } + + e.Graphics.FillRectangle( b, e.Unit.Bounds ); + } + + using( Pen p = new Pen( e.Unit.Minutes == 0 ? ColorTable.TimeUnitBorderDark : ColorTable.TimeUnitBorderLight ) ) + { + e.Graphics.DrawLine( p, e.Unit.Bounds.Location, new Point( e.Unit.Bounds.Right, e.Unit.Bounds.Top ) ); + } + } + + /// + /// Paints the timescale of the calendar + /// + /// Paint info + public override void OnDrawTimeScale( CalendarRendererEventArgs e ) + { + int margin = 5; + int largeX1 = TimeScaleBounds.Left + margin; + int largeX2 = TimeScaleBounds.Right - margin; + int shortX1 = TimeScaleBounds.Left + TimeScaleBounds.Width / 2; + int shortX2 = largeX2; + int top = 0; + Pen p = new Pen( ColorTable.TimeScaleLine ); + + for( int i = 0; i < e.Calendar.Days[0].TimeUnits.Length; i++ ) + { + CalendarTimeScaleUnit unit = e.Calendar.Days[0].TimeUnits[i]; + + if( !unit.Visible ) continue; + + top = unit.Bounds.Top; + + if( unit.Minutes == 0 ) + { + e.Graphics.DrawLine( p, largeX1, top, largeX2, top ); + } + else + { + e.Graphics.DrawLine( p, shortX1, top, shortX2, top ); + } + } + + if( e.Calendar.DaysMode == CalendarDaysMode.Expanded + && e.Calendar.Days != null + && e.Calendar.Days.Length > 0 + && e.Calendar.Days[0].TimeUnits != null + && e.Calendar.Days[0].TimeUnits.Length > 0 + ) + { + top = e.Calendar.Days[0].BodyBounds.Top; + + //Timescale top line is full + e.Graphics.DrawLine( p, TimeScaleBounds.Left, top, TimeScaleBounds.Right, top ); + } + + p.Dispose(); + + base.OnDrawTimeScale( e ); + } + + /// + /// Paints an hour of a timescale unit + /// + /// Paint Info + public override void OnDrawTimeScaleHour( CalendarRendererBoxEventArgs e ) + { + e.TextColor = ColorTable.TimeScaleHours; + base.OnDrawTimeScaleHour( e ); + } + + /// + /// Paints minutes of a timescale unit + /// + /// Paint Info + public override void OnDrawTimeScaleMinutes( CalendarRendererBoxEventArgs e ) + { + e.TextColor = ColorTable.TimeScaleMinutes; + base.OnDrawTimeScaleMinutes( e ); + } + + /// + /// Draws the background of the specified item + /// + /// Event Info + public override void OnDrawItemBackground( CalendarRendererItemBoundsEventArgs e ) + { + base.OnDrawItemBackground( e ); + + int alpha = 255; + + if( e.Item.IsDragging ) + { + alpha = 120; + } + else if( e.Calendar.DaysMode == CalendarDaysMode.Short ) + { + alpha = 200; + } + + Color color1 = Color.White; + Color color2 = e.Item.Selected ? ColorTable.ItemSelectedBackground : ColorTable.ItemBackground; + + if( !e.Item.BackgroundColorLighter.IsEmpty ) + { + color1 = e.Item.BackgroundColorLighter; + } + + if( !e.Item.BackgroundColor.IsEmpty ) + { + color2 = e.Item.BackgroundColor; + } + + ItemFill( e, e.Bounds, Color.FromArgb( alpha, color1 ), Color.FromArgb( alpha, color2 ) ); + + } + + /// + /// Draws the shadow of the specified item + /// + /// + public override void OnDrawItemShadow( CalendarRendererItemBoundsEventArgs e ) + { + base.OnDrawItemShadow( e ); + + if( e.Item.IsOnDayTop || e.Calendar.DaysMode == CalendarDaysMode.Short || e.Item.IsDragging ) + { + return; + } + + Rectangle r = e.Bounds; + r.Offset( ItemShadowPadding, ItemShadowPadding ); + + using( SolidBrush b = new SolidBrush( ColorTable.ItemShadow ) ) + { + ItemFill( e, r, ColorTable.ItemShadow, ColorTable.ItemShadow ); + } + } + + /// + /// Draws the border of the specified item + /// + /// Event Info + public override void OnDrawItemBorder( CalendarRendererItemBoundsEventArgs e ) + { + base.OnDrawItemBorder( e ); + + Color a = e.Item.BorderColor.IsEmpty ? ColorTable.ItemBorder : e.Item.BorderColor; + Color b = e.Item.Selected && !e.Item.IsDragging ? ColorTable.ItemSelectedBorder : a; + Color c = Color.FromArgb( e.Item.IsDragging ? 120 : 255, b ); + + ItemBorder( e, e.Bounds, c, e.Item.Selected && !e.Item.IsDragging ? SelectedItemBorder : 1f ); + + } + + /// + /// Draws the starttime of the item if applicable + /// + /// Event data + public override void OnDrawItemStartTime( CalendarRendererBoxEventArgs e ) + { + if( e.TextColor.IsEmpty ) + { + e.TextColor = ColorTable.ItemSecondaryText; + } + + base.OnDrawItemStartTime( e ); + } + + /// + /// Draws the end time of the item if applicable + /// + /// Event data + public override void OnDrawItemEndTime( CalendarRendererBoxEventArgs e ) + { + if( e.TextColor.IsEmpty ) + { + e.TextColor = ColorTable.ItemSecondaryText; + } + + base.OnDrawItemEndTime( e ); + + } + + /// + /// Draws the text of an item + /// + /// + public override void OnDrawItemText( CalendarRendererBoxEventArgs e ) + { + CalendarItem item = e.Tag as CalendarItem; + + if( item != null ) + { + if( item.IsDragging ) + { + e.TextColor = Color.FromArgb( 120, e.TextColor ); + } + } + + base.OnDrawItemText( e ); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public override void OnDrawWeekHeaders( CalendarRendererEventArgs e ) + { + base.OnDrawWeekHeaders( e ); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + public override void OnDrawDayNameHeader( CalendarRendererBoxEventArgs e ) + { + e.TextColor = ColorTable.WeekDayName; + + base.OnDrawDayNameHeader( e ); + + using( Pen p = new Pen( ColorTable.WeekDayName ) ) + { + e.Graphics.DrawLine( p, e.Bounds.Right, e.Bounds.Top, e.Bounds.Right, e.Bounds.Bottom ); + } + } + + /// + /// Draws the overflow to end of specified day + /// + /// + public override void OnDrawDayOverflowEnd( CalendarRendererDayEventArgs e ) + { + using( GraphicsPath path = new GraphicsPath() ) + { + int top = e.Day.OverflowEndBounds.Top + e.Day.OverflowEndBounds.Height / 2; + path.AddPolygon( new Point[] { + new Point(e.Day.OverflowEndBounds.Left, top), + new Point(e.Day.OverflowEndBounds.Right, top), + new Point(e.Day.OverflowEndBounds.Left + e.Day.OverflowEndBounds.Width / 2, e.Day.OverflowEndBounds.Bottom), + } ); + + using( Brush b = new SolidBrush( e.Day.OverflowEndSelected ? ColorTable.DayOverflowSelectedBackground : ColorTable.DayOverflowBackground ) ) + { + e.Graphics.FillPath( b, path ); + } + + using( Pen p = new Pen( ColorTable.DayOverflowBorder ) ) + { + e.Graphics.DrawPath( p, path ); + } + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/UserControls/Calendar.cs b/WindowsFormsCalendar/UserControls/Calendar.cs new file mode 100644 index 0000000..69bb84e --- /dev/null +++ b/WindowsFormsCalendar/UserControls/Calendar.cs @@ -0,0 +1,2084 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Hosts a calendar view where user can manage calendar items. + /// + [DefaultEvent( "LoadItems" )] + public class Calendar + : ScrollableControl + { + #region Static + + /// + /// Returns a value indicating if two date ranges intersect. + /// + /// The start A. + /// The end A. + /// The start B. + /// The end B. + /// + public static bool DateIntersects( DateTime startA, DateTime endA, DateTime startB, DateTime endB ) + { + return startB < endA && startA < endB; + } + + #endregion + + #region Events + + /// + /// Delegate that supports event + /// + /// Sender of the event + /// Event Data + public delegate void CalendarLoadEventHandler( object sender, CalendarLoadEventArgs e ); + + /// + /// Delegate that supports item-related events + /// + /// + /// + public delegate void CalendarItemEventHandler( object sender, CalendarItemEventArgs e ); + + /// + /// Delegate that supports cancelable item-related events + /// + /// + /// + public delegate void CalendarItemCancelEventHandler( object sender, CalendarItemCancelEventArgs e ); + + /// + /// Delegate that supports -related events + /// + /// + /// + public delegate void CalendarDayEventHandler( object sender, CalendarDayEventArgs e ); + + /// + /// Occurs when items are load into view + /// + [Description( "Occurs when items are load into view" )] + public event CalendarLoadEventHandler LoadItems; + + /// + /// Occurs when a day header is clicked + /// + [Description( "Occurs when a day header is clicked" )] + public event CalendarDayEventHandler DayHeaderClick; + + /// + /// Occurs when an item is about to be created. + /// + /// + /// Event can be cancelled + /// + [Description( "Occurs when an item is about to be created." )] + public event CalendarItemCancelEventHandler ItemCreating; + + /// + /// Occurs when an item has been created. + /// + [Description( "Occurs when an item has been created." )] + public event CalendarItemCancelEventHandler ItemCreated; + + /// + /// Occurs before an item is deleted + /// + [Description( "Occurs before an item is deleted" )] + public event CalendarItemCancelEventHandler ItemDeleting; + + /// + /// Occurs when an item has been deleted + /// + [Description( "Occurs when an item has been deleted" )] + public event CalendarItemEventHandler ItemDeleted; + + /// + /// Occurs when an item text is about to be edited + /// + [Description( "Occurs when an item text is about to be edited" )] + public event CalendarItemCancelEventHandler ItemTextEditing; + + /// + /// Occurs when an item text is edited + /// + [Description( "Occurs when an item text is edited" )] + public event CalendarItemCancelEventHandler ItemTextEdited; + + /// + /// Occurs when an item time range has changed + /// + [Description( "Occurs when an item time range has changed" )] + public event CalendarItemEventHandler ItemDatesChanged; + + /// + /// Occurs when an item is clicked + /// + [Description( "Occurs when an item is clicked" )] + public event CalendarItemEventHandler ItemClick; + + /// + /// Occurs when an item is double-clicked + /// + [Description( "Occurs when an item is double-clicked" )] + public event CalendarItemEventHandler ItemDoubleClick; + + /// + /// Occurs when an item is selected + /// + [Description( "Occurs when an item is selected" )] + public event CalendarItemEventHandler ItemSelected; + + /// + /// Occurs after the items are positioned + /// + /// + /// Items bounds can be altered using the method. + /// + [Description( "Occurs after the items are positioned" )] + public event EventHandler ItemsPositioned; + + /// + /// Occurs when the mouse is moved over an item + /// + [Description( "Occurs when the mouse is moved over an item" )] + public event CalendarItemEventHandler ItemMouseHover; + + #endregion + + #region Fields + + private CalendarTextBox _textBox; + + private bool _allowNew; + private bool _allowItemEdit; + private bool _allowItemResize; + private bool _creatingItem; + + private CalendarDay[] _days; + + private CalendarDaysMode _daysMode; + + private CalendarItem _editModeItem; + + private bool _finalizingEdition; + + private DayOfWeek _firstDayOfWeek; + + private CalendarHighlightRange[] _highlightRanges; + private CalendarItemCollection _items; + + private string _itemsDateFormat; + private string _itemsTimeFormat; + + private int _maximumFullDays; + private int _maximumViewDays; + + private CalendarRenderer _renderer; + + private DateTime _selEnd; + private DateTime _selStart; + + private CalendarState _state; + + private CalendarTimeScale _timeScale; + + private int _timeUnitsOffset; + + private DateTime _viewEnd; + private DateTime _viewStart; + + private CalendarWeek[] _weeks; + + private List _selectedElements; + + private ICalendarSelectableElement _selectedElementEnd; + private ICalendarSelectableElement _selectedElementStart; + + private Rectangle _selectedElementSquare; + + private CalendarItem itemOnState; + + private bool itemOnStateChanged; + + private CalendarTimeFormat _timeFormat; + + private CalendarScrollBars _scrollbars; + + private Font _itemsmFont; + + private DateTime _itemsStartViewTime; + private DateTime _itemEndViewTime; + + private Color _itemsForeColor = Color.Black; + private Color _itemsBackgroundColor = Color.RoyalBlue; + + #endregion + + #region Properties + + /// + /// Gets or sets the color of the items fore. + /// + /// + /// The color of the items fore. + /// + [Description( "The default foreground color of the calendar items." )] + public Color ItemsForeColor + { + get { return _itemsForeColor; } + set { _itemsForeColor = value; } + } + + /// + /// Gets or sets the color of the items background. + /// + /// + /// The color of the items background. + /// + [Description( "The default background color of the calendar items." )] + public Color ItemsBackgroundColor + { + get { return _itemsBackgroundColor; } + set { _itemsBackgroundColor = value; } + } + + /// + /// Gets or sets the calendar item font. + /// + /// + /// The calendar item font. + /// + [Description("The default font values for all calendar items. This can be overriden in code.")] + public Font ItemsFont + { + get { return _itemsmFont; } + set { _itemsmFont = value; } + } + + /// + /// Gets or sets a value indicating if the control let's the user create new items. + /// + [DefaultValue( true )] + [Description( "Allows the user to create new items on the view" )] + public bool AllowNew + { + get { return _allowNew; } + set { _allowNew = value; } + } + + /// + /// Gets or sets a value indicating if the user can edit the item using the mouse or keyboard + /// + [DefaultValue( true )] + [Description( "Allows or denies the user the edition of items text or date ranges." )] + public bool AllowItemEdit + { + get { return _allowItemEdit; } + set { _allowItemEdit = value; } + } + + /// + /// Gets or sets a value indicating if calendar allows user to resize the calendar. + /// + [DefaultValue( true )] + [Description( "Allows or denies the user to resize items on the calendar" )] + public bool AllowItemResize + { + get { return _allowItemResize; } + set { _allowItemResize = value; } + } + + /// + /// Gets the days visible on the ccurrent view + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarDay[] Days + { + get { return _days; } + } + + /// + /// Gets the mode in which days are drawn. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarDaysMode DaysMode + { + get { return _daysMode; } + } + + /// + /// Gets the union of day body rectangles + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public Rectangle DaysBodyRectangle + { + get + { + Rectangle first = Days[0].BodyBounds; + Rectangle last = Days[Days.Length - 1].BodyBounds; + + return Rectangle.Union( first, last ); + } + } + + /// + /// Gets if the calendar is currently in edit mode of some item + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public bool EditMode + { + get { return TextBox != null; } + } + + /// + /// Gets the item being edited (if any) + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarItem EditModeItem + { + get + { + return _editModeItem; + } + } + + /// + /// Gets or sets the first day of weeks + /// + [Description( "Starting day of weeks" )] + [DefaultValue( DayOfWeek.Sunday )] + public DayOfWeek FirstDayOfWeek + { + set { _firstDayOfWeek = value; } + get { return _firstDayOfWeek; } + } + + /// + /// Gets or sets the time ranges that should be highlighted as work-time. + /// This ranges are week based. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarHighlightRange[] HighlightRanges + { + get { return _highlightRanges; } + set { _highlightRanges = value; UpdateHighlights(); } + } + + /// + /// Gets the collection of items currently on the view. + /// + /// + /// This collection changes every time the view is changed + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarItemCollection Items + { + get { return _items; } + } + + /// + /// Gets or sets the format in which time is shown in the items, when applicable + /// + [DefaultValue( "dd/MMM" )] + public string ItemsDateFormat + { + get { return _itemsDateFormat; } + set { _itemsDateFormat = value; } + } + + /// + /// Gets or sets the format in which time is shown in the items, when applicable + /// + [DefaultValue( "hh:mm tt" )] + public string ItemsTimeFormat + { + get { return _itemsTimeFormat; } + set { _itemsTimeFormat = value; } + } + + /// + /// Gets or sets the maximum full days shown on the view. + /// After this amount of days, they will be shown as short days. + /// + [DefaultValue( 8 )] + public int MaximumFullDays + { + get { return _maximumFullDays; } + set { _maximumFullDays = value; } + } + + /// + /// Gets or sets the maximum amount of days supported by the view. + /// Value must be multiple of 7 + /// + [DefaultValue( 35 )] + public int MaximumViewDays + { + get { return _maximumViewDays; } + set + { + if( value % 7 != 0 ) + { + throw new Exception( "MaximumViewDays must be multiple of 7" ); + } + _maximumViewDays = value; + } + } + + /// + /// Gets or sets the time format. + /// + /// + /// The time format. + /// + [Description( "The format of the calendar time (12 or 24 hour)." )] + [DefaultValue( CalendarTimeFormat.TwelveHour )] + public CalendarTimeFormat CalendarTimeFormat + { + get { return _timeFormat; } + set { _timeFormat = value; } + } + + /// + /// Gets or sets the of the + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarRenderer Renderer + { + get { return _renderer; } + set + { + _renderer = value; + + if( value != null && Created ) + { + value.OnInitialize( new CalendarRendererEventArgs( null, null, Rectangle.Empty ) ); + } + } + } + + /// + /// Gets the last selected element + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public ICalendarSelectableElement SelectedElementEnd + { + get { return _selectedElementEnd; } + set + { + _selectedElementEnd = value; + + UpdateSelectionElements(); + } + } + + /// + /// Gets the first selected element + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public ICalendarSelectableElement SelectedElementStart + { + get { return _selectedElementStart; } + set + { + _selectedElementStart = value; + + UpdateSelectionElements(); + } + } + + /// + /// Gets or sets the end date-time of the view's selection. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public DateTime SelectionEnd + { + get { return _selEnd; } + set { _selEnd = value; } + } + + /// + /// Gets or sets the start date-time of the view's selection. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public DateTime SelectionStart + { + get { return _selStart; } + set { _selStart = value; } + } + + /// + /// Gets or sets the state of the calendar + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarState State + { + get { return _state; } + } + + /// + /// Gets or sets the scrollbars. + /// + /// + /// The scrollbars. + /// + [Description( "Does the calendar show scrollbars." )] + [DefaultValue( CalendarScrollBars.None )] + public CalendarScrollBars Scrollbars + { + get { return _scrollbars; } + set { _scrollbars = value; } + } + + /// + /// Gets the TextBox of the edit mode + /// + internal CalendarTextBox TextBox + { + get { return _textBox; } + set { _textBox = value; } + } + + /// + /// Gets or sets the for visualization. + /// + [DefaultValue( CalendarTimeScale.ThirtyMinutes )] + public CalendarTimeScale TimeScale + { + get { return _timeScale; } + set + { + _timeScale = value; + + if( Days != null ) + { + for( int i = 0; i < Days.Length; i++ ) + { + Days[i].UpdateUnits(); + } + } + + Renderer.PerformLayout(); + Refresh(); + } + } + + /// + /// Gets or sets the offset of scrolled units + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public int TimeUnitsOffset + { + get { return _timeUnitsOffset; } + set + { + _timeUnitsOffset = value; + Renderer.PerformLayout(); + Invalidate(); + } + } + + /// + /// Gets or sets the end date-time of the current view. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public DateTime ViewEnd + { + get { return _viewEnd; } + set + { + _viewEnd = value.Date.Add( new TimeSpan( 23, 59, 59 ) ); + ClearItems(); + UpdateDaysAndWeeks(); + Renderer.PerformLayout(); + Invalidate(); + ReloadItems(); + } + } + + /// + /// Gets or sets the start date-time of the current view. + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public DateTime ViewStart + { + get { return _viewStart; } + set + { + _viewStart = value.Date; + ClearItems(); + UpdateDaysAndWeeks(); + Renderer.PerformLayout(); + Invalidate(); + ReloadItems(); + } + } + + /// + /// Gets the weeks currently visible on the calendar, if is + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + [Browsable( false ), EditorBrowsable( EditorBrowsableState.Never )] + public CalendarWeek[] Weeks + { + get { return _weeks; } + } + + #endregion + + /// + /// Creates a new control + /// + public Calendar() + { + SetStyle( ControlStyles.ResizeRedraw, true ); + SetStyle( ControlStyles.Selectable, true ); + + DoubleBuffered = true; + + _selectedElements = new List(); + _items = new CalendarItemCollection( this ); + _renderer = new CalendarProfessionalRenderer( this ); + _maximumFullDays = 8; + _maximumViewDays = 35; + + HighlightRanges = new CalendarHighlightRange[] { + new CalendarHighlightRange( DayOfWeek.Monday, new TimeSpan(8,0,0), new TimeSpan(17,0,0)), + new CalendarHighlightRange( DayOfWeek.Tuesday, new TimeSpan(8,0,0), new TimeSpan(17,0,0)), + new CalendarHighlightRange( DayOfWeek.Wednesday, new TimeSpan(8,0,0), new TimeSpan(17,0,0)), + new CalendarHighlightRange( DayOfWeek.Thursday, new TimeSpan(8,0,0), new TimeSpan(17,0,0)), + new CalendarHighlightRange( DayOfWeek.Friday, new TimeSpan(8,0,0), new TimeSpan(17,0,0)), + }; + + _timeScale = CalendarTimeScale.ThirtyMinutes; + SetViewRange( DateTime.Now, DateTime.Now.AddDays( 2 ) ); + + + _itemsDateFormat = "dd/MMM"; + _itemsTimeFormat = "hh:mm tt"; + _allowItemEdit = true; + _allowNew = true; + _allowItemResize = true; + } + + #region Public Methods + + /// + /// Activates the edit mode on the first selected item + /// + public void ActivateEditMode() + { + foreach( CalendarItem item in Items ) + { + if( item.Selected ) + { + ActivateEditMode( item ); + return; + } + } + } + + /// + /// Activates the edit mode on the specified item + /// + /// The item. + public void ActivateEditMode( CalendarItem item ) + { + CalendarItemCancelEventArgs evt = new CalendarItemCancelEventArgs( item ); + + if( !_creatingItem ) + { + OnItemEditing( evt ); + } + + if( evt.Cancel ) + { + return; + } + + _editModeItem = item; + TextBox = new CalendarTextBox( this ); + TextBox.KeyDown += new KeyEventHandler( TextBox_KeyDown ); + TextBox.LostFocus += new EventHandler( TextBox_LostFocus ); + Rectangle r = item.Bounds; + r.Inflate( -2, -2 ); + TextBox.Bounds = r; + TextBox.BorderStyle = BorderStyle.None; + TextBox.Text = item.Text; + TextBox.Multiline = true; + + Controls.Add( TextBox ); + TextBox.Visible = true; + TextBox.Focus(); + TextBox.SelectionStart = TextBox.Text.Length; + + SetState( CalendarState.EditingItemText ); + } + + /// + /// Creates a new item on the current selection. + /// If there's no selection, this will be ignored. + /// + /// Text of the item + /// If true activates the edit mode so user can edit the text of the item. + public void CreateItemOnSelection( string itemText, bool editMode ) + { + if( SelectedElementEnd == null || SelectedElementStart == null ) return; + + CalendarTimeScaleUnit unitEnd = SelectedElementEnd as CalendarTimeScaleUnit; + CalendarDayTop dayTop = SelectedElementEnd as CalendarDayTop; + CalendarDay day = SelectedElementEnd as CalendarDay; + TimeSpan duration = unitEnd != null ? unitEnd.Duration : new TimeSpan( 23, 59, 59 ); + CalendarItem item = new CalendarItem( this ); + + DateTime dstart = SelectedElementStart.Date; + DateTime dend = SelectedElementEnd.Date; + + if( dend.CompareTo( dstart ) < 0 ) + { + DateTime dtmp = dend; + dend = dstart; + dstart = dtmp; + } + + item.StartDate = dstart; + item.EndDate = dend.Add( duration ); + item.Text = itemText; + + CalendarItemCancelEventArgs evtA = new CalendarItemCancelEventArgs( item ); + + OnItemCreating( evtA ); + + if( !evtA.Cancel ) + { + // set the default font, developers can change this anytime via override + Items.Add( item ); + + if( editMode ) + { + _creatingItem = true; + ActivateEditMode( item ); + } + } + + + } + + /// + /// Ensures the scrolling shows the specified time unit. It doesn't affect View date ranges. + /// + /// Unit to ensure visibility + public void EnsureVisible( CalendarTimeScaleUnit unit ) + { + if( Days == null || Days.Length == 0 ) return; + + Rectangle view = Days[0].BodyBounds; + + if( unit.Bounds.Bottom > view.Bottom ) + { + TimeUnitsOffset = -Convert.ToInt32( Math.Ceiling( unit.Date.TimeOfDay.TotalMinutes / (double)TimeScale ) ) + + Renderer.GetVisibleTimeUnits(); + } + else if( unit.Bounds.Top < view.Top ) + { + TimeUnitsOffset = -Convert.ToInt32( Math.Ceiling( unit.Date.TimeOfDay.TotalMinutes / (double)TimeScale ) ); + } + } + + /// + /// Finalizes editing the . + /// + /// Value indicating if edition of item should be canceled. + public void FinalizeEditMode( bool cancel ) + { + if( !EditMode || EditModeItem == null || _finalizingEdition ) return; + + _finalizingEdition = true; + + string cancelText = _editModeItem.Text; + CalendarItem itemBuffer = _editModeItem; + _editModeItem = null; + CalendarItemCancelEventArgs evt = new CalendarItemCancelEventArgs( itemBuffer ); + + if( !cancel ) + itemBuffer.Text = TextBox.Text.Trim(); + + if( TextBox != null ) + { + TextBox.Visible = false; + Controls.Remove( TextBox ); + TextBox.Dispose(); + } + + if( _editModeItem != null ) + Invalidate( itemBuffer ); + + _textBox = null; + + if( _creatingItem ) + { + OnItemCreated( evt ); + } + else + { + OnItemEdited( evt ); + } + + if( evt.Cancel ) + { + itemBuffer.Text = cancelText; + } + + + _creatingItem = false; + _finalizingEdition = false; + + if( State == CalendarState.EditingItemText ) + { + SetState( CalendarState.Idle ); + } + } + + /// + /// Finds the for the specified date, if in the view. + /// + /// Date to find day + /// object that matches the date, null if day was not found. + public CalendarDay FindDay( DateTime d ) + { + if( Days == null ) return null; + + for( int i = 0; i < Days.Length; i++ ) + { + if( Days[i].Date.Date.Equals( d.Date.Date ) ) + { + return Days[i]; + } + } + + return null; + } + + /// + /// Gets the items that are currently selected + /// + /// + public IEnumerable GetSelectedItems() + { + List items = new List(); + + foreach( CalendarItem item in Items ) + { + if( item.Selected ) + { + items.Add( item ); + } + } + + return items; + } + + /// + /// Gets the time unit that starts with the specified date + /// + /// The d. + /// + /// Matching time unit. null If out of range. + /// + public CalendarTimeScaleUnit GetTimeUnit( DateTime d ) + { + if( Days != null ) + { + foreach( CalendarDay day in Days ) + { + if( day.Date.Equals( d.Date ) ) + { + double duration = Convert.ToDouble( (int)TimeScale ); + int index = + Convert.ToInt32( + Math.Floor( + d.TimeOfDay.TotalMinutes / duration + ) + ); + + return day.TimeUnits[index]; + } + } + } + + return null; + } + + /// + /// Hits the test. + /// + /// The p. + /// + public ICalendarSelectableElement HitTest( Point p ) + { + return HitTest( p, false ); + } + + /// + /// Searches for the first hitted + /// + /// Point to check for hit test + /// if set to true [ignore items]. + /// + public ICalendarSelectableElement HitTest( Point p, bool ignoreItems ) + { + if( !ignoreItems ) + foreach( CalendarItem item in Items ) + { + foreach( Rectangle r in item.GetAllBounds() ) + { + if( r.Contains( p ) ) + { + return item; + } + } + } + + for( int i = 0; i < Days.Length; i++ ) + { + if( Days[i].Bounds.Contains( p ) ) + { + if( DaysMode == CalendarDaysMode.Expanded ) + { + if( Days[i].DayTop.Bounds.Contains( p ) ) + { + return Days[i].DayTop; + } + else + { + for( int j = 0; j < Days[i].TimeUnits.Length; j++ ) + { + if( Days[i].TimeUnits[j].Visible && + Days[i].TimeUnits[j].Bounds.Contains( p ) ) + { + return Days[i].TimeUnits[j]; + } + } + } + + return Days[i]; + } + else if( DaysMode == CalendarDaysMode.Short ) + { + return Days[i]; + } + } + } + + return null; + } + + /// + /// Returns the item hitted at the specified location. Null if no item hitted. + /// + /// Location to serach for items + /// Hitted item at the location. Null if no item hitted. + public CalendarItem ItemAt( Point p ) + { + return HitTest( p ) as CalendarItem; + } + + /// + /// Invalidates the bounds of the specified day + /// + /// The day. + public void Invalidate( CalendarDay day ) + { + Invalidate( day.Bounds ); + } + + /// + /// Ivalidates the bounds of the specified unit + /// + /// The unit. + public void Invalidate( CalendarTimeScaleUnit unit ) + { + Invalidate( unit.Bounds ); + } + + /// + /// Invalidates the area of the specified item + /// + /// The item. + public void Invalidate( CalendarItem item ) + { + Rectangle r = item.Bounds; + + foreach( Rectangle bounds in item.GetAllBounds() ) + { + r = Rectangle.Union( r, bounds ); + } + + r.Inflate( Renderer.ItemShadowPadding + Renderer.ItemInvalidateMargin, Renderer.ItemShadowPadding + Renderer.ItemInvalidateMargin ); + Invalidate( r ); + } + + /// + /// Establishes the selection range with only one graphical update. + /// + /// Fisrt selected element + /// Last selection element + public void SetSelectionRange( ICalendarSelectableElement selectionStart, ICalendarSelectableElement selectionEnd ) + { + _selectedElementStart = selectionStart; + SelectedElementEnd = selectionEnd; + } + + /// + /// Sets the value of and properties + /// triggering only one repaint process + /// + /// Start date of view + /// End date of view + public void SetViewRange( DateTime dateStart, DateTime dateEnd ) + { + _viewStart = dateStart.Date; + ViewEnd = dateEnd; + } + + /// + /// Returns a value indicating if the view range intersects the specified date range. + /// + /// The start date. + /// The end date. + /// + public bool ViewIntersects( DateTime startDate, DateTime endDate ) + { + return DateIntersects( ViewStart, ViewEnd, startDate, endDate ); + } + + /// + /// Returns a value indicating if the view range intersect the date range of the specified item + /// + /// The item. + /// + public bool ViewIntersects( CalendarItem item ) + { + return ViewIntersects( item.StartDate, item.EndDate ); + } + + #endregion + + #region Private Methods + + /// + /// Determines whether the specified key is a regular input key or a special key that requires preprocessing. + /// + /// One of the values. + /// + /// true if the specified key is a regular input key; otherwise, false. + /// + protected override bool IsInputKey( Keys keyData ) + { + if( + keyData == Keys.Down || + keyData == Keys.Up || + keyData == Keys.Right || + keyData == Keys.Left ) + { + return true; + } + else + { + + return base.IsInputKey( keyData ); + } + } + + /// + /// Removes all the items currently on the calendar + /// + private void ClearItems() + { + Items.Clear(); + Renderer.DayTopHeight = Renderer.DayTopMinHeight; + } + + /// + /// Unselects the selected items + /// + private void ClearSelectedItems() + { + Rectangle r = Rectangle.Empty; + + foreach( CalendarItem item in Items ) + { + if( item.Selected ) + { + if( r.IsEmpty ) + { + r = item.Bounds; + } + else + { + r = Rectangle.Union( r, item.Bounds ); + } + } + + item.SetSelected( false ); + } + + Invalidate( r ); + } + + /// + /// Deletes the currently selected item + /// + private void DeleteSelectedItems() + { + Stack toDelete = new Stack(); + + foreach( CalendarItem item in Items ) + { + if( item.Selected ) + { + CalendarItemCancelEventArgs evt = new CalendarItemCancelEventArgs( item ); + + OnItemDeleting( evt ); + + if( !evt.Cancel ) + { + toDelete.Push( item ); + } + } + } + + if( toDelete.Count > 0 ) + { + while( toDelete.Count > 0 ) + { + CalendarItem item = toDelete.Pop(); + + Items.Remove( item ); + + OnItemDeleted( new CalendarItemEventArgs( item ) ); + } + + Renderer.PerformItemsLayout(); + } + } + + /// + /// Clears current items and reloads for specified view + /// + private void ReloadItems() + { + OnLoadItems( new CalendarLoadEventArgs( this, ViewStart, ViewEnd ) ); + } + + /// + /// Grows the rectangle to repaint currently selected elements + /// + /// The rect. + private void GrowSquare( Rectangle rect ) + { + if( _selectedElementSquare.IsEmpty ) + { + _selectedElementSquare = rect; + } + else + { + _selectedElementSquare = Rectangle.Union( _selectedElementSquare, rect ); + } + } + + /// + /// Clears selection of currently selected components (As quick as possible) + /// + private void ClearSelectedComponents() + { + foreach( CalendarSelectableElement element in _selectedElements ) + { + element.SetSelected( false ); + } + + _selectedElements.Clear(); + + Invalidate( _selectedElementSquare ); + _selectedElementSquare = Rectangle.Empty; + + } + + /// + /// Scrolls the calendar using the specified delta + /// + /// The delta. + private void ScrollCalendar( int delta ) + { + if( delta < 0 ) + { + SetViewRange( ViewStart.AddDays( 7 ), ViewEnd.AddDays( 7 ) ); + } + else + { + SetViewRange( ViewStart.AddDays( -7 ), ViewEnd.AddDays( -7 ) ); + } + } + + /// + /// Raises the event + /// + internal void RaiseItemsPositioned() + { + OnItemsPositioned( EventArgs.Empty ); + } + + /// + /// Scrolls the time units using the specified delta + /// + /// The delta. + private void ScrollTimeUnits( int delta ) + { + int possible = TimeUnitsOffset; + int visible = Renderer.GetVisibleTimeUnits(); + + if( delta < 0 ) + { + possible--; + } + else + { + possible++; + } + + if( possible > 0 ) + { + possible = 0; + } + else if( + Days != null + && Days.Length > 0 + && Days[0].TimeUnits != null + && possible * -1 >= Days[0].TimeUnits.Length ) + { + possible = Days[0].TimeUnits.Length - 1; + possible *= -1; + } + else if( Days != null + && Days.Length > 0 + && Days[0].TimeUnits != null ) + { + int max = Days[0].TimeUnits.Length - visible; + max *= -1; + if( possible < max ) possible = max; + } + + if( possible != TimeUnitsOffset ) + { + TimeUnitsOffset = possible; + } + } + + /// + /// Sets the value of the property. + /// + /// Mode in which days will be rendered + private void SetDaysMode( CalendarDaysMode mode ) + { + _daysMode = mode; + } + + /// + /// Sets the state. + /// + /// The state. + private void SetState( CalendarState state ) + { + _state = state; + } + + /// + /// Handles the LostFocus event of the TextBox control. + /// + /// The source of the event. + /// The instance containing the event data. + private void TextBox_LostFocus( object sender, EventArgs e ) + { + FinalizeEditMode( false ); + } + + /// + /// Handles the KeyDown event of the TextBox control. + /// + /// The source of the event. + /// The instance containing the event data. + private void TextBox_KeyDown( object sender, KeyEventArgs e ) + { + if( e.KeyCode == Keys.Escape ) + { + FinalizeEditMode( true ); + } + else if( e.KeyCode == Keys.Enter ) + { + FinalizeEditMode( false ); + } + } + + /// + /// Updates the days and weeks. + /// + private void UpdateDaysAndWeeks() + { + TimeSpan span = ( new DateTime( ViewEnd.Year, ViewEnd.Month, ViewEnd.Day, 23, 59, 59 ) ).Subtract( ViewStart.Date ); + int preDays = 0; + span = span.Add( new TimeSpan( 0, 0, 0, 1, 0 ) ); + + if( span.Days < 1 || span.Days > MaximumViewDays ) + { + throw new Exception( "Days between ViewStart and ViewEnd should be between 1 and MaximumViewDays" ); + } + + if( span.Days > MaximumFullDays ) + { + SetDaysMode( CalendarDaysMode.Short ); + preDays = ( new int[] { 0, 1, 2, 3, 4, 5, 6 } )[(int)ViewStart.DayOfWeek] - (int)FirstDayOfWeek; + span = span.Add( new TimeSpan( preDays, 0, 0, 0 ) ); + + while( span.Days % 7 != 0 ) + span = span.Add( new TimeSpan( 1, 0, 0, 0 ) ); + } + else + { + SetDaysMode( CalendarDaysMode.Expanded ); + } + + _days = new CalendarDay[span.Days]; + + for( int i = 0; i < Days.Length; i++ ) + Days[i] = new CalendarDay( this, ViewStart.AddDays( -preDays + i ), i ); + + + //Weeks + if( DaysMode == CalendarDaysMode.Short ) + { + List weeks = new List(); + + for( int i = 0; i < Days.Length; i++ ) + { + if( Days[i].Date.DayOfWeek == FirstDayOfWeek ) + { + weeks.Add( new CalendarWeek( this, Days[i].Date ) ); + } + } + + _weeks = weeks.ToArray(); + } + else + { + _weeks = new CalendarWeek[] { }; + } + + UpdateHighlights(); + + } + + /// + /// Updates the value of the property on the time units of days. + /// + internal void UpdateHighlights() + { + if( Days == null ) return; + + for( int i = 0; i < Days.Length; i++ ) + { + Days[i].UpdateHighlights(); + } + } + + /// + /// Informs elements who's selected and who's not, and repaints + /// + private void UpdateSelectionElements() + { + CalendarTimeScaleUnit unitStart = _selectedElementStart as CalendarTimeScaleUnit; + CalendarDayTop topStart = _selectedElementStart as CalendarDayTop; + CalendarDay dayStart = _selectedElementStart as CalendarDay; + CalendarTimeScaleUnit unitEnd = _selectedElementEnd as CalendarTimeScaleUnit; + CalendarDayTop topEnd = _selectedElementEnd as CalendarDayTop; + CalendarDay dayEnd = _selectedElementEnd as CalendarDay; + + ClearSelectedComponents(); + + if( _selectedElementEnd == null || _selectedElementStart == null ) return; + + if( _selectedElementEnd.CompareTo( SelectedElementStart ) < 0 ) + { + //swap + unitStart = _selectedElementEnd as CalendarTimeScaleUnit; + topStart = _selectedElementEnd as CalendarDayTop; + dayStart = _selectedElementEnd as CalendarDay; + unitEnd = SelectedElementStart as CalendarTimeScaleUnit; + topEnd = SelectedElementStart as CalendarDayTop; + dayEnd = _selectedElementStart as CalendarDay; + } + + if( unitStart != null && unitEnd != null ) + { + bool reached = false; + for( int i = unitStart.Day.Index; !reached; i++ ) + { + for( int j = ( i == unitStart.Day.Index ? unitStart.Index : 0 ); i < Days.Length && j < Days[i].TimeUnits.Length; j++ ) + { + CalendarTimeScaleUnit unit = Days[i].TimeUnits[j]; + unit.SetSelected( true ); + GrowSquare( unit.Bounds ); + _selectedElements.Add( unit ); + + if( unit.Equals( unitEnd ) ) + { + reached = true; + break; + } + } + } + } + else if( topStart != null && topEnd != null ) + { + for( int i = topStart.Day.Index; i <= topEnd.Day.Index; i++ ) + { + CalendarDayTop top = Days[i].DayTop; + + top.SetSelected( true ); + GrowSquare( top.Bounds ); + _selectedElements.Add( top ); + } + } + else if( dayStart != null && dayEnd != null ) + { + for( int i = dayStart.Index; i <= dayEnd.Index; i++ ) + { + CalendarDay day = Days[i]; + + day.SetSelected( true ); + GrowSquare( day.Bounds ); + _selectedElements.Add( day ); + } + } + + Invalidate( _selectedElementSquare ); + } + + #endregion + + #region Overrided Events and Raisers + + /// + /// Raises the method. + /// + protected override void OnCreateControl() + { + base.OnCreateControl(); + + Renderer.OnInitialize( new CalendarRendererEventArgs( new CalendarRendererEventArgs( this, null, Rectangle.Empty ) ) ); + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnClick( EventArgs e ) + { + base.OnClick( e ); + + Select(); + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnDoubleClick( EventArgs e ) + { + base.OnDoubleClick( e ); + + CreateItemOnSelection( string.Empty, true ); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnDayHeaderClick( CalendarDayEventArgs e ) + { + if( DayHeaderClick != null ) + { + DayHeaderClick( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemClick( CalendarItemEventArgs e ) + { + if( ItemClick != null ) + { + ItemClick( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemCreating( CalendarItemCancelEventArgs e ) + { + if( ItemCreating != null ) + { + ItemCreating( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemCreated( CalendarItemCancelEventArgs e ) + { + if( ItemCreated != null ) + { + ItemCreated( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemDeleting( CalendarItemCancelEventArgs e ) + { + if( ItemDeleting != null ) + { + ItemDeleting( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemDeleted( CalendarItemEventArgs e ) + { + if( ItemDeleted != null ) + { + ItemDeleted( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemDoubleClick( CalendarItemEventArgs e ) + { + if( ItemDoubleClick != null ) + { + ItemDoubleClick( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemEditing( CalendarItemCancelEventArgs e ) + { + if( ItemTextEditing != null ) + { + ItemTextEditing( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemEdited( CalendarItemCancelEventArgs e ) + { + if( ItemTextEdited != null ) + { + ItemTextEdited( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemSelected( CalendarItemEventArgs e ) + { + if( ItemSelected != null ) + { + ItemSelected( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemsPositioned( EventArgs e ) + { + if( ItemsPositioned != null ) + { + ItemsPositioned( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemDatesChanged( CalendarItemEventArgs e ) + { + if( ItemDatesChanged != null ) + { + ItemDatesChanged( this, e ); + } + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnItemMouseHover( CalendarItemEventArgs e ) + { + if( ItemMouseHover != null ) + { + ItemMouseHover( this, e ); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnKeyDown( KeyEventArgs e ) + { + base.OnKeyDown( e ); + + bool shiftPressed = ( ModifierKeys & Keys.Shift ) == Keys.Shift; + int jump = (int)TimeScale; + ICalendarSelectableElement sStart = null; + ICalendarSelectableElement sEnd = null; + + if( e.KeyCode == Keys.F2 ) + { + ActivateEditMode(); + } + else if( e.KeyCode == Keys.Delete ) + { + DeleteSelectedItems(); + } + else if( e.KeyCode == Keys.Insert ) + { + if( AllowNew ) + CreateItemOnSelection( string.Empty, true ); + } + else if( e.KeyCode == Keys.Down ) + { + if( e.Shift ) + sStart = SelectedElementStart; + + sEnd = GetTimeUnit( SelectedElementEnd.Date.Add( new TimeSpan( 0, (int)TimeScale, 0 ) ) ); + } + else if( e.KeyCode == Keys.Up ) + { + if( e.Shift ) + sStart = SelectedElementStart; + + sEnd = GetTimeUnit( SelectedElementEnd.Date.Add( new TimeSpan( 0, -(int)TimeScale, 0 ) ) ); + } + else if( e.KeyCode == Keys.Right ) + { + sEnd = GetTimeUnit( SelectedElementEnd.Date.Add( new TimeSpan( 24, 0, 0 ) ) ); + } + else if( e.KeyCode == Keys.Left ) + { + sEnd = GetTimeUnit( SelectedElementEnd.Date.Add( new TimeSpan( -24, 0, 0 ) ) ); + } + else if( e.KeyCode == Keys.PageDown ) + { + + } + else if( e.KeyCode == Keys.PageUp ) + { + + } + + + if( sStart != null ) + { + SetSelectionRange( sStart, sEnd ); + } + else if( sEnd != null ) + { + SetSelectionRange( sEnd, sEnd ); + + if( sEnd is CalendarTimeScaleUnit ) + EnsureVisible( sEnd as CalendarTimeScaleUnit ); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnKeyPress( KeyPressEventArgs e ) + { + base.OnKeyPress( e ); + + if( AllowNew ) + CreateItemOnSelection( e.KeyChar.ToString(), true ); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnLoadItems( CalendarLoadEventArgs e ) + { + if( LoadItems != null ) + { + LoadItems( this, e ); + } + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnMouseDoubleClick( MouseEventArgs e ) + { + base.OnMouseDoubleClick( e ); + + CalendarItem item = ItemAt( e.Location ); + + if( item != null ) + { + OnItemDoubleClick( new CalendarItemEventArgs( item ) ); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseDown( MouseEventArgs e ) + { + base.OnMouseDown( e ); + + ICalendarSelectableElement hitted = HitTest( e.Location ); + CalendarItem hittedItem = hitted as CalendarItem; + bool shiftPressed = ( ModifierKeys & Keys.Shift ) == Keys.Shift; + + if( !Focused ) + { + Focus(); + } + + switch( State ) + { + case CalendarState.Idle: + if( hittedItem != null ) + { + if( !shiftPressed ) + ClearSelectedItems(); + + hittedItem.SetSelected( true ); + Invalidate( hittedItem ); + OnItemSelected( new CalendarItemEventArgs( hittedItem ) ); + + itemOnState = hittedItem; + itemOnStateChanged = false; + + if( AllowItemEdit ) + { + if( itemOnState.ResizeStartDateZone( e.Location ) && AllowItemResize ) + { + SetState( CalendarState.ResizingItem ); + itemOnState.SetIsResizingStartDate( true ); + } + else if( itemOnState.ResizeEndDateZone( e.Location ) && AllowItemResize ) + { + SetState( CalendarState.ResizingItem ); + itemOnState.SetIsResizingEndDate( true ); + } + else + { + SetState( CalendarState.DraggingItem ); + } + } + + SetSelectionRange( null, null ); + } + else + { + ClearSelectedItems(); + + if( shiftPressed ) + { + if( hitted != null && SelectedElementEnd == null && !SelectedElementEnd.Equals( hitted ) ) + SelectedElementEnd = hitted; + } + else + { + if( SelectedElementStart == null || ( hitted != null && !SelectedElementStart.Equals( hitted ) ) ) + { + SetSelectionRange( hitted, hitted ); + } + } + + SetState( CalendarState.DraggingTimeSelection ); + } + break; + case CalendarState.DraggingTimeSelection: + break; + case CalendarState.DraggingItem: + break; + case CalendarState.ResizingItem: + break; + case CalendarState.EditingItemText: + break; + + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseMove( MouseEventArgs e ) + { + base.OnMouseMove( e ); + + ICalendarSelectableElement hitted = HitTest( e.Location, State != CalendarState.Idle ); + CalendarItem hittedItem = hitted as CalendarItem; + CalendarDayTop hittedTop = hitted as CalendarDayTop; + bool shiftPressed = ( ModifierKeys & Keys.Shift ) == Keys.Shift; + + if( hitted != null ) + { + switch( State ) + { + case CalendarState.Idle: + Cursor should = Cursors.Default; + + if( hittedItem != null ) + { + if( ( hittedItem.ResizeEndDateZone( e.Location ) || hittedItem.ResizeStartDateZone( e.Location ) ) && AllowItemResize ) + { + should = hittedItem.IsOnDayTop || DaysMode == CalendarDaysMode.Short ? Cursors.SizeWE : Cursors.SizeNS; + } + + OnItemMouseHover( new CalendarItemEventArgs( hittedItem ) ); + + } + if( !Cursor.Equals( should ) ) Cursor = should; + break; + case CalendarState.DraggingTimeSelection: + if( SelectedElementStart != null && !SelectedElementEnd.Equals( hitted ) ) + SelectedElementEnd = hitted; + break; + case CalendarState.DraggingItem: + TimeSpan duration = itemOnState.Duration; + itemOnState.SetIsDragging( true ); + itemOnState.StartDate = hitted.Date; + itemOnState.EndDate = itemOnState.StartDate.Add( duration ); + Renderer.PerformItemsLayout(); + Invalidate(); + itemOnStateChanged = true; + break; + case CalendarState.ResizingItem: + if( itemOnState.IsResizingEndDate && hitted.Date.CompareTo( itemOnState.StartDate ) >= 0 ) + { + itemOnState.EndDate = hitted.Date.Add( hittedTop != null || DaysMode == CalendarDaysMode.Short ? new TimeSpan( 23, 59, 59 ) : Days[0].TimeUnits[0].Duration ); + } + else if( itemOnState.IsResizingStartDate && hitted.Date.CompareTo( itemOnState.EndDate ) <= 0 ) + { + itemOnState.StartDate = hitted.Date; + } + Renderer.PerformItemsLayout(); + Invalidate(); + itemOnStateChanged = true; + break; + case CalendarState.EditingItemText: + break; + } + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseUp( MouseEventArgs e ) + { + base.OnMouseUp( e ); + + ICalendarSelectableElement hitted = HitTest( e.Location, State == CalendarState.DraggingTimeSelection ); + CalendarItem hittedItem = hitted as CalendarItem; + CalendarDay hittedDay = hitted as CalendarDay; + bool shiftPressed = ( ModifierKeys & Keys.Shift ) == Keys.Shift; + + switch( State ) + { + case CalendarState.Idle: + + break; + case CalendarState.DraggingTimeSelection: + if( SelectedElementStart == null || ( hitted != null && !SelectedElementEnd.Equals( hitted ) ) ) + { + SelectedElementEnd = hitted; + } + if( hittedDay != null ) + { + if( hittedDay.HeaderBounds.Contains( e.Location ) ) + { + OnDayHeaderClick( new CalendarDayEventArgs( hittedDay ) ); + } + } + break; + case CalendarState.DraggingItem: + if( itemOnStateChanged ) + OnItemDatesChanged( new CalendarItemEventArgs( itemOnState ) ); + break; + case CalendarState.ResizingItem: + if( itemOnStateChanged ) + OnItemDatesChanged( new CalendarItemEventArgs( itemOnState ) ); + break; + case CalendarState.EditingItemText: + break; + } + + if( itemOnState != null ) + { + itemOnState.SetIsDragging( false ); + itemOnState.SetIsResizingEndDate( false ); + itemOnState.SetIsResizingStartDate( false ); + Invalidate( itemOnState ); + OnItemClick( new CalendarItemEventArgs( itemOnState ) ); + itemOnState = null; + } + SetState( CalendarState.Idle ); + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseWheel( MouseEventArgs e ) + { + base.OnMouseWheel( e ); + + if( DaysMode == CalendarDaysMode.Expanded ) + { + ScrollTimeUnits( e.Delta ); + } + else if( DaysMode == CalendarDaysMode.Short ) + { + ScrollCalendar( e.Delta ); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnPaint( PaintEventArgs e ) + { + base.OnPaint( e ); + + CalendarRendererEventArgs evt = new CalendarRendererEventArgs( this, e.Graphics, e.ClipRectangle ); + + //Calendar background + Renderer.OnDrawBackground( evt ); + + // Headers / Timescale + switch( DaysMode ) + { + case CalendarDaysMode.Short: + Renderer.OnDrawDayNameHeaders( evt ); + Renderer.OnDrawWeekHeaders( evt ); + break; + case CalendarDaysMode.Expanded: + Renderer.OnDrawTimeScale( evt ); + break; + default: + throw new NotImplementedException( "Current DaysMode not implemented" ); + } + + //Days on view + Renderer.OnDrawDays( evt ); + + //Items + Renderer.OnDrawItems( evt ); + + //Overflow marks + Renderer.OnDrawOverflows( evt ); + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnResize( EventArgs e ) + { + base.OnResize( e ); + + TimeUnitsOffset = TimeUnitsOffset; + Renderer.PerformLayout(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/UserControls/CalendarTextBox.cs b/WindowsFormsCalendar/UserControls/CalendarTextBox.cs new file mode 100644 index 0000000..3414aac --- /dev/null +++ b/WindowsFormsCalendar/UserControls/CalendarTextBox.cs @@ -0,0 +1,68 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// A text box control used in the calendar + /// + public class CalendarTextBox + : TextBox + { + #region Fields + + private Calendar _calendar; + + #endregion + + #region Properties + + /// + /// Gets the calendar where this control lives + /// + public Calendar Calendar + { + get { return _calendar; } + } + + #endregion + + /// + /// Creates a new for the specified + /// + /// Calendar where this control lives + public CalendarTextBox( Calendar calendar ) + { + _calendar = calendar; + this.Font = _calendar.ItemsFont; + this.ForeColor = _calendar.ItemsForeColor; + this.BackColor = _calendar.ItemsBackgroundColor; + } + + #region Methods + #endregion + + } +} \ No newline at end of file diff --git a/WindowsFormsCalendar/UserControls/MonthView.cs b/WindowsFormsCalendar/UserControls/MonthView.cs new file mode 100644 index 0000000..ef623c3 --- /dev/null +++ b/WindowsFormsCalendar/UserControls/MonthView.cs @@ -0,0 +1,1025 @@ +/* + Copyright 2012 Justin LeCheminant + + This file is part of WindowsFormsCalendar. + + indowsFormsCalendar 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 3 of the License, or + (at your option) any later version. + + indowsFormsCalendar 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. + + You should have received a copy of the GNU General Public License + along with indowsFormsCalendar. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace WindowsFormsCalendar +{ + /// + /// Hosts a month-level calendar where user can select day-based dates + /// + [DefaultEvent("SelectionChanged")] + public class MonthView + : ContainerControl + { + #region Fields + private int _forwardMonthIndex; + private MonthViewDay _lastHitted; + private bool _mouseDown; + private Size _daySize; + private DateTime _selectionStart; + private DateTime _selectionEnd; + private string _monthTitleFormat; + private DayOfWeek _weekStart; + private DayOfWeek _workWeekStart; + private DayOfWeek _workWeekEnd; + private MonthViewSelection _selectionMode; + private string _dayNamesFormat; + private bool _dayNamesVisible; + private int _dayNamesLength; + private DateTime _viewStart; + private Size _monthSize; + private MonthViewMonth[] _months; + private Padding _itemPadding; + private Color _monthTitleColor; + private Color _monthTitleColorInactive; + private Color _monthTitleTextColor; + private Color _monthTitleTextColorInactive; + private Color _dayBackgroundColor; + private Color _daySelectedBackgroundColor; + private Color _dayTextColor; + private Color _daySelectedTextColor; + private Color _arrowsColor; + private Color _arrowsSelectedColor; + private Color _dayGrayedText; + private Color _todayBorderColor; + private int _maxSelectionCount; + private Rectangle _forwardButtonBounds; + private bool _forwardButtonSelected; + private Rectangle _backwardButtonBounds; + private bool _backwardButtonSelected; + #endregion + + #region Events + + /// + /// Occurs when selection has changed. + /// + public event EventHandler SelectionChanged; + + #endregion + + #region Properties + + /// + /// Gets the size of days rectangles + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public Size DaySize + { + get { return _daySize; } + } + + /// + /// Gets or sets the format of day names + /// + [DefaultValue( "ddd" )] + public string DayNamesFormat + { + get { return _dayNamesFormat; } + set { _dayNamesFormat = value; } + } + + /// + /// Gets or sets a value indicating if day names should be visible + /// + [DefaultValue( true )] + public bool DayNamesVisible + { + get { return _dayNamesVisible; } + set { _dayNamesVisible = value; } + } + + /// + /// Gets or sets how many characters of day names should be displayed + /// + [DefaultValue( 2 )] + public int DayNamesLength + { + get { return _dayNamesLength; } + set { _dayNamesLength = value; UpdateMonths(); } + } + + /// + /// Gets or sets what the first day of weeks should be + /// + [DefaultValue( DayOfWeek.Sunday )] + public DayOfWeek FirstDayOfWeek + { + get { return _weekStart; } + set { _weekStart = value; } + } + + /// + /// Gets a value indicating if the backward button is selected + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public bool BackwardButtonSelected + { + get { return _backwardButtonSelected; } + } + + /// + /// Gets the bounds of the backward button + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public Rectangle BackwardButtonBounds + { + get { return _backwardButtonBounds; } + } + + /// + /// Gets a value indicating if the forward button is selected + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public bool ForwardButtonSelected + { + get { return _forwardButtonSelected; } + } + + /// + /// Gets the bounds of the forward button + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public Rectangle ForwardButtonBounds + { + get { return _forwardButtonBounds; } + } + + /// + /// Gets or sets the Font of the Control + /// + public override Font Font + { + get + { + return base.Font; + } + set + { + base.Font = value; + + UpdateMonthSize(); + UpdateMonths(); + } + } + + /// + /// Gets or sets the internal padding of items (Days, day names, month names) + /// + public Padding ItemPadding + { + get { return _itemPadding; } + set { _itemPadding = value; } + } + + /// + /// Gets or sets the maximum selection count of days + /// + [DefaultValue( 0 )] + public int MaxSelectionCount + { + get { return _maxSelectionCount; } + set { _maxSelectionCount = value; } + } + + /// + /// Gets the Months currently displayed on the calendar + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public MonthViewMonth[] Months + { + get { return _months; } + } + + /// + /// Gets the size of an entire month inside the + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public Size MonthSize + { + get { return _monthSize; } + } + + /// + /// Gets or sets the format of month titles + /// + [DefaultValue( "MMMM yyyy" )] + public string MonthTitleFormat + { + get { return _monthTitleFormat; } + set { _monthTitleFormat = value; UpdateMonths(); } + } + + /// + /// Gets or sets the start of selection + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public DateTime SelectionStart + { + get { return _selectionStart; } + set + { + if( MaxSelectionCount > 0 ) + { + if( Math.Abs( value.Subtract( SelectionEnd ).TotalDays ) >= MaxSelectionCount ) + { + return; + } + } + + _selectionStart = value; + Invalidate(); + OnSelectionChanged( EventArgs.Empty ); + } + } + + /// + /// Gets or sets the end of selection + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public DateTime SelectionEnd + { + get { return _selectionEnd; } + set + { + if( MaxSelectionCount > 0 ) + { + if( Math.Abs( value.Subtract( SelectionStart ).TotalDays ) >= MaxSelectionCount ) + { + return; + } + } + + _selectionEnd = value.Date.Add( new TimeSpan( 23, 59, 59 ) ); + Invalidate(); + OnSelectionChanged( EventArgs.Empty ); + } + } + + /// + /// Gets or sets the selection mode of + /// + [DefaultValue( MonthViewSelection.Manual )] + public MonthViewSelection SelectionMode + { + get { return _selectionMode; } + set { _selectionMode = value; } + } + + /// + /// Gets or sets the date of the first displayed month + /// + [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )] + public DateTime ViewStart + { + get { return _viewStart; } + set { _viewStart = value; UpdateMonths(); Invalidate(); } + } + + /// + /// Gets the last day of the last month showed on the view. + /// + public DateTime ViewEnd + { + get + { + DateTime month = Months[Months.Length - 1].Date; + return month.Date.AddDays( DateTime.DaysInMonth( month.Year, month.Month ) ); + } + } + + /// + /// Gets or sets the day that starts a work-week + /// + [DefaultValue( DayOfWeek.Monday )] + public DayOfWeek WorkWeekStart + { + get { return _workWeekStart; } + set { _workWeekStart = value; } + } + + /// + /// Gets or sets the day that ends a work-week + /// + [DefaultValue( DayOfWeek.Friday )] + public DayOfWeek WorkWeekEnd + { + get { return _workWeekEnd; } + set { _workWeekEnd = value; } + } + + #endregion + + #region Color Properties + + /// + /// Gets or sets the color of the arrows selected. + /// + /// + /// The color of the arrows selected. + /// + public Color ArrowsSelectedColor + { + get { return _arrowsSelectedColor; } + set { _arrowsSelectedColor = value; } + } + + /// + /// Gets or sets the color of the arrows. + /// + /// + /// The color of the arrows. + /// + public Color ArrowsColor + { + get { return _arrowsColor; } + set { _arrowsColor = value; } + } + + /// + /// Gets or sets the color of the day selected text. + /// + /// + /// The color of the day selected text. + /// + public Color DaySelectedTextColor + { + get { return _daySelectedTextColor; } + set { _daySelectedTextColor = value; } + } + + /// + /// Gets or sets the color of the day selected. + /// + /// + /// The color of the day selected. + /// + public Color DaySelectedColor + { + get { return _dayTextColor; } + set { _dayTextColor = value; } + } + + /// + /// Gets or sets the color of the day selected background. + /// + /// + /// The color of the day selected background. + /// + public Color DaySelectedBackgroundColor + { + get { return _daySelectedBackgroundColor; } + set { _daySelectedBackgroundColor = value; } + } + + /// + /// Gets or sets the color of the day background. + /// + /// + /// The color of the day background. + /// + public Color DayBackgroundColor + { + get { return _dayBackgroundColor; } + set { _dayBackgroundColor = value; } + } + + /// + /// Gets or sets the day grayed text. + /// + /// + /// The day grayed text. + /// + public Color DayGrayedText + { + get { return _dayGrayedText; } + set { _dayGrayedText = value; } + } + + /// + /// Gets or sets the color of the month title. + /// + /// + /// The color of the month title. + /// + public Color MonthTitleColor + { + get { return _monthTitleColor; } + set { _monthTitleColor = value; } + } + + /// + /// Gets or sets the month title text color inactive. + /// + /// + /// The month title text color inactive. + /// + public Color MonthTitleTextColorInactive + { + get { return _monthTitleTextColorInactive; } + set { _monthTitleTextColorInactive = value; } + } + + /// + /// Gets or sets the color of the month title text. + /// + /// + /// The color of the month title text. + /// + public Color MonthTitleTextColor + { + get { return _monthTitleTextColor; } + set { _monthTitleTextColor = value; } + } + + /// + /// Gets or sets the month title color inactive. + /// + /// + /// The month title color inactive. + /// + public Color MonthTitleColorInactive + { + get { return _monthTitleColorInactive; } + set { _monthTitleColorInactive = value; } + } + + /// + /// Gets or sets the color of the today day border color + /// + public Color TodayBorderColor + { + get { return _todayBorderColor; } + set { _todayBorderColor = value; } + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + public MonthView() + { + SetStyle(ControlStyles.Opaque, true); + DoubleBuffered = true; + + _dayNamesFormat = "ddd"; + _monthTitleFormat = "MMMM yyyy"; + _selectionMode = MonthViewSelection.Manual; + _workWeekStart = DayOfWeek.Monday; + _workWeekEnd = DayOfWeek.Friday; + _weekStart = DayOfWeek.Sunday; + _dayNamesVisible = true; + _dayNamesLength = 2; + _viewStart = DateTime.Now; + _itemPadding = new Padding(2); + _monthTitleColor = SystemColors.ActiveCaption; + _monthTitleColorInactive = SystemColors.InactiveCaption; + _monthTitleTextColor = SystemColors.ActiveCaptionText; + _monthTitleTextColorInactive = SystemColors.InactiveCaptionText; + _dayBackgroundColor = Color.Empty; + _daySelectedBackgroundColor = SystemColors.Highlight; + _dayTextColor = SystemColors.WindowText; + _daySelectedTextColor = SystemColors.HighlightText; + _arrowsColor = SystemColors.Window; + _arrowsSelectedColor = Color.Gold; + _dayGrayedText = SystemColors.GrayText; + _todayBorderColor = Color.Maroon; + + UpdateMonthSize(); + UpdateMonths(); + } + + #region Public Methods + + /// + /// Checks if a day is hitted on the specified point + /// + /// + /// + public MonthViewDay HitTest(Point p) + { + for (int i = 0; i < Months.Length; i++) + { + if (Months[i].Bounds.Contains(p)) + { + for (int j = 0; j < Months[i].Days.Length; j++) + { + if (/*Months[i].Days[j].Visible && */Months[i].Days[j].Bounds.Contains(p)) + { + return Months[i].Days[j]; + } + } + } + } + + return null; + } + + /// + /// Moves the view one month forward + /// + public void GoForward() + { + ViewStart = ViewStart.AddMonths(1); + } + + /// + /// Moves the view one month backward + /// + public void GoBackward() + { + ViewStart = ViewStart.AddMonths(-1); + } + + #endregion + + #region Private Methods + + /// + /// Sets the forward button bounds. + /// + /// The bounds. + private void SetForwardButtonBounds(Rectangle bounds) + { + _forwardButtonBounds = bounds; + } + + /// + /// Sets the backward button bounds. + /// + /// The bounds. + private void SetBackwardButtonBounds(Rectangle bounds) + { + _backwardButtonBounds = bounds; + } + + /// + /// Sets the forward button selected. + /// + /// if set to true [selected]. + private void SetForwardButtonSelected(bool selected) + { + _forwardButtonSelected = selected; + Invalidate(ForwardButtonBounds); + } + + /// + /// Sets the backward button selected. + /// + /// if set to true [selected]. + private void SetBackwardButtonSelected(bool selected) + { + _backwardButtonSelected = selected; + Invalidate(BackwardButtonBounds); + } + + /// + /// Selects the week where the hit is contained + /// + /// + private void SelectWeek(DateTime hit) + { + int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[(int)hit.DayOfWeek] - (int)FirstDayOfWeek; + + _selectionStart = hit.AddDays(-preDays); + SelectionEnd = SelectionStart.AddDays(6); + } + + /// + /// Selecs the work-week where the hit is contanied + /// + /// + private void SelectWorkWeek(DateTime hit) + { + int preDays = (new int[] { 0, 1, 2, 3, 4, 5, 6 })[(int)hit.DayOfWeek] - (int)WorkWeekStart; + + _selectionStart = hit.AddDays(-preDays); + SelectionEnd = SelectionStart.AddDays(Math.Abs(WorkWeekStart - WorkWeekEnd)); + } + + /// + /// Selecs the month where the hit is contanied + /// + /// + private void SelectMonth(DateTime hit) + { + _selectionStart = new DateTime(hit.Year, hit.Month, 1); + SelectionEnd = new DateTime(hit.Year, hit.Month, DateTime.DaysInMonth(hit.Year, hit.Month)); + } + + /// + /// Draws a box of text + /// + /// + private void DrawBox(MonthViewBoxEventArgs e) + { + if (!e.BackgroundColor.IsEmpty) + { + using (SolidBrush b = new SolidBrush(e.BackgroundColor)) + { + e.Graphics.FillRectangle(b, e.Bounds); + } + } + + if (!e.TextColor.IsEmpty && !string.IsNullOrEmpty(e.Text)) + { + TextRenderer.DrawText(e.Graphics, e.Text, e.Font != null ? e.Font : Font, e.Bounds, e.TextColor, e.TextFlags); + } + + if (!e.BorderColor.IsEmpty) + { + using (Pen p = new Pen(e.BorderColor)) + { + Rectangle r = e.Bounds; + r.Width--; r.Height--; + e.Graphics.DrawRectangle(p, r); + } + } + } + + /// + /// Updates the size of the month. + /// + private void UpdateMonthSize() + { + //One row of day names plus 31 possible numbers + string[] strs = new string[7 + 31]; + int maxWidth = 0; + int maxHeight = 0; + + for (int i = 0; i < 7; i++) + { + strs[i] = ViewStart.AddDays(i).ToString(DayNamesFormat).Substring(0, DayNamesLength); + } + + for (int i = 7; i < strs.Length; i++) + { + strs[i] = (i - 6).ToString(); + } + + Font f = new Font(Font, FontStyle.Bold); + + for (int i = 0; i < strs.Length; i++) + { + Size s = TextRenderer.MeasureText(strs[i], f); + maxWidth = Math.Max(s.Width, maxWidth); + maxHeight = Math.Max(s.Height, maxHeight); + } + + maxWidth += ItemPadding.Horizontal; + maxHeight += ItemPadding.Vertical; + + _daySize = new Size(maxWidth, maxHeight); + _monthSize = new Size(maxWidth * 7, maxHeight * 7 + maxHeight * (DayNamesVisible ? 1 : 0)); + } + + /// + /// Updates the months. + /// + private void UpdateMonths() + { + int gapping = 2; + int calendarsX = Convert.ToInt32(Math.Max(Math.Floor((double)ClientSize.Width / (double)(MonthSize.Width + gapping)), 1.0)); + int calendarsY = Convert.ToInt32(Math.Max(Math.Floor((double)ClientSize.Height / (double)(MonthSize.Height + gapping)), 1.0)); + int calendars = calendarsX * calendarsY; + int monthsWidth = (calendarsX * MonthSize.Width) + (calendarsX - 1) * gapping; + int monthsHeight = (calendarsY * MonthSize.Height) + (calendarsY - 1) * gapping; + int startX = (ClientSize.Width - monthsWidth) / 2; + int startY = (ClientSize.Height - monthsHeight) / 2; + int curX = startX; + int curY = startY; + _forwardMonthIndex = calendarsX - 1; + + _months = new MonthViewMonth[calendars]; + + for (int i = 0; i < Months.Length; i++) + { + Months[i] = new MonthViewMonth(this, ViewStart.AddMonths(i)); + Months[i].SetLocation(new Point(curX, curY)); + + curX += gapping + MonthSize.Width; + + if ((i + 1) % calendarsX == 0) + { + curX = startX; + curY += gapping + MonthSize.Height; + } + } + + MonthViewMonth first = Months[0]; + MonthViewMonth last = Months[_forwardMonthIndex]; + + SetBackwardButtonBounds(new Rectangle(first.Bounds.Left + ItemPadding.Left, first.Bounds.Top + ItemPadding.Top, DaySize.Height - ItemPadding.Horizontal, DaySize.Height - ItemPadding.Vertical)); + SetForwardButtonBounds(new Rectangle(first.Bounds.Right - ItemPadding.Right - BackwardButtonBounds.Width, first.Bounds.Top + ItemPadding.Top, BackwardButtonBounds.Width, BackwardButtonBounds.Height )); + } + + #endregion + + #region Overrides + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnGotFocus(EventArgs e) + { + base.OnGotFocus(e); + + Invalidate(); + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + + Focus(); + + _mouseDown = true; + + MonthViewDay day = HitTest(e.Location); + + if (day != null) + { + switch (SelectionMode) + { + case MonthViewSelection.Manual: + case MonthViewSelection.Day: + SelectionEnd = _selectionStart = day.Date; + break; + case MonthViewSelection.WorkWeek: + SelectWorkWeek(day.Date); + break; + case MonthViewSelection.Week: + SelectWeek(day.Date); + break; + case MonthViewSelection.Month: + SelectMonth(day.Date); + break; + } + } + + if (ForwardButtonSelected) + { + GoForward(); + } + else if (BackwardButtonSelected) + { + GoBackward(); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (_mouseDown) + { + MonthViewDay day = HitTest(e.Location); + + if (day != null && day != _lastHitted) + { + switch (SelectionMode) + { + case MonthViewSelection.Manual: + if (day.Date > SelectionStart) + { + SelectionEnd = day.Date; + } + else + { + SelectionStart = day.Date; + } + break; + case MonthViewSelection.Day: + SelectionEnd = _selectionStart = day.Date; + break; + case MonthViewSelection.WorkWeek: + SelectWorkWeek(day.Date); + break; + case MonthViewSelection.Week: + SelectWeek(day.Date); + break; + case MonthViewSelection.Month: + SelectMonth(day.Date); + break; + } + + _lastHitted = day; + } + } + + if (ForwardButtonBounds.Contains(e.Location)) + { + SetForwardButtonSelected(true); + } + else if (ForwardButtonSelected) + { + SetForwardButtonSelected(false); + } + + if (BackwardButtonBounds.Contains(e.Location)) + { + SetBackwardButtonSelected(true); + } + else if (BackwardButtonSelected) + { + SetBackwardButtonSelected(false); + } + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + + _mouseDown = false; + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnMouseWheel(MouseEventArgs e) + { + base.OnMouseWheel(e); + + if (e.Delta < 0) + { + GoForward(); + } + else + { + GoBackward(); + } + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnLostFocus(EventArgs e) + { + base.OnLostFocus(e); + + Invalidate(); + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + e.Graphics.Clear(SystemColors.Window); + + for (int i = 0; i < Months.Length; i++) + { + if (Months[i].Bounds.IntersectsWith(e.ClipRectangle)) + { + #region MonthTitle + + string title = Months[i].Date.ToString(MonthTitleFormat); + MonthViewBoxEventArgs evtTitle = new MonthViewBoxEventArgs(e.Graphics, Months[i].MonthNameBounds, + title, + Focused ? MonthTitleTextColor : MonthTitleTextColorInactive, + Focused ? MonthTitleColor : MonthTitleColorInactive); + + DrawBox(evtTitle); + + #endregion + + #region DayNames + + for (int j = 0; j < Months[i].DayNamesBounds.Length; j++) + { + MonthViewBoxEventArgs evtDay = new MonthViewBoxEventArgs(e.Graphics, Months[i].DayNamesBounds[j], Months[i].DayHeaders[j], + StringAlignment.Far, ForeColor, DayBackgroundColor); + + DrawBox(evtDay); + } + + if (Months[i].DayNamesBounds != null && Months[i].DayNamesBounds.Length != 0) + { + using (Pen p = new Pen(MonthTitleColor)) + { + int y = Months[i].DayNamesBounds[0].Bottom; + e.Graphics.DrawLine(p, new Point(Months[i].Bounds.X, y), new Point(Months[i].Bounds.Right, y)); + } + } + #endregion + + #region Days + foreach (MonthViewDay day in Months[i].Days) + { + if (!day.Visible) continue; + + MonthViewBoxEventArgs evtDay = new MonthViewBoxEventArgs(e.Graphics, day.Bounds, day.Date.Day.ToString(), + StringAlignment.Far, + day.Grayed ? DayGrayedText : (day.Selected ? DaySelectedTextColor : ForeColor), + day.Selected ? DaySelectedBackgroundColor : DayBackgroundColor); + + if (day.Date.Equals(DateTime.Now.Date)) + { + evtDay.BorderColor = TodayBorderColor; + } + + DrawBox(evtDay); + } + #endregion + + #region Arrows + + if (i == 0) + { + Rectangle r = BackwardButtonBounds; + using (Brush b = new SolidBrush(BackwardButtonSelected ? ArrowsSelectedColor : ArrowsColor)) + { + e.Graphics.FillPolygon(b, new Point[] { + new Point(r.Right, r.Top), + new Point(r.Right, r.Bottom - 1), + new Point(r.Left + r.Width / 2, r.Top + r.Height / 2), + }); + } + } + + if (i == _forwardMonthIndex) + { + Rectangle r = ForwardButtonBounds; + using (Brush b = new SolidBrush(ForwardButtonSelected ? ArrowsSelectedColor : ArrowsColor)) + { + e.Graphics.FillPolygon(b, new Point[] { + new Point(r.X, r.Top), + new Point(r.X, r.Bottom - 1), + new Point(r.Left + r.Width / 2, r.Top + r.Height / 2), + }); + } + } + + #endregion + } + } + } + + /// + /// Raises the event. + /// + /// An that contains the event data. + protected override void OnResize(EventArgs e) + { + UpdateMonths(); + Invalidate(); + } + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected void OnSelectionChanged(EventArgs e) + { + if (SelectionChanged != null) + { + SelectionChanged(this, e); + } + } + + #endregion + + } +} + diff --git a/WindowsFormsCalendar/WindowsFormsCalendar.csproj b/WindowsFormsCalendar/WindowsFormsCalendar.csproj new file mode 100644 index 0000000..e352a3d --- /dev/null +++ b/WindowsFormsCalendar/WindowsFormsCalendar.csproj @@ -0,0 +1,144 @@ + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {25649F08-3046-4891-ADB8-7EA787B57063} + Library + Properties + WindowsFormsCalendar + WindowsFormsCalendar + v4.0 + + + 2.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\WindowsFormsCalendar.XML + + + false + + + + + + + + + + + + + + + + + + + + + + + + + Component + + + + + + + + + + + + + + + + + + + Component + + + + + + + + + + + + + + + Component + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + \ No newline at end of file diff --git a/WindowsFormsCalendar/help/Documentation.chm b/WindowsFormsCalendar/help/Documentation.chm new file mode 100644 index 0000000..2f1c308 Binary files /dev/null and b/WindowsFormsCalendar/help/Documentation.chm differ