commit a083e412fd34aa33dda65e0298920c2c96ceec41 Author: roberti Date: Mon Feb 16 22:56:35 2015 +0100 init commit diff --git a/DayPilot.csproj b/DayPilot.csproj new file mode 100644 index 0000000..5dcb392 --- /dev/null +++ b/DayPilot.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {5D7983A4-CCFF-46F6-920F-F184A031D7E1} + Library + Properties + DayPilot + DayPilot + + + 3.5 + + + v2.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\Corp\ + DEBUG;TRACE + full + AnyCPU + prompt + AllRules.ruleset + true + true + + + + + + + + + + + + + True + True + Settings.settings + + + + + + + + + + + + + + + + + + + + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + \ No newline at end of file diff --git a/DayPilot.sln b/DayPilot.sln new file mode 100644 index 0000000..c948368 --- /dev/null +++ b/DayPilot.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DayPilot", "DayPilot.csproj", "{5D7983A4-CCFF-46F6-920F-F184A031D7E1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dpMvc2", "..\..\..\Projects\dpMvc2\dpMvc2.csproj", "{2A46CBBE-6F72-433B-96ED-6B5CEA12F696}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5D7983A4-CCFF-46F6-920F-F184A031D7E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D7983A4-CCFF-46F6-920F-F184A031D7E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D7983A4-CCFF-46F6-920F-F184A031D7E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D7983A4-CCFF-46F6-920F-F184A031D7E1}.Release|Any CPU.Build.0 = Release|Any CPU + {2A46CBBE-6F72-433B-96ED-6B5CEA12F696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A46CBBE-6F72-433B-96ED-6B5CEA12F696}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A46CBBE-6F72-433B-96ED-6B5CEA12F696}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A46CBBE-6F72-433B-96ED-6B5CEA12F696}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4dd117b --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System.Reflection; +using System.Runtime.InteropServices; +using System.Web.UI; + +// 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("DayPilot")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DayPilot")] +[assembly: AssemblyCopyright("Copyright © 2005 - 2008 Annpoint, s.r.o.")] +[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("e5d0e09d-0160-4c7c-a16e-374ba8867712")] + +[assembly: TagPrefix("DayPilot.Web.Ui", "DayPilot")] + +// 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("3.0.210.0")] +[assembly: AssemblyFileVersion("3.0.210.0")] diff --git a/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs new file mode 100644 index 0000000..10ef68c --- /dev/null +++ b/Properties/Settings.Designer.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.20506.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DayPilot.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; + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)] + [global::System.Configuration.DefaultSettingValueAttribute("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\bookings.mdf;Integrated" + + " Security=True;User Instance=True")] + public string bookingsConnectionString { + get { + return ((string)(this["bookingsConnectionString"])); + } + } + } +} diff --git a/Properties/Settings.settings b/Properties/Settings.settings new file mode 100644 index 0000000..3b13c1f --- /dev/null +++ b/Properties/Settings.settings @@ -0,0 +1,14 @@ + + + + + + <?xml version="1.0" encoding="utf-16"?> +<SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <ConnectionString>Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\bookings.mdf;Integrated Security=True;User Instance=True</ConnectionString> + <ProviderName>System.Data.SqlClient</ProviderName> +</SerializableConnectionString> + Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\bookings.mdf;Integrated Security=True;User Instance=True + + + \ No newline at end of file diff --git a/Utils/Encoder.cs b/Utils/Encoder.cs new file mode 100644 index 0000000..f01cfbd --- /dev/null +++ b/Utils/Encoder.cs @@ -0,0 +1,123 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using System.Globalization; +using System.Text; +using System.Web; + +namespace DayPilot.Utils +{ + internal class Encoder + { + private static HttpApplication _app = null; + private static HttpServerUtility Server + { + get + { + if (HttpContext.Current != null) + return HttpContext.Current.Server; + + if (_app == null) + _app = new HttpApplication(); + return _app.Server; + } + } + + internal static string HtmlEncode(string input) + { + if (input == null) + { + return null; + } + + return Server.HtmlEncode(input); + } + + + internal static string UrlEncode(string input) + { +// return Server.UrlPathEncode(input); + if (input == null) + { + return null; + } + return input.Replace("&", "%26"); +// return Server.UrlEncode(input); + } + + internal static string UrlDecode(string input) + { + return Server.UrlDecode(input); + } + + internal static DateTime UrlDecodeDateTime(string input) + { + CultureInfo culture = new CultureInfo("en-US"); + string decoded = Server.UrlDecode(input); + + try + { + return DateTime.ParseExact(decoded, culture.DateTimeFormat.SortableDateTimePattern, culture.DateTimeFormat); + } + catch (FormatException e) + { + throw new ApplicationException("Unable to parse DateTime: '" + decoded + "'.", e); + } + } + + internal static string UrlEncode(IList list) + { + StringBuilder sb = new StringBuilder(); + + bool isFirst = true; + foreach (object o in list) + { + string item; + if (o is DateTime) + { + DateTime dt = (DateTime) o; + item = dt.ToString("s"); + } + else if (o == null) + { + item = String.Empty; + } + else + { + item = o.ToString(); + } + + if (!isFirst) + { + sb.Append("&"); + } + + sb.Append(UrlEncode(item)); + + isFirst = false; + } + + return sb.ToString(); + } + } +} diff --git a/Utils/TimeFormatter.cs b/Utils/TimeFormatter.cs new file mode 100644 index 0000000..679645e --- /dev/null +++ b/Utils/TimeFormatter.cs @@ -0,0 +1,83 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using DayPilot.Web.Ui; + +namespace DayPilot.Utils +{ + /// + /// Helper class for hour formatting. + /// + public class TimeFormatter + { + /// + /// Extracts hour from DateTime class and formats it for 12/24 hours clock. + /// + /// + /// + /// + /// + public static string GetHour(DateTime time, TimeFormat clock, string format) + { + return GetHour(time.Hour, clock, format); + } + + /// + /// Formats an hour number for 12/24 hours clock. + /// + /// + /// + /// + /// + public static string GetHour(int hour, TimeFormat clock, string format) + { + bool am = (hour / 12) == 0; + if (clock == TimeFormat.Clock12Hours) + { + hour = hour % 12; + if (hour == 0) + hour = 12; + } + + string suffix = String.Empty; + if (clock == TimeFormat.Clock12Hours) + { + if (am) + { + suffix = "AM"; + } + else + { + suffix = "PM"; + } + } + + if (String.IsNullOrEmpty(format)) + { + format = "{0} {1}"; + } + + return String.Format(format, hour, suffix); + + } + } +} diff --git a/Utils/Week.cs b/Utils/Week.cs new file mode 100644 index 0000000..c904ca3 --- /dev/null +++ b/Utils/Week.cs @@ -0,0 +1,158 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ +using System; +using System.Collections; +using System.Threading; + +namespace DayPilot.Utils +{ + /// + /// Helper class for week manipulation and formatting. + /// + public class Week + { + /// + /// Gets the first day of this week. Based on current culture. + /// + /// + public static DateTime FirstDayOfWeek() + { + return FirstDayOfWeek(DateTime.Today); + } + + /// + /// Gets the first day of a week where day (parameter) belongs. Based on current culture. + /// + /// + public static DateTime FirstDayOfWeek(DateTime day) + { + return FirstDayOfWeek(day, Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek); + } + + + /// + /// Gets the first day of a week where day (parameter) belongs. weekStart (parameter) specifies the starting day of week. + /// + /// + public static DateTime FirstDayOfWeek(DateTime day, DayOfWeek weekStarts) + { + DateTime d = day; + while (d.DayOfWeek != weekStarts) + { + d = d.AddDays(-1); + } + + return d; + } + + /// + /// Returns Monday of the week where day (parameter) belongs. + /// + /// + /// + public static DateTime FirstWorkingDayOfWeek(DateTime day) + { + return FirstDayOfWeek(day, DayOfWeek.Monday); + } + + + // http://konsulent.sandelien.no/VB_help/Week/ + // just for Monday being the first day of week + /// + /// Calculates week number for the specified date according to ISO 8601. + /// + /// + /// + public static int WeekNrISO8601(DateTime date) + { + bool ThursdayFlag = false; + int DayOfYear = date.DayOfYear; + + int StartWeekDayOfYear = + (int)(new DateTime(date.Year, 1, 1)).DayOfWeek; + int EndWeekDayOfYear = + (int)(new DateTime(date.Year, 12, 31)).DayOfWeek; + + if (StartWeekDayOfYear == 0) + StartWeekDayOfYear = 7; + if (EndWeekDayOfYear == 0) + EndWeekDayOfYear = 7; + + int DaysInFirstWeek = 8 - (StartWeekDayOfYear); + + if (StartWeekDayOfYear == 4 || EndWeekDayOfYear == 4) + ThursdayFlag = true; + + int FullWeeks = (int)Math.Ceiling((DayOfYear - (DaysInFirstWeek)) / 7.0); + + int WeekNumber = FullWeeks; + + if (DaysInFirstWeek >= 4) + WeekNumber = WeekNumber + 1; + + if (WeekNumber > 52 && !ThursdayFlag) + WeekNumber = 1; + + if (WeekNumber == 0) + WeekNumber = WeekNrISO8601(new DateTime(date.Year - 1, 12, 31)); + return WeekNumber; + } + + + /// + /// Returns day names (using current culture). + /// + /// + public static ArrayList GetDayNames() + { + return GetDayNames("dddd"); + } + + /// + /// Returns day names (using current culture). + /// + /// Corresponds to DateTime.ToString() formats. "DD" is also available (first two characters of short day name). + /// + public static ArrayList GetDayNames(string format) + { + ArrayList result = new ArrayList(); + DateTime start = new DateTime(2006, 12, 31); // Sunday + for (int i = 0; i < 7; i++) + { + // this uses the current culture + string name; + if (format == "DD") + { + name = start.AddDays(i).ToString("ddd").Substring(0, 2); + } + else + { + name = start.AddDays(i).ToString(format); + } + + + result.Add(name); + } + return result; + } + + } +} diff --git a/Web/Ui/Block.cs b/Web/Ui/Block.cs new file mode 100644 index 0000000..d5cf668 --- /dev/null +++ b/Web/Ui/Block.cs @@ -0,0 +1,127 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; + +namespace DayPilot.Web.Ui +{ + /// + /// Block is a set of concurrent events. + /// + internal class Block + { + internal ArrayList Columns; + private ArrayList events = new ArrayList(); + + + internal Block() + { + } + + internal void Add(Event ev) + { + events.Add(ev); + arrangeColumns(); + } + + private Column createColumn() + { + Column col = new Column(); + this.Columns.Add(col); + col.Block = this; + + return col; + } + + + private void arrangeColumns() + { + // cleanup + this.Columns = new ArrayList(); + + foreach(Event e in events) + e.Column = null; + + // there always will be at least one column because arrangeColumns is called only from Add() + createColumn(); + + foreach (Event e in events) + { + foreach (Column col in Columns) + { + if (col.CanAdd(e)) + { + col.Add(e); + break; + } + } + // it wasn't placed + if (e.Column == null) + { + Column col = createColumn(); + col.Add(e); + } + } + } + + internal bool OverlapsWith(Event e) + { + if (events.Count == 0) + return false; + + return (this.BoxStart < e.BoxEnd && this.BoxEnd > e.BoxStart); + } + + internal DateTime BoxStart + { + get + { + DateTime min = DateTime.MaxValue; + + foreach(Event ev in events) + { + if (ev.BoxStart < min) + min = ev.BoxStart; + } + + return min; + } + } + + internal DateTime BoxEnd + { + get + { + DateTime max = DateTime.MinValue; + + foreach(Event ev in events) + { + if (ev.BoxEnd > max) + max = ev.BoxEnd; + } + + return max; + } + } + + } +} diff --git a/Web/Ui/Column.cs b/Web/Ui/Column.cs new file mode 100644 index 0000000..e245ce2 --- /dev/null +++ b/Web/Ui/Column.cs @@ -0,0 +1,119 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using DayPilot.Web.Ui; + +namespace DayPilot.Web.Ui +{ + /// + /// Column is a column of events in a Block. + /// + public class Column + { + private ArrayList events = new ArrayList(); + internal Block Block; + + /// + /// Gets the width of the column in percent. + /// + public int WidthPct + { + get + { + if (Block == null) + throw new ApplicationException("This Column does not belong to any Block."); + + if (Block.Columns.Count == 0) + throw new ApplicationException("Internal error: Problem with Block.Column.Counts (it is zero)."); + + // the last block will be a bit longer to make sure the total width is 100% + if (isLastInBlock) + return 100 / Block.Columns.Count + 100 % Block.Columns.Count; + else + return 100 / Block.Columns.Count; + } + } + + /// + /// Gets the starting percent of the column. + /// + public int StartsAtPct + { + get + { + if (Block == null) + throw new ApplicationException("This Column does not belong to any Block."); + + if (Block.Columns.Count == 0) + throw new ApplicationException("Internal error: Problem with Block.Column.Counts (it is zero)."); + + return 100 / Block.Columns.Count * Number; + } + } + + private bool isLastInBlock + { + get + { + return Block.Columns[Block.Columns.Count - 1] == this; + } + } + + internal Column() + { + } + + internal bool CanAdd(Event e) + { + foreach (Event ev in events) + { + if (ev.OverlapsWith(e)) + return false; + } + return true; + } + + internal void Add(Event e) + { + if (e.Column != null) + throw new ApplicationException("This Event was already placed into a Column."); + + events.Add(e); + e.Column = this; + } + + /// + /// Gets the order number of the column. + /// + public int Number + { + get + { + if (Block == null) + throw new ApplicationException("This Column doesn't belong to any Block."); + + return Block.Columns.IndexOf(this); + } + } + } +} diff --git a/Web/Ui/Day.cs b/Web/Ui/Day.cs new file mode 100644 index 0000000..70c4c2a --- /dev/null +++ b/Web/Ui/Day.cs @@ -0,0 +1,236 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace DayPilot.Web.Ui +{ + /// + /// Day handles events of a single day. + /// + internal class Day : ISerializable + { + internal List events = new List(); + private List blocks = new List(); + + internal int cellDuration; // in minutes + + private DateTime start; + internal DateTime end; + + internal string Name; + internal string Value; + + internal DateTime Start + { + get { return start; } + } + + internal DateTime End + { + get { return end; } + } + + public Day(DateTime date) + { + this.start = date.Date; + this.end = date.Date.AddDays(1); + } + + internal Day(DateTime start, DateTime end, string header, string id, int cellDuration) + { + this.start = start.Date; + this.end = end.Date; + this.Name = header; + this.Value = id; + this.cellDuration = cellDuration; + } + + private void stripAndAddEvent(Event e) + { + stripAndAddEvent(e.Start, e.End, e.PK, e.Name, e.Resource, e.Owner); + } + + private void stripAndAddEvent(DateTime start, DateTime end, string pk, string name, string resource, string owner) + { + if (!String.IsNullOrEmpty(Value)) // this applies to resources view only + { + if (Value != resource) // don't add events that don't belong to this column + return; + } + + // the event happens before this day + if (end <= Start) + return; + + // the event happens after this day + if (start >= End) + return; + + // this is invalid event that does have no duration + if (start >= end) + return; + + // fix the starting time + if (start < Start) + start = Start; + + + // fix the ending time + if (end > End) + end = End; + + events.Add(new Event(pk, start, end, name, resource, owner)); + } + +/* + private void stripAndAddEvent(Event e) + { + if (!String.IsNullOrEmpty(Value)) // this applies to resources view only + { + if (Value != e.Resource) // don't add events that don't belong to this column + return; + } + + // the event happens before this day + if (e.End <= Start) + return; + + // the event happens after this day + if (e.Start >= End.AddDays(1)) + return; + + // this is invalid event that has no duration + if (e.Start >= e.End) + return; + + // Event part = new Event(this, e); + events.Add(e); + + + } +*/ + + /// + /// Loads events from ArrayList of Events. + /// + /// ArrayList that contains the Events. + public void Load(ArrayList events) + { + if (events == null) + { + return; + } + + foreach (Event e in events) + { + stripAndAddEvent(e); + } + putIntoBlocks(); + } + + private void putIntoBlocks() + { + foreach (Event e in events) + { + // if there is no block, create the first one + if (lastBlock == null) + { + blocks.Add(new Block()); + } + // or if the event doesn't overlap with the last block, create a new block + else if (!lastBlock.OverlapsWith(e)) + { + blocks.Add(new Block()); + } + + // any case, add it to some block + lastBlock.Add(e); + + } + } + + private Block lastBlock + { + get + { + if (blocks.Count == 0) + return null; + return blocks[blocks.Count - 1]; + } + } + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + } + + internal int MaxColumns() + { + int i = 1; + foreach (Block b in blocks) + { + if (b.Columns.Count > i) + i = b.Columns.Count; + } + return i; + } + + public DateTime BoxStart + { + get + { + DateTime min = DateTime.MaxValue; + + foreach (Block block in blocks) + { + if (block.BoxStart < min) + min = block.BoxStart; + } + + return min; + } + } + + /// + /// The end of the box of the last event. + /// + public DateTime BoxEnd + { + get + { + DateTime max = DateTime.MinValue; + + foreach (Block block in blocks) + { + if (block.BoxEnd > max) + max = block.BoxEnd; + } + + return max; + } + } + + + } +} diff --git a/Web/Ui/DayPilotCalendar.cs b/Web/Ui/DayPilotCalendar.cs new file mode 100644 index 0000000..0a75fbf --- /dev/null +++ b/Web/Ui/DayPilotCalendar.cs @@ -0,0 +1,909 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using System.ComponentModel; +using System.Drawing; +using System.Security.Permissions; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using DayPilot.Web.Ui.Design; + +namespace DayPilot.Web.Ui +{ + /// + /// DayPilot is a component for showing a day schedule. + /// + [ToolboxBitmap(typeof(Calendar))] + [Designer(typeof(DayPilotCalendarDesigner))] + [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] + public partial class DayPilotCalendar : DataBoundControl, IPostBackEventHandler + { + internal Day[] days; + + private string dataStartField; + private string dataEndField; + private string dataTextField; + private string dataValueField; + private string dataOwnerField; + + // day header + private bool showHeader = true; + private int headerHeight = 21; + private string headerDateFormat = "d"; + + private ArrayList items; + + /// + /// Event called when the user clicks an event in the calendar. It's only called when EventClickHandling is set to PostBack. + /// + [Category("User actions")] + [Description("Event called when the user clicks an event in the calendar.")] + public event EventClickDelegate EventClick; + + /// + /// Event called when the user clicks a free space in the calendar. It's only called when FreeTimeClickHandling is set to PostBack. + /// + [Category("User actions")] + [Description("Event called when the user clicks a free space in the calendar.")] + public event FreeClickDelegate FreeTimeClick; + + + #region Viewstate + + /// + /// Loads ViewState. + /// + /// + protected override void LoadViewState(object savedState) + { + if (savedState == null) + return; + + object[] vs = (object[])savedState; + + if (vs.Length != 2) + throw new ArgumentException("Wrong savedState object."); + + if (vs[0] != null) + base.LoadViewState(vs[0]); + + if (vs[1] != null) + items = (ArrayList)vs[1]; + + } + + /// + /// Saves ViewState. + /// + /// + protected override object SaveViewState() + { + object[] vs = new object[2]; + vs[0] = base.SaveViewState(); + vs[1] = items; + + return vs; + } + + #endregion + + #region PostBack + + + /// + /// + /// + /// + public void RaisePostBackEvent(string eventArgument) + { + + if (eventArgument.StartsWith("PK:")) + { + string pk = eventArgument.Substring(3, eventArgument.Length - 3); + if (EventClick != null) + EventClick(this, new EventClickEventArgs(pk)); + } + else if (eventArgument.StartsWith("TIME:")) + { + DateTime time = Convert.ToDateTime(eventArgument.Substring(5, eventArgument.Length - 5)); + if (FreeTimeClick != null) + FreeTimeClick(this, new FreeClickEventArgs(time)); + } + else + { + throw new ArgumentException("Bad argument passed from postback event."); + } + } + + #endregion + + #region Rendering + + /// + /// Renders the component HTML code. + /// + /// + protected override void Render(HtmlTextWriter output) + { + loadEventsToDays(); + + // + output.AddAttribute("id", ClientID); + output.AddAttribute("cellpadding", "0"); + output.AddAttribute("cellspacing", "0"); + output.AddAttribute("border", "0"); + output.AddAttribute("width", Width.ToString()); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("text-align", "left"); + output.RenderBeginTag("table"); + + // + output.RenderBeginTag("tr"); + + // + output.RenderEndTag(); + + // + output.RenderEndTag(); + // + output.RenderEndTag(); + //
+ output.AddAttribute("valign", "top"); + output.RenderBeginTag("td"); + + if (ShowHours) + renderHourNamesTable(output); + + // + output.AddAttribute("width", "100%"); + output.AddAttribute("valign", "top"); + output.RenderBeginTag("td"); + + renderEventsAndCells(output); + + //
+ output.RenderEndTag(); + } + + + private void renderHourNamesTable(HtmlTextWriter output) + { + // output.WriteLine(""); + output.AddAttribute("cellpadding", "0"); + output.AddAttribute("cellspacing", "0"); + output.AddAttribute("border", "0"); + output.AddAttribute("width", this.HourWidth.ToString()); + + output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.RenderBeginTag("table"); + + // first emtpy + output.AddStyleAttribute("height", "1px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(BorderColor)); + output.RenderBeginTag("tr"); + + output.RenderBeginTag("td"); + output.RenderEndTag(); + + // first empty + output.RenderEndTag(); + + if (this.ShowHeader) + renderHourHeader(output); + + for (DateTime i = visibleStart; i < visibleEnd; i = i.AddHours(1)) + { + renderHourTr(output, i); + } + + // + output.RenderEndTag(); + + } + + + private void renderHourTr(HtmlTextWriter output, DateTime i) + { + + // + output.AddStyleAttribute("height", HourHeight + "px"); + output.RenderBeginTag("tr"); + + // + output.AddAttribute("valign", "bottom"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("cursor", "default"); + output.RenderBeginTag("td"); + + //
block +// DivWriter divBlock = new DivWriter(); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(HourNameBorderColor)); + output.AddStyleAttribute("height", (HourHeight - 1) + "px"); + output.AddStyleAttribute("text-align", "right"); + output.RenderBeginTag("div"); +// output.Write(divBlock.BeginTag()); + + //
text +// DivWriter divText = new DivWriter(); + output.AddStyleAttribute("padding", "2px"); + output.AddStyleAttribute("font-family", HourFontFamily); + output.AddStyleAttribute("font-size", HourFontSize); + output.RenderBeginTag("div"); +// output.Write(divText.BeginTag()); + + int hour = i.Hour; + bool am = (i.Hour / 12) == 0; + if (TimeFormat == TimeFormat.Clock12Hours) + { + hour = i.Hour % 12; + if (hour == 0) + hour = 12; + } + + output.Write(hour); + output.Write(" "); + if (TimeFormat == TimeFormat.Clock24Hours) + { + output.Write("00"); + } + else + { + if (am) + output.Write("AM"); + else + output.Write("PM"); + } + output.Write(""); + + output.RenderEndTag(); + output.RenderEndTag(); +// output.Write(divText.EndTag()); +// output.Write(divBlock.EndTag()); + output.RenderEndTag(); // + output.RenderEndTag(); // + } + + + private void renderHourHeader(HtmlTextWriter output) + { + + // + output.AddStyleAttribute("height", (this.HeaderHeight) + "px"); + output.RenderBeginTag("tr"); + + // + output.AddAttribute("valign", "bottom"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("cursor", "default"); + output.RenderBeginTag("td"); + + //
block +// DivWriter divBlock = new DivWriter(); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("text-align", "right"); + output.RenderBeginTag("div"); +// output.Write(divBlock.BeginTag()); + + //
text +// DivWriter divText = new DivWriter(); + output.AddStyleAttribute("padding", "2px"); + output.AddStyleAttribute("font-size", "6pt"); + output.RenderBeginTag("div"); +// output.Write(divText.BeginTag()); + + output.Write(" "); + + output.RenderEndTag(); + output.RenderEndTag(); +// output.Write(divText.EndTag()); +// output.Write(divBlock.EndTag()); + output.RenderEndTag(); // + output.RenderEndTag(); // + } + + private void renderEventsAndCells(HtmlTextWriter output) + { + // output.WriteLine(""); + + if (days != null) + { + // + output.AddAttribute("cellpadding", "0"); + output.AddAttribute("cellspacing", "0"); + output.AddAttribute("border", "0"); + output.AddAttribute("width", "100%"); + output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.RenderBeginTag("table"); + + // first + output.AddStyleAttribute("height", "1px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(BorderColor)); + output.RenderBeginTag("tr"); + + renderEventTds(output); + + // first + output.RenderEndTag(); + + // header + if (this.ShowHeader) + { + renderDayHeaders(output); + } + } + + output.WriteLine(""); + + // render all cells + + for (DateTime i = visibleStart; i < visibleEnd; i = i.AddHours(1)) + { + + // first half-hour + output.RenderBeginTag("tr"); + + addHalfHourCells(output, i, true, false); + + // + output.RenderEndTag(); + + // second half-hour + output.AddStyleAttribute("height", (HourHeight / 2) + "px"); + output.RenderBeginTag("tr"); + + bool isLastRow = (i == visibleEnd.AddHours(-1)); + addHalfHourCells(output, i, false, isLastRow); + + // + output.RenderEndTag(); + } + + //
+ output.RenderEndTag(); + + } + + private void renderDayHeaders(HtmlTextWriter output) + { + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("height", this.HeaderHeight + "px"); + output.RenderBeginTag("tr"); + + foreach (Day d in days) + { + DateTime h = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, 0, 0, 0); + + // + output.AddAttribute("valign", "bottom"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("cursor", "default"); + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.RenderBeginTag("td"); + + //
block +// DivWriter divBlock = new DivWriter(); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("text-align", "center"); + output.RenderBeginTag("div"); +// output.Write(divBlock.BeginTag()); + + //
text +// DivWriter divText = new DivWriter(); + output.AddStyleAttribute("padding", "2px"); + output.AddStyleAttribute("font-family", DayFontFamily); + output.AddStyleAttribute("font-size", DayFontSize); + output.RenderBeginTag("div"); +// output.Write(divText.BeginTag()); + + output.Write(h.ToString(this.headerDateFormat)); + // output.Write(" "); + + output.RenderEndTag(); + output.RenderEndTag(); +// output.Write(divText.EndTag()); +// output.Write(divBlock.EndTag()); + output.RenderEndTag(); // + + + } + + output.RenderEndTag(); + } + + + + private void renderEventTds(HtmlTextWriter output) + { + + int dayPctWidth = 100 / days.Length; + + for (int i = 0; i < days.Length; i++) + { + Day d = days[i]; + + + // + output.AddStyleAttribute("height", "1px"); + output.AddStyleAttribute("text-align", "left"); + output.AddAttribute("width", dayPctWidth + "%"); + output.RenderBeginTag("td"); + + //
position +// DivWriter divPosition = new DivWriter(); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("margin-right", ColumnMarginRight + "px"); + output.AddStyleAttribute("position", "relative"); + output.AddStyleAttribute("height", "1px"); + output.AddStyleAttribute("font-size", "1px"); + output.AddStyleAttribute("margin-top", "-1px"); + output.RenderBeginTag("div"); +// output.Write(divPosition.BeginTag()); + + foreach (Event e in d.events) + { + renderEvent(output, e, d); + } + + //
position +// output.Write(divPosition.EndTag()); + output.RenderEndTag(); + + // + output.RenderEndTag(); + } + } + + private void renderEvent(HtmlTextWriter output, Event e, Day d) + { + string displayTextPopup = e.Name + " (" + e.Start.ToShortTimeString() + " - " + e.End.ToShortTimeString() + ")"+":"+e.Owner; + string displayText = e.Name + ": " + e.Owner; + + // real box dimensions and position + DateTime dayVisibleStart = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleStart.Hour, 0, 0); + DateTime realBoxStart = e.BoxStart < dayVisibleStart ? dayVisibleStart : e.BoxStart; + + DateTime dayVisibleEnd; + if (visibleEnd.Day == 1) + dayVisibleEnd = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleEnd.Hour, 0, 0); + else if (visibleEnd.Day == 2) + dayVisibleEnd = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, visibleEnd.Hour, 0, 0).AddDays(1); + else + throw new ArgumentOutOfRangeException("Unexpected time for dayVisibleEnd."); + + DateTime realBoxEnd = e.BoxEnd > dayVisibleEnd ? dayVisibleEnd : e.BoxEnd; + + // top + double top = (realBoxStart - dayVisibleStart).TotalHours * HourHeight + 1; + if (ShowHeader) + top += this.HeaderHeight; + + // height + double height = ((realBoxEnd - realBoxStart).TotalHours * HourHeight - 2); + + // It's outside of visible area (for NonBusinessHours set to Hide). + // Don't draw it in that case. + if (height <= 0) + { + return; + } + + // MAIN BOX + output.AddAttribute("onselectstart", "return false;"); // prevent text selection in IE + + if (EventClickHandling == UserActionHandling.PostBack) + { + output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + Page.ClientScript.GetPostBackEventReference(this, "PK:" + e.PK)); + } + else + { + output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + String.Format(EventClickJavaScript, e.PK)); + } + + output.AddStyleAttribute("-moz-user-select", "none"); // prevent text selection in FF + output.AddStyleAttribute("-khtml-user-select", "none"); // prevent text selection + output.AddStyleAttribute("user-select", "none"); // prevent text selection + output.AddStyleAttribute("cursor", "pointer"); + //output.AddStyleAttribute("cursor", "hand"); + output.AddStyleAttribute("position", "absolute"); + output.AddStyleAttribute("font-family", EventFontFamily); + output.AddStyleAttribute("font-size", EventFontSize); + output.AddStyleAttribute("white-space", "no-wrap"); + output.AddStyleAttribute("left", e.Column.StartsAtPct + "%"); + output.AddStyleAttribute("top", top + "px"); + output.AddStyleAttribute("width", e.Column.WidthPct + "%"); + output.AddStyleAttribute("height", (realBoxEnd - realBoxStart).TotalHours * HourHeight + "px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBorderColor)); + output.RenderBeginTag("div"); + //output.Write(divMain.BeginTag()); + + // FIX BOX - to fix the outer/inner box differences in Mozilla/IE (to create border) +// DivWriter divFix = new DivWriter(); + output.AddAttribute("onmouseover", "this.style.backgroundColor='" + ColorTranslator.ToHtml(EventHoverColor) + "';event.cancelBubble=true;"); + output.AddAttribute("onmouseout", "this.style.backgroundColor='" + ColorTranslator.ToHtml(EventBackColor) + "';event.cancelBubble=true;"); + + if (ShowToolTip) + { + output.AddAttribute("title", displayTextPopup); + } + + output.AddStyleAttribute("margin-top", "1px"); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("height", height + "px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBackColor)); + output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(EventBorderColor)); + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(EventBorderColor)); + output.AddStyleAttribute("overflow", "hidden"); + output.RenderBeginTag("div"); +// output.Write(divFix.BeginTag()); + + // blue column + if (e.Start > realBoxStart) + { + + } + + int startDelta = (int) Math.Floor((e.Start - realBoxStart).TotalHours * HourHeight); + int endDelta = (int) Math.Floor((realBoxEnd - e.End).TotalHours * HourHeight); + +// DivWriter divBlue = new DivWriter(); + output.AddStyleAttribute("float", "left"); + output.AddStyleAttribute("width", "5px"); + output.AddStyleAttribute("height", height - startDelta - endDelta + "px"); + output.AddStyleAttribute("margin-top", startDelta + "px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(DurationBarColor)); + output.AddStyleAttribute("font-size", "1px"); + output.RenderBeginTag("div"); + output.RenderEndTag(); +// output.Write(divBlue.BeginTag()); +// output.Write(divBlue.EndTag()); + + // right border of blue column +// DivWriter divBorder = new DivWriter(); + output.AddStyleAttribute("float", "left"); + output.AddStyleAttribute("width", "1px"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBorderColor)); + output.AddStyleAttribute("height", "100%"); + output.RenderBeginTag("div"); + output.RenderEndTag(); +// output.Write(divBorder.BeginTag()); +// output.Write(divBorder.EndTag()); + + // space +// DivWriter divSpace = new DivWriter(); + output.AddStyleAttribute("float", "left"); + output.AddStyleAttribute("width", "2px"); + output.AddStyleAttribute("height", "100%"); + output.RenderBeginTag("div"); + output.RenderEndTag(); +// output.Write(divSpace.BeginTag()); +// output.Write(divSpace.EndTag()); + + // PADDING BOX +// DivWriter divPadding = new DivWriter(); + output.AddStyleAttribute("padding", "1px"); + output.RenderBeginTag("div"); +// output.Write(divPadding.BeginTag()); + + output.Write(displayText); // e.BoxStart - dayVisibleStart + + // closing the PADDING BOX + output.RenderEndTag(); +// output.Write(divPadding.EndTag()); + + // closing the FIX BOX + output.RenderEndTag(); +// output.Write(divFix.EndTag()); + + // closing the MAIN BOX +// output.Write(divMain.EndTag()); + output.RenderEndTag(); + } + + private void addHalfHourCells(HtmlTextWriter output, DateTime hour, bool hourStartsHere, bool isLast) + { + foreach (Day d in days) + { + DateTime h = new DateTime(d.Start.Year, d.Start.Month, d.Start.Day, hour.Hour, 0, 0); + addHalfHourCell(output, h, hourStartsHere, isLast); + } + } + + private void addHalfHourCell(HtmlTextWriter output, DateTime hour, bool hourStartsHere, bool isLast) + { + string cellBgColor; + if (hour.Hour < BusinessBeginsHour || hour.Hour >= BusinessEndsHour || hour.DayOfWeek == DayOfWeek.Saturday || hour.DayOfWeek == DayOfWeek.Sunday) + cellBgColor = ColorTranslator.ToHtml(NonBusinessBackColor); + else + cellBgColor = ColorTranslator.ToHtml(BackColor); + + string borderBottomColor; + if (hourStartsHere) + borderBottomColor = ColorTranslator.ToHtml(HourHalfBorderColor); + else + borderBottomColor = ColorTranslator.ToHtml(HourBorderColor); + + DateTime startingTime = hour; + if (!hourStartsHere) + startingTime = hour.AddMinutes(30); + + if (FreetimeClickHandling == UserActionHandling.PostBack) + { + output.AddAttribute("onclick", "javascript:" + Page.ClientScript.GetPostBackEventReference(this, "TIME:" + startingTime.ToString("s"))); + } + else + { + output.AddAttribute("onclick", "javascript:" + String.Format(FreeTimeClickJavaScript, startingTime.ToString("s"))); + } + output.AddAttribute("onmouseover", "this.style.backgroundColor='" + ColorTranslator.ToHtml(HoverColor) + "';"); + output.AddAttribute("onmouseout", "this.style.backgroundColor='" + cellBgColor + "';"); + output.AddAttribute("valign", "bottom"); + output.AddStyleAttribute("background-color", cellBgColor); + output.AddStyleAttribute("cursor", "pointer"); + output.AddStyleAttribute("cursor", "hand"); + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("height", (HourHeight / 2) + "px"); + output.RenderBeginTag("td"); + + // FIX BOX - to fix the outer/inner box differences in Mozilla/IE (to create border) +// DivWriter divFix = new DivWriter(); + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("height", "14px"); + if (!isLast) + output.AddStyleAttribute("border-bottom", "1px solid " + borderBottomColor); + output.RenderBeginTag("div"); +// output.Write(divFix.BeginTag()); + + // required + output.Write(" "); + + // closing the FIX BOX + output.RenderEndTag(); +// output.Write(divFix.EndTag()); + + // + output.RenderEndTag(); + + } + + + #endregion + + #region Calculations + + + /// + /// This is only a relative time. The date part should be ignored. + /// + private DateTime visibleStart + { + get + { + DateTime date = new DateTime(1900, 1, 1); + + if (NonBusinessHours == NonBusinessHoursBehavior.Show) + return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0); + + DateTime start = new DateTime(date.Year, date.Month, date.Day, BusinessBeginsHour, 0, 0); + + if (NonBusinessHours == NonBusinessHoursBehavior.Hide) + return start; + + if (days == null) + return start; + + if (totalEvents == 0) + return start; + + foreach (Day d in days) + { + DateTime boxStart = new DateTime(date.Year, date.Month, date.Day, d.BoxStart.Hour, d.BoxStart.Minute, d.BoxStart.Second); + if (boxStart < start) + start = boxStart; + } + + return new DateTime(start.Year, start.Month, start.Day, start.Hour, 0, 0); + + + } + } + + /// + /// This is only a relative time. The date part should be ignored. + /// + private DateTime visibleEnd + { + get + { + DateTime date = new DateTime(1900, 1, 1); + + if (NonBusinessHours == NonBusinessHoursBehavior.Show) + return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddDays(1); + + DateTime end; + if (BusinessEndsHour == 24) + end = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).AddDays(1); + else + end = new DateTime(date.Year, date.Month, date.Day, BusinessEndsHour, 0, 0); + + if (NonBusinessHours == NonBusinessHoursBehavior.Hide) + return end; + + if (days == null) + return end; + + if (totalEvents == 0) + return end; + + foreach (Day d in days) + { + + bool addDay = false; + if (d.BoxEnd > DateTime.MinValue && d.BoxEnd.AddDays(-1) >= d.Start) + addDay = true; + + DateTime boxEnd = new DateTime(date.Year, date.Month, date.Day, d.BoxEnd.Hour, d.BoxEnd.Minute, d.BoxEnd.Second); + + if (addDay) + boxEnd = boxEnd.AddDays(1); + + if (boxEnd > end) + end = boxEnd; + } + + if (end.Minute != 0) + end = end.AddHours(1); + + return new DateTime(end.Year, end.Month, end.Day, end.Hour, 0, 0); + } + } + + + private int totalEvents + { + get + { + int ti = 0; + foreach (Day d in days) + ti += d.events.Count; + + return ti; + } + } + #endregion + + #region Data binding + + + protected override void PerformSelect() + { + // Call OnDataBinding here if bound to a data source using the + // DataSource property (instead of a DataSourceID), because the + // databinding statement is evaluated before the call to GetData. + if (!IsBoundUsingDataSourceID) + { + this.OnDataBinding(EventArgs.Empty); + } + + // The GetData method retrieves the DataSourceView object from + // the IDataSource associated with the data-bound control. + GetData().Select(CreateDataSourceSelectArguments(), + this.OnDataSourceViewSelectCallback); + + // The PerformDataBinding method has completed. + RequiresDataBinding = false; + MarkAsDataBound(); + + // Raise the DataBound event. + OnDataBound(EventArgs.Empty); + } + + private void OnDataSourceViewSelectCallback(IEnumerable retrievedData) + { + // Call OnDataBinding only if it has not already been + // called in the PerformSelect method. + if (IsBoundUsingDataSourceID) + { + OnDataBinding(EventArgs.Empty); + } + // The PerformDataBinding method binds the data in the + // retrievedData collection to elements of the data-bound control. + PerformDataBinding(retrievedData); + } + + protected override void PerformDataBinding(IEnumerable retrievedData) + { + // don't load events in design mode + if (DesignMode) + { + return; + } + + base.PerformDataBinding(retrievedData); + + if (DataStartField == null || DataStartField == String.Empty) + throw new NullReferenceException("DataStartField property must be specified."); + + if (DataEndField == null || DataEndField == String.Empty) + throw new NullReferenceException("DataEndField property must be specified."); + + if (DataTextField == null || DataTextField == String.Empty) + throw new NullReferenceException("DataTextField property must be specified."); + + if (DataValueField == null || DataValueField == String.Empty) + throw new NullReferenceException("DataValueField property must be specified."); + if (DataOwnerField == null || DataOwnerField == String.Empty) + throw new NullReferenceException("DataOwnerField property must be specified."); + + + // Verify data exists. + if (retrievedData != null) + { + items = new ArrayList(); + + foreach (object dataItem in retrievedData) + { + + DateTime start = Convert.ToDateTime(DataBinder.GetPropertyValue(dataItem, DataStartField, null)); + DateTime end = Convert.ToDateTime(DataBinder.GetPropertyValue(dataItem, DataEndField, null)); + string name = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataTextField, null)); + string pk = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataValueField, null)); + string own = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataOwnerField, null)); + + items.Add(new Event(pk, start, end, name, null, own)); + + } + + items.Sort(new EventComparer()); + +// loadEventsToDays(); + } + } + + private void loadEventsToDays() + { + + if (EndDate < StartDate) + throw new ArgumentException("EndDate must be equal to or greater than StartDate."); + + int dayCount = (int)(EndDate - StartDate).TotalDays + 1; + days = new Day[dayCount]; + + for (int i = 0; i < days.Length; i++) + { + days[i] = new Day(StartDate.AddDays(i)); + + if (items != null) + days[i].Load(items); + + } + } + + #endregion + + + } +} diff --git a/Web/Ui/DayPilotCalendarProperties.cs b/Web/Ui/DayPilotCalendarProperties.cs new file mode 100644 index 0000000..b0682ac --- /dev/null +++ b/Web/Ui/DayPilotCalendarProperties.cs @@ -0,0 +1,825 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Web.UI.WebControls; + +namespace DayPilot.Web.Ui +{ + public partial class DayPilotCalendar + { + + /// + /// Gets or sets the start of the business day (in hours). + /// + [Description("Start of the business day (hour from 0 to 23).")] + [Category("Appearance")] + [DefaultValue(9)] + public int BusinessBeginsHour + { + get + { + if (ViewState["BusinessBeginsHour"] == null) + return 9; + return (int)ViewState["BusinessBeginsHour"]; + } + set + { + if (value < 0) + ViewState["BusinessBeginsHour"] = 0; + else if (value > 23) + ViewState["BusinessBeginsHour"] = 23; + else + ViewState["BusinessBeginsHour"] = value; + } + } + + /// + /// Gets or sets the end of the business day (hours). + /// + [Description("End of the business day (hour from 1 to 24).")] + [Category("Appearance")] + [DefaultValue(18)] + public int BusinessEndsHour + { + get + { + if (ViewState["BusinessEndsHour"] == null) + return 18; + return (int)ViewState["BusinessEndsHour"]; + } + set + { + if (value < BusinessBeginsHour) + ViewState["BusinessEndsHour"] = BusinessBeginsHour + 1; + else if (value > 24) + ViewState["BusinessEndsHour"] = 24; + else + ViewState["BusinessEndsHour"] = value; + } + } + + /// + /// Gets or sets the height of the hour cell in pixels. Must be even. + /// + [Description("Height of the hour cell in pixels. Must be even.")] + [Category("Layout")] + [DefaultValue(40)] + public int HourHeight + { + get + { + if (ViewState["HourHeight"] == null) + return 40; + return (int)ViewState["HourHeight"]; + } + set + { + if (value % 2 == 0) + ViewState["HourHeight"] = value; + else + ViewState["HourHeight"] = value - 1; + } + } + + /// + /// Gets or sets the width of the hour cell in pixels. + /// + [Description("Width of the hour cell in pixels.")] + [Category("Layout")] + [DefaultValue(40)] + public int HourWidth + { + get + { + if (ViewState["HourWidth"] == null) + return 40; + return (int)ViewState["HourWidth"]; + } + set + { + ViewState["HourWidth"] = value; + } + } + + /// + /// Gets or sets the Javascript code that is executed when the users clicks on an event. '{0}' will be replaced by the primary key of the event. + /// + [Description("Javascript code that is executed when the users clicks on an event. '{0}' will be replaced by the primary key of the event.")] + [Category("User actions")] + [DefaultValue("alert('{0}');")] + public string EventClickJavaScript + { + get + { + if (ViewState["EventClickJavaScript"] == null) + return "alert('{0}');"; + return (string)ViewState["EventClickJavaScript"]; + } + set + { + ViewState["EventClickJavaScript"] = value; + } + } + + /// + /// Gets or sets the Javascript code that is executed when the users clicks on a free time slot. '{0}' will be replaced by the starting time of that slot (i.e. '9:00'. + /// + [Description("Javascript code that is executed when the users clicks on a free time slot. '{0}' will be replaced by the starting time of that slot (i.e. '9:00'.")] + [Category("User actions")] + [DefaultValue("alert('{0}');")] + public string FreeTimeClickJavaScript + { + get + { + if (ViewState["FreeTimeClickJavaScript"] == null) + return "alert('{0}');"; + return (string)ViewState["FreeTimeClickJavaScript"]; + } + set + { + ViewState["FreeTimeClickJavaScript"] = value; + } + } + + /// + /// Gets or sets the first day to be shown. Default is DateTime.Today. + /// + [Description("The first day to be shown. Default is DateTime.Today.")] + public DateTime StartDate + { + get + { + if (ViewState["StartDate"] == null) + { + return DateTime.Today; + } + + return (DateTime)ViewState["StartDate"]; + + } + set + { + ViewState["StartDate"] = new DateTime(value.Year, value.Month, value.Day); + } + } + + /// + /// Gets or sets the number of days to be displayed. Default is 1. + /// + [Description("The number of days to be displayed on the calendar. Default value is 1.")] + [DefaultValue(1)] + public int Days + { + get + { + if (ViewState["Days"] == null) + return 1; + return (int)ViewState["Days"]; + } + set + { + int daysCount = value; + + if (daysCount < 1) + daysCount = 1; + + ViewState["Days"] = daysCount; + } + } + + /// + /// Gets the last day to be shown. + /// + public DateTime EndDate + { + get + { + return StartDate.AddDays(Days - 1); + } + } + + /// + /// Gets or sets the name of the column that contains the event starting date and time (must be convertible to DateTime). + /// + [Description("The name of the column that contains the event starting date and time (must be convertible to DateTime).")] + [Category("Data")] + public string DataStartField + { + get + { + return dataStartField; + } + set + { + dataStartField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Gets or sets the name of the column that contains the event ending date and time (must be convertible to DateTime). + /// + [Description("The name of the column that contains the event ending date and time (must be convertible to DateTime).")] + [Category("Data")] + public string DataEndField + { + get + { + return dataEndField; + } + set + { + dataEndField = value; + if (Initialized) + { + OnDataPropertyChanged(); + } + } + } + + /// + /// Gets or sets the name of the column that contains the name of an event. + /// + [Category("Data")] + [Description("The name of the column that contains the name of an event.")] + public string DataTextField + { + get + { + return dataTextField; + } + set + { + dataTextField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Gets or sets the name of the column that contains the primary key. The primary key will be used for rendering the custom JavaScript actions. + /// + [Category("Data")] + [Description("The name of the column that contains the primary key. The primary key will be used for rendering the custom JavaScript actions.")] + public string DataValueField + { + get + { + return dataValueField; + } + set + { + dataValueField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + [Category("Data")] + [Description("The name of the owner field")] + public string DataOwnerField + { + get + { + return dataOwnerField; + } + set + { + dataOwnerField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + + /// + /// Gets or sets whether the hour numbers should be visible. + /// + [Category("Appearance")] + [Description("Should the hour numbers be visible?")] + [DefaultValue(true)] + public bool ShowHours + { + get + { + if (ViewState["ShowHours"] == null) + return true; + return (bool)ViewState["ShowHours"]; + } + set + { + ViewState["ShowHours"] = value; + } + } + + /// + /// Gets or sets the time-format for hour numbers (on the left). + /// + [Category("Appearance")] + [Description("The time-format that will be used for the hour numbers.")] + [DefaultValue(TimeFormat.Clock12Hours)] + public TimeFormat TimeFormat + { + get + { + if (ViewState["TimeFormat"] == null) + return TimeFormat.Clock12Hours; + return (TimeFormat)ViewState["TimeFormat"]; + } + set + { + ViewState["TimeFormat"] = value; + } + } + + /// + /// Gets or sets the drawing mode of non-business hours. + /// + [Category("Appearance")] + [Description("Determines whether the control shows the non-business hours.")] + [DefaultValue(NonBusinessHoursBehavior.HideIfPossible)] + public NonBusinessHoursBehavior NonBusinessHours + { + get + { + if (ViewState["NonBusinessHours"] == null) + return NonBusinessHoursBehavior.HideIfPossible; + return (NonBusinessHoursBehavior)ViewState["NonBusinessHours"]; + } + set + { + ViewState["NonBusinessHours"] = value; + } + } + + /// + /// Handling of user action (clicking an event). + /// + [Category("User actions")] + [Description("Whether clicking an event should do a postback or run a javascript action. By default, it calls the javascript code specified in EventClickJavaScript property.")] + [DefaultValue(UserActionHandling.JavaScript)] + public UserActionHandling EventClickHandling + { + get + { + if (ViewState["EventClickHandling"] == null) + return UserActionHandling.JavaScript; + return (UserActionHandling)ViewState["EventClickHandling"]; + } + set + { + ViewState["EventClickHandling"] = value; + } + } + + /// + /// Handling of user action (clicking a free-time slot). + /// + [Category("User actions")] + [Description("Whether clicking a free-time slot should do a postback or run a javascript action. By default, it calls the javascript code specified in FreeTimeClickJavaScript property.")] + [DefaultValue(UserActionHandling.JavaScript)] + public UserActionHandling FreetimeClickHandling + { + get + { + if (ViewState["FreeTimeClickHandling"] == null) + return UserActionHandling.JavaScript; + return (UserActionHandling)ViewState["FreeTimeClickHandling"]; + } + set + { + ViewState["FreeTimeClickHandling"] = value; + } + } + + //headerDateFormat + /// + /// Gets or sets the format of the date display in the header columns. + /// + [Description("Format of the date display in the header columns.")] + [Category("Appearance")] + [DefaultValue("d")] + public string HeaderDateFormat + { + get + { + return headerDateFormat; + } + set + { + headerDateFormat = value; + } + } + + /// + /// Gets or sets whether the header should be visible. + /// + [Category("Appearance")] + [Description("Should the header be visible?")] + [DefaultValue(true)] + public bool ShowHeader + { + get + { + return showHeader; + } + set + { + showHeader = value; + } + } + + + /// + /// Gets or sets whether the header should be visible. + /// + [Category("Layout")] + [Description("Header height in pixels.")] + [DefaultValue(21)] + public int HeaderHeight + { + get + { + return headerHeight; + } + set + { + headerHeight = value; + } + } + + public override Color BackColor + { + get + { + if (ViewState["BackColor"] == null) + return ColorTranslator.FromHtml("#FFFFD5"); + return (Color)ViewState["BackColor"]; + } + set + { + ViewState["BackColor"] = value; + } + } + + public override Color BorderColor + { + get + { + if (ViewState["BorderColor"] == null) + return ColorTranslator.FromHtml("#000000"); + return (Color)ViewState["BorderColor"]; + } + set + { + ViewState["BorderColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HoverColor + { + get + { + if (ViewState["HoverColor"] == null) + return ColorTranslator.FromHtml("#FFED95"); + return (Color)ViewState["HoverColor"]; + + } + set + { + ViewState["HoverColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HourBorderColor + { + get + { + if (ViewState["HourBorderColor"] == null) + return ColorTranslator.FromHtml("#EAD098"); + return (Color)ViewState["HourBorderColor"]; + + } + set + { + ViewState["HourBorderColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HourHalfBorderColor + { + get + { + if (ViewState["HourHalfBorderColor"] == null) + return ColorTranslator.FromHtml("#F3E4B1"); + return (Color)ViewState["HourHalfBorderColor"]; + + } + set + { + ViewState["HourHalfBorderColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HourNameBorderColor + { + get + { + if (ViewState["HourNameBorderColor"] == null) + return ColorTranslator.FromHtml("#ACA899"); + return (Color)ViewState["HourNameBorderColor"]; + } + set + { + ViewState["HourNameBorderColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HourNameBackColor + { + get + { + if (ViewState["HourNameBackColor"] == null) + return ColorTranslator.FromHtml("#ECE9D8"); + return (Color)ViewState["HourNameBackColor"]; + } + set + { + ViewState["HourNameBackColor"] = value; + } + } + + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color EventBackColor + { + get + { + if (ViewState["EventBackColor"] == null) + return ColorTranslator.FromHtml("#FFFFFF"); + return (Color)ViewState["EventBackColor"]; + } + set + { + ViewState["EventBackColor"] = value; + } + } + + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color EventHoverColor + { + get + { + if (ViewState["EventHoverColor"] == null) + return ColorTranslator.FromHtml("#DCDCDC"); + return (Color)ViewState["EventHoverColor"]; + } + set + { + ViewState["EventHoverColor"] = value; + } + } + + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color EventBorderColor + { + get + { + if (ViewState["EventBorderColor"] == null) + return ColorTranslator.FromHtml("#000000"); + return (Color)ViewState["EventBorderColor"]; + } + set + { + ViewState["EventBorderColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color DurationBarColor + { + get + { + if (ViewState["DurationBarColor"] == null) + return ColorTranslator.FromHtml("blue"); + return (Color)ViewState["DurationBarColor"]; + } + set + { + ViewState["DurationBarColor"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color NonBusinessBackColor + { + get + { + if (ViewState["NonBusinessBackColor"] == null) + return ColorTranslator.FromHtml("#FFF4BC"); + + return (Color)ViewState["NonBusinessBackColor"]; + } + set + { + ViewState["NonBusinessBackColor"] = value; + } + } + + [Category("Appearance")] + public string EventFontFamily + { + get + { + if (ViewState["EventFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["EventFontFamily"]; + } + set + { + ViewState["EventFontFamily"] = value; + } + } + + + [Category("Appearance")] + public string HourFontFamily + { + get + { + if (ViewState["HourFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["HourFontFamily"]; + } + set + { + ViewState["HourFontFamily"] = value; + } + } + + [Category("Appearance")] + public string DayFontFamily + { + get + { + if (ViewState["DayFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["DayFontFamily"]; + } + set + { + ViewState["DayFontFamily"] = value; + } + } + + [Category("Appearance")] + public string EventFontSize + { + get + { + if (ViewState["EventFontSize"] == null) + return "8pt"; + + return (string)ViewState["EventFontSize"]; + } + set + { + ViewState["EventFontSize"] = value; + } + } + + [Category("Appearance")] + public string HourFontSize + { + get + { + if (ViewState["HourFontSize"] == null) + return "16pt"; + + return (string)ViewState["HourFontSize"]; + } + set + { + ViewState["HourFontSize"] = value; + } + } + + [Category("Appearance")] + public string DayFontSize + { + get + { + if (ViewState["DayFontSize"] == null) + return "10pt"; + + return (string)ViewState["DayFontSize"]; + } + set + { + ViewState["DayFontSize"] = value; + } + } + + /// + /// Determines whether the event tooltip is active. + /// + [Description("Determines whether the event tooltip is active.")] + [Category("Appearance")] + [DefaultValue(true)] + public bool ShowToolTip + { + get + { + if (ViewState["ShowToolTip"] == null) + return true; + return (bool)ViewState["ShowToolTip"]; + } + set + { + ViewState["ShowToolTip"] = value; + } + } + + /// + /// Width of the right margin inside a column (in pixels). + /// + [Description("Width of the right margin inside a column (in pixels).")] + [Category("Appearance")] + [DefaultValue(5)] + public int ColumnMarginRight + { + get + { + if (ViewState["ColumnMarginRight"] == null) + return 5; + return (int)ViewState["ColumnMarginRight"]; + } + set + { + ViewState["ColumnMarginRight"] = value; + } + } + + + + } +} diff --git a/Web/Ui/DayPilotScheduler.cs b/Web/Ui/DayPilotScheduler.cs new file mode 100644 index 0000000..d81d584 --- /dev/null +++ b/Web/Ui/DayPilotScheduler.cs @@ -0,0 +1,1437 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Security.Permissions; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using DayPilot.Utils; + +namespace DayPilot.Web.Ui +{ + /// + /// Calendar/scheduler control with hours on the horizontal axis and resources on the vertical axis. + /// + /// + /// + [PersistChildren(false)] + [ParseChildren(true)] + [DefaultProperty(null)] + [ToolboxBitmap(typeof(Calendar))] + [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] + public class DayPilotScheduler : DataBoundControl, IPostBackEventHandler + { + internal List days; + + private string dataStartField; + private string dataEndField; + private string dataTextField; + private string dataValueField; + private string dataResourceField; + + + /// + /// Event called when the user clicks an event in the calendar. It's only called when EventClickHandling is set to PostBack. + /// + [Category("User actions")] + [Description("Event called when the user clicks an event in the calendar.")] + public event EventClickDelegate EventClick; + + /// + /// Event called when the user clicks a free space in the calendar. It's only called when FreeTimeClickHandling is set to PostBack. + /// + [Category("User actions")] + [Description("Event called when the user clicks a free space in the calendar.")] + public event FreeClickDelegate FreeTimeClick; + + + /// + /// Renders the component HTML code. + /// + /// + protected override void Render(HtmlTextWriter output) + { + loadEventsToDays(); + renderMainTable(output); + } + + + private void renderMainTable(HtmlTextWriter output) + { + output.AddAttribute("id", ClientID); + output.AddStyleAttribute("width", Width + "px"); + output.AddStyleAttribute("line-height", "1.2"); + output.RenderBeginTag("div"); + + output.AddAttribute("cellspacing", "0"); + output.AddAttribute("cellpadding", "0"); + output.AddAttribute("border", "0"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.RenderBeginTag("table"); + + output.RenderBeginTag("tr"); + output.AddStyleAttribute("width", (RowHeaderWidth) + "px"); + output.RenderBeginTag("td"); + renderCorner(output); + output.RenderEndTag(); // td + renderHeaderCols(output); + output.RenderEndTag(); // tr + + // SOUTH + renderRows(output); + + output.RenderEndTag(); // table + + output.RenderEndTag(); // main + } + + private void renderCells(HtmlTextWriter output, Day d) + { + int cellsToRender = cellCount; + + for (int i = 0; i < cellsToRender; i++) + { + DateTime start = d.Start.AddMinutes(i*CellDuration); + + int thisCellWidth = CellWidth; + if (i == 0) + { + thisCellWidth = CellWidth - 1; + } + string back = getCellColor(start, d.Value); + + if (i == cellsToRender - 1) + { + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + } + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("width", thisCellWidth + "px"); + output.AddStyleAttribute("background-color", back); + output.AddStyleAttribute("cursor", "pointer"); + + if (FreeTimeClickHandling == UserActionHandling.PostBack) + { + output.AddAttribute("onclick", "javascript:" + Page.ClientScript.GetPostBackEventReference(this, "TIME:" + start.ToString("s") + d.Value)); + } + else + { + output.AddAttribute("onclick", "javascript:" + String.Format(FreeTimeClickJavaScript, start.ToString("s"), d.Value)); + } + output.AddAttribute("onmouseover", "this.style.backgroundColor='" + ColorTranslator.ToHtml(HoverColor) + "';"); + output.AddAttribute("onmouseout", "this.style.backgroundColor='" + back + "';"); + + output.RenderBeginTag("td"); + + output.Write("
"); + output.RenderEndTag(); + + } + } + + private void renderEvents(Day d, HtmlTextWriter output) + { + if (d.events.Count == 0) + { + output.Write("
"); + } + else + { + output.AddStyleAttribute("position", "relative"); + output.AddStyleAttribute("height", (d.MaxColumns() * EventHeight - 1) + "px"); // + output.AddStyleAttribute("overflow", "none"); + output.AddAttribute("unselectable", "on"); + output.RenderBeginTag("div"); + + foreach (Event ep in d.events) + { + renderEvent(d, ep, output); + } + + // div relative + output.RenderEndTag(); + } + } + + + private void renderEvent(Day d, Event p, HtmlTextWriter output) + { + int max = cellCount*CellWidth; + + int left = (int)Math.Floor((p.BoxStart - d.Start).TotalMinutes * CellWidth / CellDuration); + int top = p.Column.Number * EventHeight - 1; + int width = (int)Math.Floor((p.BoxEnd - p.BoxStart).TotalMinutes * CellWidth / CellDuration) - 2; + int height = EventHeight - 1; + + int startDelta = (int)Math.Floor((p.Start - p.BoxStart).TotalMinutes * CellWidth / CellDuration - 1); + int realWidth = (int)Math.Floor((p.End - p.Start).TotalMinutes * CellWidth / CellDuration); + realWidth = realWidth == 0 ? 1 : realWidth; + + + // adjustments + if (left > max) // don't render + { + return; + } + if (left + width > max - 2) + { + width = max - left - 2; + } + if (left < 0) + { + width += left; + left = 0; + } + + width = Math.Max(width, 2); + output.AddAttribute("unselectable", "on"); + + output.AddStyleAttribute("position", "absolute"); + output.AddStyleAttribute("left", left + "px"); + output.AddStyleAttribute("top", top + "px"); + output.AddStyleAttribute("width", width + "px"); + output.AddStyleAttribute("height", height + "px"); + output.AddStyleAttribute("border", "1px solid " + ColorTranslator.ToHtml(EventBorderColor)); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(EventBackColor)); + output.AddStyleAttribute("white-space", "nowrap"); + output.AddStyleAttribute("overflow", "hidden"); + output.AddStyleAttribute("font-family", EventFontFamily); + output.AddStyleAttribute("font-size", EventFontSize); + output.AddStyleAttribute("cursor", "pointer"); + + if (EventClickHandling == UserActionHandling.PostBack) + { + output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + Page.ClientScript.GetPostBackEventReference(this, "PK:" + p.PK)); + } + else + { + output.AddAttribute("onclick", "javascript:event.cancelBubble=true;" + String.Format(EventClickJavaScript, p.PK)); + } + + output.RenderBeginTag("div"); + + if (DurationBarVisible) + { + output.Write("
"); + output.Write("
"); + } + + output.AddStyleAttribute("display", "block"); + output.AddStyleAttribute("padding-left", "1px"); + output.AddAttribute("unselectable", "on"); + output.RenderBeginTag("div"); + output.Write(p.Name); + output.RenderEndTag(); + output.RenderEndTag(); + } + + private void renderRows(HtmlTextWriter output) + { + foreach (Day d in days) + { + output.RenderBeginTag("tr"); + + renderRowHeader(output, d); + renderRowCells(output, d); + + output.RenderEndTag(); + + } + + } + + private void renderRowCells(HtmlTextWriter output, Day d) + { + // render all events in the first cell + output.AddStyleAttribute("width", "1px"); + output.AddStyleAttribute("border-bottom", "1px solid black"); + output.AddStyleAttribute("background-color", getCellColor(d.Start, d.Value)); + + output.AddAttribute("valign", "top"); + output.AddAttribute("unselectable", "on"); + output.RenderBeginTag("td"); + + renderEvents(d, output); + + // td + output.RenderEndTag(); + + renderCells(output, d); + } + + private void renderRowHeader(HtmlTextWriter output, Day d) + { + int height = (d.MaxColumns() * EventHeight - 1); + + output.AddStyleAttribute("width", (RowHeaderWidth - 1) + "px"); + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("font-family", HeaderFontFamily); + output.AddStyleAttribute("font-size", HeaderFontSize); + output.AddStyleAttribute("color", ColorTranslator.ToHtml(HeaderFontColor)); + output.AddStyleAttribute("cursor", "default"); + + output.AddAttribute("unselectable", "on"); + output.AddAttribute("resource", d.Value); + output.RenderBeginTag("td"); + + output.Write("
"); + output.Write(d.Name); + output.Write("
"); + + output.RenderEndTag(); + } + + private void renderCorner(HtmlTextWriter output) + { + + output.AddStyleAttribute("width", (RowHeaderWidth - 1) + "px"); + output.AddStyleAttribute("height", (HeaderHeight - 1) + "px"); + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-top", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-left", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("cursor", "default"); + output.AddAttribute("unselectable", "on"); + output.RenderBeginTag("div"); + + output.RenderEndTag(); // td + } + + internal void renderHeaderCols(HtmlTextWriter output) + { + for (int i = 0; i < cellCount; i++) + { + DateTime from = StartDate.AddMinutes(CellDuration * i); + //DateTime to = from.AddMinutes(CellDuration); + + string text; + + if (CellDuration < 60) // smaller than hour, use minutes + { + text = String.Format("{0:00}", from.Minute); + } + else if (CellDuration < 1440)// smaller than day, use hours + { + text = TimeFormatter.GetHour(from, TimeFormat, "{0} {1}"); + } + else // use days + { + text = from.Day.ToString(); + } + + if (i == 0) + { + output.AddAttribute("colspan", "2"); + } + if (i == cellCount - 1) + { + output.AddStyleAttribute("border-right", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + } + output.AddStyleAttribute("border-top", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("border-bottom", "1px solid " + ColorTranslator.ToHtml(BorderColor)); + output.AddStyleAttribute("width", (CellWidth) + "px"); + output.AddStyleAttribute("height", (HeaderHeight - 1) + "px"); + output.AddStyleAttribute("overflow", "hidden"); + output.AddStyleAttribute("text-align", "center"); + output.AddStyleAttribute("background-color", ColorTranslator.ToHtml(HourNameBackColor)); + output.AddStyleAttribute("font-family", HourFontFamily); + output.AddStyleAttribute("font-size", HourFontSize); + output.AddAttribute("unselectable", "on"); + output.AddStyleAttribute("-khtml-user-select", "none"); + output.AddStyleAttribute("-moz-user-select", "none"); + output.AddStyleAttribute("cursor", "default"); + output.RenderBeginTag("td"); + + output.Write("
"); + output.Write(text); + output.Write("
"); + output.RenderEndTag(); + } + } + + private void loadEventsToDays() + { + days = new List(); + ArrayList items = (ArrayList)ViewState["Items"]; + + if (Resources == null) + { + return; + } + + foreach (Resource resource in Resources) + { + Day d = new Day(StartDate, EndDate.AddDays(1), resource.Name, resource.Value, CellDuration); + days.Add(d); + } + + foreach (Day d in days) + { + d.Load(items); + } + + } + + + #region Properties + + + /// + /// Gets or sets the first day to be shown. Default is DateTime.Today. + /// + [Description("The first day to be shown. Default is DateTime.Today.")] + [Category("Behavior")] + public DateTime StartDate + { + get + { + if (ViewState["StartDate"] == null) + { + return DateTime.Today; + } + + return (DateTime)ViewState["StartDate"]; + + } + set + { + ViewState["StartDate"] = new DateTime(value.Year, value.Month, value.Day); + } + } + + + /// + /// Gets the last day to be shown. + /// + [Browsable(false)] + public DateTime EndDate + { + get + { + return StartDate.AddDays(Days - 1); + } + } + + + /// + /// Gets or sets the number of days to be displayed. Default is 1. + /// + [Description("The number of days to be displayed on the calendar. Default value is 1.")] + [Category("Behavior")] + [DefaultValue(1)] + public int Days + { + get + { + if (ViewState["Days"] == null) + return 1; + return (int)ViewState["Days"]; + } + set + { + int daysCount = value; + + if (daysCount < 1) + daysCount = 1; + + ViewState["Days"] = daysCount; + } + } + + /// + /// Cell size in minutes. + /// + [Description("Cell width in pixels.")] + [Category("Layout")] + [DefaultValue(20)] + public virtual int CellWidth + { + get + { + if (ViewState["CellWidth"] == null) + return 20; + return (int)ViewState["CellWidth"]; + } + set + { + ViewState["CellWidth"] = value; + } + } + + /// + /// Number of cells per hour horizontally. + /// + [Description("Cell length in minutes.")] + [Category("Layout")] + [DefaultValue(60)] + public int CellDuration + { + get + { + if (ViewState["CellDuration"] == null) + return 60; + return (int)ViewState["CellDuration"]; + } + set + { + ViewState["CellDuration"] = value; + } + } + + + + /// + /// Collection of rows (resources). + /// + [Category("Behavior")] + [PersistenceMode(PersistenceMode.InnerProperty)] + [Description("Collection of rows that will be used when ViewType property is set to ViewTypeEnum.Resources.")] + public ResourceCollection Resources + { + get + { + if (ViewState["Resources"] == null) + { + ResourceCollection rc = new ResourceCollection(); + rc.designMode = DesignMode; + + ViewState["Resources"] = rc; + } + return (ResourceCollection)ViewState["Resources"]; + } + } + + /// + /// Gets or sets the name of the column that contains the event starting date and time (must be convertible to DateTime). + /// + [Description("The name of the column that contains the event starting date and time (must be convertible to DateTime).")] + [Category("Data")] + public string DataStartField + { + get + { + return dataStartField; + } + set + { + dataStartField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Gets or sets the name of the column that contains the event ending date and time (must be convertible to DateTime). + /// + [Description("The name of the column that contains the event ending date and time (must be convertible to DateTime).")] + [Category("Data")] + public string DataEndField + { + get + { + return dataEndField; + } + set + { + dataEndField = value; + if (Initialized) + { + OnDataPropertyChanged(); + } + } + } + + /// + /// Gets or sets the name of the column that contains the name of an event. + /// + [Category("Data")] + [Description("The name of the column that contains the name of an event.")] + public string DataTextField + { + get + { + return dataTextField; + } + set + { + dataTextField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Gets or sets the name of the column that contains the primary key. The primary key will be used for rendering the custom JavaScript actions. + /// + [Category("Data")] + [Description("The name of the column that contains the primary key. The primary key will be used for rendering the custom JavaScript actions.")] + public string DataValueField + { + get + { + return dataValueField; + } + set + { + dataValueField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Gets or sets the name of the column that contains the primary key. The primary key will be used for rendering the custom JavaScript actions. + /// + [Category("Data")] + [Description("The name of the column that contains the column id.")] + public string DataResourceField + { + get + { + return dataResourceField; + } + set + { + dataResourceField = value; + + if (Initialized) + { + OnDataPropertyChanged(); + } + + } + } + + /// + /// Color of the hour names background. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of the hour names background.")] + public Color HourNameBackColor + { + get + { + if (ViewState["HourNameBackColor"] == null) + return ColorTranslator.FromHtml("#ECE9D8"); + return (Color)ViewState["HourNameBackColor"]; + } + set + { + ViewState["HourNameBackColor"] = value; + } + } + + /// + /// Color of the horizontal border that separates our names. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of the horizontal border that separates our names.")] + public Color HourNameBorderColor + { + get + { + if (ViewState["HourNameBorderColor"] == null) + return ColorTranslator.FromHtml("#ACA899"); + return (Color)ViewState["HourNameBorderColor"]; + } + set + { + ViewState["HourNameBorderColor"] = value; + } + } + + + + /// + /// Color of an event border. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of an event border.")] + public Color EventBorderColor + { + get + { + if (ViewState["EventBorderColor"] == null) + return ColorTranslator.FromHtml("#000000"); + return (Color)ViewState["EventBorderColor"]; + } + set + { + ViewState["EventBorderColor"] = value; + } + } + + /// + /// Color of an event background. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of an event background.")] + public Color EventBackColor + { + get + { + if (ViewState["EventBackColor"] == null) + return ColorTranslator.FromHtml("#FFFFFF"); + return (Color)ViewState["EventBackColor"]; + } + set + { + ViewState["EventBackColor"] = value; + } + } + + + /// + ///Gets or sets the background color of the Web server control. + /// + /// + /// + ///A that represents the background color of the control. The default is , which indicates that this property is not set. + /// + /// + public override Color BackColor + { + get + { + if (ViewState["BackColor"] == null) + return ColorTranslator.FromHtml("#FFFFD5"); + return (Color)ViewState["BackColor"]; + } + set + { + ViewState["BackColor"] = value; + } + } + + + /// + /// Gets or sets the start of the business day (in hours). + /// + [Description("Start of the business day (hour from 0 to 23).")] + [Category("Behavior")] + [DefaultValue(9)] + public int BusinessBeginsHour + { + get + { + if (ViewState["BusinessBeginsHour"] == null) + return 9; + return (int)ViewState["BusinessBeginsHour"]; + } + set + { + if (value < 0) + ViewState["BusinessBeginsHour"] = 0; + else if (value > 23) + ViewState["BusinessBeginsHour"] = 23; + else + ViewState["BusinessBeginsHour"] = value; + } + } + + + /// + /// Gets or sets the end of the business day (hours). + /// + [Description("End of the business day (hour from 1 to 24).")] + [Category("Behavior")] + [DefaultValue(18)] + public int BusinessEndsHour + { + get + { + if (ViewState["BusinessEndsHour"] == null) + return 18; + return (int)ViewState["BusinessEndsHour"]; + } + set + { + if (value < BusinessBeginsHour) + ViewState["BusinessEndsHour"] = BusinessBeginsHour + 1; + else if (value > 24) + ViewState["BusinessEndsHour"] = 24; + else + ViewState["BusinessEndsHour"] = value; + } + } + + /// + /// Font family of the row header, e.g. "Tahoma". + /// + [Description("Font family of the event text, e.g. \"Tahoma\".")] + [Category("Appearance")] + [DefaultValue("Tahoma")] + public string HeaderFontFamily + { + get + { + if (ViewState["HeaderFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["HeaderFontFamily"]; + } + set + { + ViewState["HeaderFontFamily"] = value; + } + } + + /// + /// Color of the column header font. + /// + [Description("Color of the column header font.")] + [Category("Appearance")] + public Color HeaderFontColor + { + get + { + if (ViewState["HeaderFontColor"] == null) + return ColorTranslator.FromHtml("#000000"); + + return (Color)ViewState["HeaderFontColor"]; + } + set + { + ViewState["HeaderFontColor"] = value; + } + } + + /// + /// Font size of the row header, e.g. "10pt". + /// + [Description("Font size of the row header, e.g. \"10pt\".")] + [Category("Appearance")] + [DefaultValue("10pt")] + public string HeaderFontSize + { + get + { + if (ViewState["HeaderFontSize"] == null) + return "10pt"; + + return (string)ViewState["HeaderFontSize"]; + } + set + { + ViewState["HeaderFontSize"] = value; + } + } + + + /// + /// Font family of the time axis headers, e.g. "Tahoma". + /// + [Category("Appearance")] + [Description("Font family of the hour names (horizontal axis), e.g. \"Tahoma\".")] + [DefaultValue("Tahoma")] + public string HourFontFamily + { + get + { + if (ViewState["HourFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["HourFontFamily"]; + } + set + { + ViewState["HourFontFamily"] = value; + } + } + + /// + /// Font size of the time axis header e.g. "16pt". + /// + [Description("Font size of the hour names (horizontal axis), e.g. \"10pt\".")] + [Category("Appearance")] + [DefaultValue("10pt")] + public string HourFontSize + { + get + { + if (ViewState["HourFontSize"] == null) + return "10pt"; + + return (string)ViewState["HourFontSize"]; + } + set + { + ViewState["HourFontSize"] = value; + } + } + + /// + /// Font family of the event text, e.g. "Tahoma". + /// + [Category("Appearance")] + [DefaultValue("Tahoma")] + [Description("Font family of the event text, e.g. \"Tahoma\".")] + public string EventFontFamily + { + get + { + if (ViewState["EventFontFamily"] == null) + return "Tahoma"; + + return (string)ViewState["EventFontFamily"]; + } + set + { + ViewState["EventFontFamily"] = value; + } + } + + /// + /// Font size of the event text, e.g. "8pt". + /// + [Category("Appearance")] + [DefaultValue("7pt")] + [Description("Font size of the event text, e.g. \"7pt\".")] + public string EventFontSize + { + get + { + if (ViewState["EventFontSize"] == null) + return "7pt"; + + return (string)ViewState["EventFontSize"]; + } + set + { + ViewState["EventFontSize"] = value; + } + } + + /// + /// Height of the event cell in pixels. + /// + [Category("Appearance")] + [DefaultValue("17")] + [Description("Height of the event cell in pixels.")] + public int EventHeight + { + get + { + if (ViewState["EventHeight"] == null) + return 17; + + return (int)ViewState["EventHeight"]; + } + set + { + ViewState["EventHeight"] = value; + } + } + + /// + /// Height of the header cells (with hour names) in pixels. + /// + [Category("Appearance")] + [DefaultValue("17")] + [Description("Height of the header cells (with hour names) in pixels.")] + public int HeaderHeight + { + get + { + if (ViewState["HeaderHeight"] == null) + return 17; + + return (int)ViewState["HeaderHeight"]; + } + set + { + ViewState["HeaderHeight"] = value; + } + } + + /// + /// Background color of time cells outside of the busines hours. + /// + [Category("Appearance")] + [DefaultValue("#FFF4BC")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Background color of time cells outside of the busines hours.")] + public Color NonBusinessBackColor + { + get + { + if (ViewState["NonBusinessBackColor"] == null) + return ColorTranslator.FromHtml("#FFF4BC"); + + return (Color)ViewState["NonBusinessBackColor"]; + } + set + { + ViewState["NonBusinessBackColor"] = value; + } + } + + /// + /// Color of the horizontal border that separates hour names. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of the vertical border that separates hour names.")] + public Color HourBorderColor + { + get + { + if (ViewState["HourBorderColor"] == null) + return ColorTranslator.FromHtml("#EAD098"); + return (Color)ViewState["HourBorderColor"]; + + } + set + { + ViewState["HourBorderColor"] = value; + } + } + + /// + ///Gets or sets the border color of the Web control. + /// + /// + /// + ///A that represents the border color of the control. The default is , which indicates that this property is not set. + /// + public override Color BorderColor + { + get + { + if (ViewState["BorderColor"] == null) + return ColorTranslator.FromHtml("#000000"); + return (Color)ViewState["BorderColor"]; + } + set + { + ViewState["BorderColor"] = value; + } + } + + + /// + /// Color of the horizontal bar on the top of an event. + /// + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + [Description("Color of the horizontal bar on the top of an event.")] + public Color DurationBarColor + { + get + { + if (ViewState["DurationBarColor"] == null) + return ColorTranslator.FromHtml("blue"); + return (Color)ViewState["DurationBarColor"]; + } + set + { + ViewState["DurationBarColor"] = value; + } + } + + + /// + /// Gets or sets the time-format for hour numbers (on the top). + /// + [Category("Appearance")] + [Description("The time-format that will be used for the hour numbers.")] + [DefaultValue(TimeFormat.Clock12Hours)] + public TimeFormat TimeFormat + { + get + { + if (ViewState["TimeFormat"] == null) + return TimeFormat.Clock12Hours; + return (TimeFormat)ViewState["TimeFormat"]; + } + set + { + ViewState["TimeFormat"] = value; + } + } + + + /// + /// Width of the control (pixels and percentage values supported). + /// + [Description("Width of the control (pixels and percentage values supported).")] + public new int Width + { + get + { + return RowHeaderWidth + cellCount * CellWidth; + } + } + + + /// + /// Width of the row header (resource names) in pixels. + /// + [Description("Width of the row header (resource names) in pixels.")] + [Category("Appearance")] + [DefaultValue(80)] + public int RowHeaderWidth + { + get + { + if (ViewState["RowHeaderWidth"] == null) + return 80; + return (int)ViewState["RowHeaderWidth"]; + } + set + { + ViewState["RowHeaderWidth"] = value; + } + } + + /// + /// Whether the color bar on the left side of and event should be visible. + /// + [Category("Appearance")] + [DefaultValue(true)] + [Description("Whether the duration bar on the top of and event should be visible.")] + public bool DurationBarVisible + { + get + { + if (ViewState["DurationBarVisible"] == null) + return true; + return (bool)ViewState["DurationBarVisible"]; + } + set + { + ViewState["DurationBarVisible"] = value; + } + } + + /// + /// Handling of user action (clicking an event). + /// + [Category("User actions")] + [Description("Whether clicking an event should do a postback or run a javascript action. By default, it calls the javascript code specified in EventClickJavaScript property.")] + [DefaultValue(UserActionHandling.JavaScript)] + public UserActionHandling EventClickHandling + { + get + { + if (ViewState["EventClickHandling"] == null) + return UserActionHandling.JavaScript; + return (UserActionHandling)ViewState["EventClickHandling"]; + } + set + { + ViewState["EventClickHandling"] = value; + } + } + + /// + /// Gets or sets the Javascript code that is executed when the users clicks on an event. '{0}' will be replaced by the primary key of the event. + /// + [Description("Javascript code that is executed when the users clicks on an event. '{0}' will be replaced by the primary key of the event.")] + [Category("User actions")] + [DefaultValue("alert('{0}');")] + public string EventClickJavaScript + { + get + { + if (ViewState["EventClickJavaScript"] == null) + return "alert('{0}');"; + return (string)ViewState["EventClickJavaScript"]; + } + set + { + ViewState["EventClickJavaScript"] = value; + } + } + + /// + /// Handling of user action (clicking a free-time slot). + /// + [Category("User actions")] + [Description("Whether clicking a free-time slot should do a postback or run a javascript action. By default, it calls the javascript code specified in FreeTimeClickJavaScript property.")] + [DefaultValue(UserActionHandling.JavaScript)] + public UserActionHandling FreeTimeClickHandling + { + get + { + if (ViewState["FreeTimeClickHandling"] == null) + return UserActionHandling.JavaScript; + return (UserActionHandling)ViewState["FreeTimeClickHandling"]; + } + set + { + ViewState["FreeTimeClickHandling"] = value; + } + } + + /// + /// Gets or sets the Javascript code that is executed when the users clicks on a free time slot. '{0}' will be replaced by the starting time of that slot (i.e. '9:00'. + /// + [Description("Javascript code that is executed when the users clicks on a free time slot. '{0}' will be replaced by the starting time of that slot (i.e. '9:00'.")] + [Category("User actions")] + [DefaultValue("alert('{0}, {1}');")] + public string FreeTimeClickJavaScript + { + get + { + if (ViewState["FreeTimeClickJavaScript"] == null) + return "alert('{0}, {1}');"; + return (string)ViewState["FreeTimeClickJavaScript"]; + } + set + { + ViewState["FreeTimeClickJavaScript"] = value; + } + } + + [Category("Appearance")] + [TypeConverter(typeof(WebColorConverter))] + public Color HoverColor + { + get + { + if (ViewState["HoverColor"] == null) + return ColorTranslator.FromHtml("#FFED95"); + return (Color)ViewState["HoverColor"]; + + } + set + { + ViewState["HoverColor"] = value; + } + } + + + #endregion + + #region Data binding + + /// + ///Retrieves data from the associated data source. + /// + /// + protected override void PerformSelect() + { + if (!IsBoundUsingDataSourceID) + { + this.OnDataBinding(EventArgs.Empty); + } + + GetData().Select(CreateDataSourceSelectArguments(), this.OnDataSourceViewSelectCallback); + + RequiresDataBinding = false; + MarkAsDataBound(); + + OnDataBound(EventArgs.Empty); + } + + private void OnDataSourceViewSelectCallback(IEnumerable retrievedData) + { + if (IsBoundUsingDataSourceID) + { + OnDataBinding(EventArgs.Empty); + } + PerformDataBinding(retrievedData); + } + + + /// + ///Binds data from the data source to the control. + /// + /// + ///The list of data returned from a method call. + protected override void PerformDataBinding(IEnumerable retrievedData) + { + ViewState["Items"] = new ArrayList(); + + // don't load events in design mode + if (DesignMode) + { + return; + } + + base.PerformDataBinding(retrievedData); + + + // Verify data exists. + if (retrievedData == null) + { + return; + } + + if (String.IsNullOrEmpty(DataStartField)) + { + throw new NullReferenceException("DataStartField property must be specified."); + } + + if (String.IsNullOrEmpty(DataEndField)) + { + throw new NullReferenceException("DataEndField property must be specified."); + } + + if (String.IsNullOrEmpty(DataTextField)) + { + throw new NullReferenceException("DataTextField property must be specified."); + } + + if (String.IsNullOrEmpty(DataValueField)) + { + throw new NullReferenceException("DataValueField property must be specified."); + } + + if (String.IsNullOrEmpty(DataResourceField)) + { + throw new NullReferenceException("DataResourceField property must be specified."); + } + + foreach (object dataItem in retrievedData) + { + + DateTime start; + DateTime end; + + string strStart = DataBinder.GetPropertyValue(dataItem, DataStartField, null); + if (!DateTime.TryParse(strStart, out start)) + { + throw new FormatException(String.Format("Unable to convert '{0}' (from DataStartField column) to DateTime.", strStart)); + } + + string strEnd = DataBinder.GetPropertyValue(dataItem, DataEndField, null); + if (!DateTime.TryParse(strEnd, out end)) + { + throw new FormatException(String.Format("Unable to convert '{0}' (from DataEndField column) to DateTime.", strEnd)); + } + + string name = DataBinder.GetPropertyValue(dataItem, DataTextField, null); + string val = DataBinder.GetPropertyValue(dataItem, DataValueField, null); + + string resourceId = Convert.ToString(DataBinder.GetPropertyValue(dataItem, DataResourceField, null)); + + ((ArrayList)ViewState["Items"]).Add(new Event(val, start, end, name, resourceId)); + + } + + ((ArrayList)ViewState["Items"]).Sort(new EventComparer()); + + } + #endregion + + + private int cellCount + { + get + { + return Days * 24 * 60 / CellDuration; + } + } + + internal string getCellColor(DateTime from, string resourceId) + { + bool isBusiness = isBusinessCell(from); + + if (isBusiness) + { + return ColorTranslator.ToHtml(BackColor); + } + else + { + return ColorTranslator.ToHtml(NonBusinessBackColor); + } + } + + private bool isBusinessCell(DateTime from) + { + if (from.DayOfWeek == DayOfWeek.Saturday || from.DayOfWeek == DayOfWeek.Sunday) + { + return false; + } + else + { + if (CellDuration < 720) // use hours + { + if (from.Hour < BusinessBeginsHour || from.Hour >= BusinessEndsHour) + { + return false; + } + else + { + return true; + } + } + else // use days + { + return true; + } + } + } + + /// + ///When implemented by a class, enables a server control to process an event raised when a form is posted to the server. + /// + /// + ///A that represents an optional event argument to be passed to the event handler. + public void RaisePostBackEvent(string eventArgument) + { + if (eventArgument.StartsWith("PK:")) + { + string pk = eventArgument.Substring(3, eventArgument.Length - 3); + if (EventClick != null) + EventClick(this, new EventClickEventArgs(pk)); + } + else if (eventArgument.StartsWith("TIME:")) + { + DateTime time = Convert.ToDateTime(eventArgument.Substring(5, 19)); + string resource = eventArgument.Substring(24); + if (FreeTimeClick != null) + FreeTimeClick(this, new FreeClickEventArgs(time, resource)); + } + else + { + throw new ArgumentException("Bad argument passed from postback event."); + } + + } + } +} diff --git a/Web/Ui/Design/DayPilotCalendarDesigner.cs b/Web/Ui/Design/DayPilotCalendarDesigner.cs new file mode 100644 index 0000000..8a496a6 --- /dev/null +++ b/Web/Ui/Design/DayPilotCalendarDesigner.cs @@ -0,0 +1,44 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + + +using System.Collections; +using System.Web.UI.Design.WebControls; + +namespace DayPilot.Web.Ui.Design +{ + public class DayPilotCalendarDesigner : DataBoundControlDesigner + { + protected override void PreFilterProperties(IDictionary properties) + { + base.PreFilterProperties(properties); + + properties.Remove("Height"); + properties.Remove("BorderStyle"); + properties.Remove("BorderWidth"); + properties.Remove("CssClass"); + properties.Remove("Font"); + properties.Remove("ForeColor"); + properties.Remove("ToolTip"); + properties.Remove("EndDate"); + } + } +} diff --git a/Web/Ui/Enums/GroupByEnum.cs b/Web/Ui/Enums/GroupByEnum.cs new file mode 100644 index 0000000..032dda4 --- /dev/null +++ b/Web/Ui/Enums/GroupByEnum.cs @@ -0,0 +1,55 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +namespace DayPilot.Web.Ui.Enums +{ + + /// + /// Header grouping units. + /// + public enum GroupByEnum + { + /// + /// Grouped by hour. + /// + Hour, + + /// + /// Grouped by day. + /// + Day, + + /// + /// Grouped by week. + /// + Week, + + /// + /// Grouped by month. + /// + Month, + + /// + /// No grouping. + /// + None + } +} diff --git a/Web/Ui/Event.cs b/Web/Ui/Event.cs new file mode 100644 index 0000000..3f12a3d --- /dev/null +++ b/Web/Ui/Event.cs @@ -0,0 +1,142 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; + +namespace DayPilot.Web.Ui +{ + /// + /// Summary description for Event. + /// + [Serializable] + public class Event + { + /// + /// Event start. + /// + public DateTime Start; + + /// + /// Event end; + /// + public DateTime End; + + /// + /// Event name; + /// + public string Name; + + /// + /// Event primary key. + /// + public string PK; + + public string Resource; + public string Owner; + + /// + /// Column to which this event belongs. + /// + [NonSerialized] + public Column Column; + + /// + /// Constructor. + /// + public Event() + { + } + + /// + /// Constructor that prefills the fields. + /// + /// + /// + /// + /// + public Event(string pk, DateTime start, DateTime end, string name) : this(pk, start, end, name, null) + { + + } + + public Event(string pk, DateTime start, DateTime end, string name, string resource): this(pk, start, end, name, resource, null) + { + + } + public Event(string pk, DateTime start, DateTime end, string name, string resource, string owner) + { + this.PK = pk; + this.Start = start; + this.End = end; + this.Name = name; + this.Resource = resource; + this.Owner = owner; + } + + /// + /// Gets the starting time of an event box. + /// + public DateTime BoxStart + { + get + { + if (Start.Minute >= 30) + return new DateTime(Start.Year, Start.Month, Start.Day, Start.Hour, 30, 0); + else + return new DateTime(Start.Year, Start.Month, Start.Day, Start.Hour, 0, 0); + } + } + + /// + /// Gets the ending time of an event box. + /// + public DateTime BoxEnd + { + get + { + if (End.Minute > 30) + { + DateTime hourPlus = End.AddHours(1); + return new DateTime(hourPlus.Year, hourPlus.Month, hourPlus.Day, hourPlus.Hour, 0, 0); + } + else if (End.Minute > 0) + { + return new DateTime(End.Year, End.Month, End.Day, End.Hour, 30, 0); + } + else + { + return new DateTime(End.Year, End.Month, End.Day, End.Hour, 0, 0); + } + } + } + + /// + /// Returns true if this box overlaps with e's box. + /// + /// + /// + public bool OverlapsWith(Event e) + { + return (this.BoxStart < e.BoxEnd && this.BoxEnd > e.Start); + } + + } +} diff --git a/Web/Ui/EventComparer.cs b/Web/Ui/EventComparer.cs new file mode 100644 index 0000000..67ab73e --- /dev/null +++ b/Web/Ui/EventComparer.cs @@ -0,0 +1,52 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System.Collections; + +namespace DayPilot.Web.Ui +{ + public class EventComparer : IComparer + { + + // Calls CaseInsensitiveComparer.Compare with the parameters reversed. + public int Compare(object x, object y) + { + Event first = (Event) x; + Event second = (Event) y; + + if (first.Start < second.Start) + { + return -1; + } + + if (first.Start > second.Start) + { + return 1; + } + + if (first.End > second.End) + return -1; + + return 0; + } + + } +} diff --git a/Web/Ui/EventDelegates.cs b/Web/Ui/EventDelegates.cs new file mode 100644 index 0000000..0da7e8e --- /dev/null +++ b/Web/Ui/EventDelegates.cs @@ -0,0 +1,80 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; + +namespace DayPilot.Web.Ui +{ + /// + /// Delegate for passing an event primary key. + /// + public delegate void EventClickDelegate(object sender, EventClickEventArgs e); + + /// + /// Delegate for passing a starting time. + /// + public delegate void FreeClickDelegate(object sender, FreeClickEventArgs e); + + + public class EventClickEventArgs : EventArgs + { + private string value; + + public string Value + { + get { return value; } + } + + public EventClickEventArgs(string value) + { + this.value = value; + } + } + + public class FreeClickEventArgs : EventArgs + { + private DateTime start; + private string resource; + + + public DateTime Start + { + get { return start; } + } + + public string Resource + { + get { return resource; } + } + + public FreeClickEventArgs(DateTime start) + { + this.start = start; + } + + public FreeClickEventArgs(DateTime start, string resource) + { + this.start = start; + this.resource = resource; + } + } + +} diff --git a/Web/Ui/NonBusinessHoursBehavior.cs b/Web/Ui/NonBusinessHoursBehavior.cs new file mode 100644 index 0000000..93e7c22 --- /dev/null +++ b/Web/Ui/NonBusinessHoursBehavior.cs @@ -0,0 +1,45 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +namespace DayPilot.Web.Ui +{ + /// + /// Behavior of the non-business hours. + /// + public enum NonBusinessHoursBehavior + { + /// + /// Hides the non-business hours if there is no event in that time. + /// + HideIfPossible, + + + /// + /// Always hides the non-business hours. + /// + Hide, + + /// + /// Always shows the non-business hours. + /// + Show + } +} diff --git a/Web/Ui/Resource.cs b/Web/Ui/Resource.cs new file mode 100644 index 0000000..15abe06 --- /dev/null +++ b/Web/Ui/Resource.cs @@ -0,0 +1,87 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; + +namespace DayPilot.Web.Ui +{ + /// + /// Class representing a resource DayPilotScheduler. + /// + [Serializable] + public class Resource + { + private string val; + private string name; + + + /// + /// Default constructor. + /// + public Resource() + { + } + + /// + /// Constructor that sets the default values. + /// + /// Row name (visible). + /// Row value (id). + public Resource(string name, string val) + { + this.name = name; + this.val = val; + } + + /// + /// Row value (id). + /// + public string Value + { + get { return val; } + set { val = value; } + } + + /// + /// Get or set the row name (Row.Name). + /// + public string Name + { + get { return name; } + set { name = value; } + } + + + /// + ///Returns a that represents the current . + /// + /// + /// + ///A that represents the current . + /// + ///2 + public override string ToString() + { + return Name; + } + } + +} diff --git a/Web/Ui/ResourceCollection.cs b/Web/Ui/ResourceCollection.cs new file mode 100644 index 0000000..69d2631 --- /dev/null +++ b/Web/Ui/ResourceCollection.cs @@ -0,0 +1,155 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System.Collections; +using System.ComponentModel; +using DayPilot.Web.Ui.Serialization; + +namespace DayPilot.Web.Ui +{ + /// + /// Collection of resources definitions. + /// + + [TypeConverter(typeof(ResourceCollectionConverter))] + public class ResourceCollection : CollectionBase + { + internal bool designMode; + + /// + /// Gets the specified Resource. + /// + /// Item index + /// Resource at the specified position. + public Resource this[int index] + { + get + { + return ((Resource)List[index]); + } + set + { + List[index] = value; + } + } + + /// + /// Converts ResourceCollection to ArrayList. + /// + /// ArrayList with ResourceCollection items. + public ArrayList ToArrayList() + { + ArrayList retArray = new ArrayList(); + for (int i = 0; i < this.Count; i++) + { + retArray.Add(this[i]); + } + + return retArray; + } + + /// + /// Adds a new Resource to the collection. + /// + /// Resource to be added. + /// + public int Add(Resource value) + { + return (List.Add(value)); + } + + /// + /// Adds a new Resource to the collection. + /// + /// Resource name + /// Resource id + /// + public int Add(string name, string id) + { + return Add(new Resource(name, id)); + } + + /// + /// Determines the index of a specific item in the collection. + /// + /// + /// + public int IndexOf(Resource value) + { + return (List.IndexOf(value)); + } + + /// + /// Inserts a new resource at the specified position. + /// + /// New resource position. + /// Resource to be added. + public void Insert(int index, Resource value) + { + List.Insert(index, value); + } + + /// + /// Removes a Resource from the collection. + /// + /// Resource to be removed. + public void Remove(Resource value) + { + List.Remove(value); + } + + + /// + /// Determines whether the collection contains a specified resource. + /// + /// Resource to be found. + /// True if the collection contains the resource + public bool Contains(Resource value) + { + return (List.Contains(value)); + } + + + /// + /// Creates a new collection from an ArrayList. + /// + /// ArrayList that contains the new resources. + public ResourceCollection(ArrayList items) + : base() + { + for (int i = 0; i < items.Count; i++) + { + if (items[i] is Resource) + { + this.Add((Resource)items[i]); + } + } + } + + /// + /// Creates a new ResourceCollection. + /// + public ResourceCollection() + : base() + { } + } + +} diff --git a/Web/Ui/Serialization/ResourceCollectionConverter.cs b/Web/Ui/Serialization/ResourceCollectionConverter.cs new file mode 100644 index 0000000..a57d8fe --- /dev/null +++ b/Web/Ui/Serialization/ResourceCollectionConverter.cs @@ -0,0 +1,136 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +using System; +using System.Collections; +using System.ComponentModel; +using Encoder=DayPilot.Utils.Encoder; + +namespace DayPilot.Web.Ui.Serialization +{ + /// + /// Internal class for serializing ResourceCollection (ViewState). + /// + public class ResourceCollectionConverter : TypeConverter + { + /// + /// + /// + /// + /// + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(String)) + return true; + return base.CanConvertFrom(context, sourceType); + } + + /// + /// + /// + /// + /// + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(String)) + return true; + return base.CanConvertTo(context, destinationType); + } + + /// + /// + /// + /// + /// + /// + /// + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + String state = value as String; + if (state == null) + { + return base.ConvertFrom(context, culture, value); + } + + if (state == String.Empty) + { + return new ResourceCollection(); + } + + String[] parts = state.Split('&'); + + ResourceCollection collection = new ResourceCollection(); + foreach (string encRes in parts) + { + string[] props = Encoder.UrlDecode(encRes).Split('&'); + + Resource r = new Resource(); + r.Name = Encoder.UrlDecode(props[0]); + r.Value = Encoder.UrlDecode(props[1]); + + collection.Add(r); + } + + return collection; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + if (destinationType == null) + throw new ArgumentException("destinationType"); + ResourceCollection collection = value as ResourceCollection; + + if (collection == null) + { + return base.ConvertTo(context, culture, value, destinationType); + + } + + if (collection.designMode) + { + return "(Collection)"; + } + + ArrayList al = new ArrayList(); + + foreach (Resource r in collection) + { + ArrayList properties = new ArrayList(); + properties.Add(r.Name); + properties.Add(r.Value); + + al.Add(Encoder.UrlEncode(properties)); + } + + return Encoder.UrlEncode(al); + } + } +} diff --git a/Web/Ui/TimeFormat.cs b/Web/Ui/TimeFormat.cs new file mode 100644 index 0000000..d49fbd3 --- /dev/null +++ b/Web/Ui/TimeFormat.cs @@ -0,0 +1,39 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + +namespace DayPilot.Web.Ui +{ + /// + /// Options for the time format. + /// + public enum TimeFormat + { + /// + /// 12-hours time format (e.g. 2 p.m.) + /// + Clock12Hours, + + /// + /// 24-hours time format (e.g. 14:00) + /// + Clock24Hours + } +} diff --git a/Web/Ui/UserActionHandling.cs b/Web/Ui/UserActionHandling.cs new file mode 100644 index 0000000..e44b0f1 --- /dev/null +++ b/Web/Ui/UserActionHandling.cs @@ -0,0 +1,40 @@ +/* +Copyright © 2005 - 2008 Annpoint, s.r.o. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------------------------------------------------------------------------- + +NOTE: Reuse requires the following acknowledgement (see also NOTICE): +This product includes DayPilot (http://www.daypilot.org) developed by Annpoint, s.r.o. +*/ + + +namespace DayPilot.Web.Ui +{ + /// + /// Summary description for UserActionHandling. + /// + public enum UserActionHandling + { + /// + /// It should run a JavaScript action. + /// + JavaScript, + + /// + /// It should call a PostBack. + /// + PostBack + } +} diff --git a/app.config b/app.config new file mode 100644 index 0000000..32d0381 --- /dev/null +++ b/app.config @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file