# FTRCalendarPlanner

## Overview

`FTRCalendarPlannerControl` is a Windows Forms calendar and planning control that allows users to:

* Display a monthly calendar
* Work with Gregorian or Persian (Jalali) calendars
* Select dates
* Add multiple notes to each date
* Edit and delete notes
* Display note summaries directly inside calendar cells
* Display note content through tooltips
* Persist notes using a custom storage provider
* Integrate with the FTR Controls theme system

The control is designed for applications such as:

* Task planners
* Maintenance planning
* Appointment systems
* Production schedules
* Employee schedules
* Project calendars
* Personal calendars
* Reminder systems

---

# Requirements

`FTRCalendarPlannerControl` is a Windows Forms control and should be used in a Windows Forms application.

After referencing the FTR Controls assembly, the control is available from:

**Visual Studio Toolbox → FTR Controls → FTRCalendarPlannerControl**

You can also create it programmatically.

---

# Namespace

```csharp
using FTRControls;
```

Control type:

```csharp
FTRCalendarPlannerControl
```

---

# Quick Start

The simplest way to add the calendar is:

```csharp
var calendar = new FTRCalendarPlannerControl
{
    Dock = DockStyle.Fill
};

this.Controls.Add(calendar);
```

The control starts with the current month.

The default calendar mode is **Gregorian**.

---

# Default Configuration

The control is initialized with the following defaults:

| Property       | Default     |
| -------------- | ----------- |
| `CalendarType` | `Gregorian` |
| `Size`         | `600 × 500` |
| `NoteProvider` | `null`      |

The calendar initially displays the current month.

---

# Calendar Modes

FTRCalendarPlanner supports two calendar systems.

```csharp
public enum CalendarMode
{
    Gregorian,
    Persian
}
```

## Gregorian

Gregorian is the default mode.

```csharp
calendar.CalendarType = CalendarMode.Gregorian;
```

The calendar displays:

* Gregorian month names
* Gregorian dates
* Gregorian weekday names

---

## Persian (Jalali)

To display the Persian calendar:

```csharp
calendar.CalendarType = CalendarMode.Persian;
```

The calendar displays Persian month names and Persian weekday abbreviations.

Example:

```csharp
var calendar = new FTRCalendarPlannerControl
{
    CalendarType = CalendarMode.Persian,
    Size = new Size(600, 500)
};
```

### License

`CalendarMode.Persian` is a Premium feature and requires an activated FTR Controls license.

If the feature is not licensed, the control will prevent changing `CalendarType` to `Persian` and may display the FTR Controls activation prompt.

---

# Important: DateTime in Persian Mode

Even when the calendar is displayed using the Persian calendar, the .NET value exposed by the control is still:

```csharp
System.DateTime
```

The `DateTime` represents the corresponding actual date and can be used normally with .NET, SQL Server and other APIs.

For example:

```csharp
calendar.DateSelected += (sender, date) =>
{
    Console.WriteLine(date.ToString("yyyy-MM-dd"));
};
```

The Persian calendar changes the **display and calendar calculation**, not the type of the returned value.

This is especially important when storing dates in a database.

---

# Date Selection

The `DateSelected` event is raised when the user clicks a valid date.

```csharp
calendar.DateSelected += Calendar_DateSelected;

private void Calendar_DateSelected(object sender, DateTime date)
{
    MessageBox.Show(
        $"Selected date: {date:yyyy-MM-dd}");
}
```

Event definition:

```csharp
public event EventHandler<DateTime> DateSelected;
```

The event provides the selected date as a `DateTime`.

---

# Important Click Behavior

When the user left-clicks a valid date, two things happen:

1. `DateSelected` is raised.
2. The built-in note editor opens for that date.

Therefore, `DateSelected` should normally be used for application logic such as:

* Loading external information
* Updating another control
* Displaying selected-date details
* Filtering records
* Loading tasks for the selected day

It should not be assumed that `DateSelected` is only a notification event; the calendar also opens its built-in note editor automatically.

---

# Changing the Month

The calendar provides previous/next navigation buttons in the header.

Users can:

* Click the left arrow to move to the previous month.
* Click the right arrow to move to the next month.

The calendar automatically reloads notes after changing the month.

---

# Mouse Wheel Navigation

The user can also change the month using the mouse wheel.

* Scroll up → previous month
* Scroll down → next month

This works when the mouse is over the calendar control.

---

# Notes

Each calendar date can contain multiple notes.

A note contains:

```csharp
public class NoteItem
{
    public string Text { get; set; }
    public Color Color { get; set; }
}
```

Each note therefore consists of:

* Text
* Display color

Example:

```csharp
var note = new NoteItem
{
    Text = "Maintenance inspection",
    Color = Color.Orange
};
```

---

# Adding Notes

The built-in note editor is opened by left-clicking a date.

The user can then add one or more notes.

The note editor provides:

* Add Note
* Edit existing notes
* Delete individual notes
* Save

When the user clicks **Save**, the notes are stored in the calendar and, if a `NoteProvider` has been configured, also sent to the provider.

---

# Multiple Notes per Date

A single date can contain multiple notes.

For example:

```text
08:00 - Machine inspection
10:30 - Production meeting
14:00 - Spare parts delivery
```

The calendar displays up to three notes directly inside a date cell.

If more than three notes exist, the calendar displays:

```text
+2 more
```

or the corresponding number of additional notes.

---

# Note Colors

Each note has its own color.

For example:

```csharp
new NoteItem
{
    Text = "Important maintenance",
    Color = Color.Red
};
```

The note color is used as the background of the note displayed inside the calendar.

The text color is automatically selected for readability based on the brightness of the note color.

---

# Editing Existing Notes

If a date already contains notes, left-clicking that date opens the note editor with the existing notes.

The user can:

* Modify note text
* Change note colors
* Add additional notes
* Delete notes
* Save changes

---

# Deleting Notes

Right-click a date that contains notes.

The context menu provides:

* **Edit Notes**
* **Delete All Notes**

Selecting **Delete All Notes** removes all notes for that date.

If a `NoteProvider` is configured, the control also calls:

```csharp
DeleteNotes(date)
```

---

# Tooltips

When the mouse is moved over a date containing notes, the calendar displays the note text as a tooltip.

For example, if a date contains:

```text
Machine inspection
Replace bearing
Check lubrication
```

the tooltip displays the note texts.

If the combined tooltip text exceeds 200 characters, it is automatically shortened and ends with:

```text
...
```

---

# Note Persistence

By default, notes are stored only inside the control's memory.

```csharp
var calendar = new FTRCalendarPlannerControl();
```

This is useful when:

* Persistence is not required.
* The calendar is temporary.
* Notes are managed by another part of the application.

If the application needs notes to survive application restarts, implement `ICalendarNoteProvider`.

---

# ICalendarNoteProvider

`ICalendarNoteProvider` allows the application to control how calendar notes are stored.

```csharp
public interface ICalendarNoteProvider
{
    Dictionary<DateTime, List<NoteItem>> LoadAllNotes(DateTime month);

    void SaveNotes(
        DateTime date,
        List<NoteItem> notes);

    void DeleteNotes(DateTime date);
}
```

The control does not decide where the notes are stored.

You can store notes in:

* SQL Server
* SQLite
* JSON
* XML
* Files
* Web API
* REST service
* Any other storage system

---

# Implementing a Note Provider

A simple provider can be implemented as follows:

```csharp
public class MyNoteProvider : ICalendarNoteProvider
{
    public Dictionary<DateTime, List<NoteItem>> LoadAllNotes(DateTime month)
    {
        // Load notes for the requested month.
        return new Dictionary<DateTime, List<NoteItem>>();
    }

    public void SaveNotes(
        DateTime date,
        List<NoteItem> notes)
    {
        // Save notes for the specified date.
    }

    public void DeleteNotes(DateTime date)
    {
        // Delete all notes for the specified date.
    }
}
```

---

# LoadAllNotes

```csharp
Dictionary<DateTime, List<NoteItem>> LoadAllNotes(DateTime month)
```

The control calls this method when it needs to load notes for the currently displayed month.

The `month` parameter represents the current month being displayed.

The provider should return a dictionary where:

* Key = date
* Value = list of notes for that date

Example:

```csharp
public Dictionary<DateTime, List<NoteItem>> LoadAllNotes(DateTime month)
{
    return new Dictionary<DateTime, List<NoteItem>>
    {
        {
            new DateTime(2026, 8, 10),
            new List<NoteItem>
            {
                new NoteItem
                {
                    Text = "Maintenance",
                    Color = Color.Orange
                }
            }
        }
    };
}
```

---

# SaveNotes

```csharp
void SaveNotes(
    DateTime date,
    List<NoteItem> notes)
```

The control calls this method when the user saves notes for a date.

Example:

```csharp
public void SaveNotes(
    DateTime date,
    List<NoteItem> notes)
{
    foreach (var note in notes)
    {
        Console.WriteLine(
            $"{date:yyyy-MM-dd}: {note.Text}");
    }
}
```

The application is responsible for storing the data permanently.

---

# DeleteNotes

```csharp
void DeleteNotes(DateTime date)
```

The control calls this method when all notes for a date are deleted.

Example:

```csharp
public void DeleteNotes(DateTime date)
{
    // Delete all notes for this date
}
```

---

# SQL Server Example

A typical SQL Server implementation can store notes using a table such as:

```sql
CREATE TABLE CalendarNotes
(
    Id INT IDENTITY PRIMARY KEY,
    NoteDate DATE NOT NULL,
    NoteText NVARCHAR(500) NOT NULL,
    NoteColor INT NOT NULL
);
```

A provider can then use this table to implement:

```csharp
LoadAllNotes()
SaveNotes()
DeleteNotes()
```

The FTRCalendarPlanner control does not require SQL Server specifically; this is only one possible implementation.

---

# Connecting a Provider

Create the provider before adding the calendar to the form.

```csharp
var provider = new MyNoteProvider();

var calendar = new FTRCalendarPlannerControl(provider)
{
    Dock = DockStyle.Fill
};

Controls.Add(calendar);
```

The constructor accepts the provider directly:

```csharp
public FTRCalendarPlannerControl(
    ICalendarNoteProvider provider)
```

This is the recommended approach when persistent storage is required.

---

# Using NoteProvider Property

The provider can also be assigned through the property:

```csharp
var calendar = new FTRCalendarPlannerControl();

calendar.NoteProvider = new MyNoteProvider();
```

For predictable initialization, assigning the provider through the constructor is recommended when creating the control programmatically.

---

# Complete Persistence Example

```csharp
public class CalendarNotes : ICalendarNoteProvider
{
    public Dictionary<DateTime, List<NoteItem>> LoadAllNotes(
        DateTime month)
    {
        // Load notes from your database.

        return new Dictionary<DateTime, List<NoteItem>>();
    }

    public void SaveNotes(
        DateTime date,
        List<NoteItem> notes)
    {
        // Save notes to your database.
    }

    public void DeleteNotes(DateTime date)
    {
        // Delete notes from your database.
    }
}
```

Then:

```csharp
var calendar = new FTRCalendarPlannerControl(
    new CalendarNotes())
{
    CalendarType = CalendarMode.Persian,
    Dock = DockStyle.Fill
};

calendar.DateSelected += (sender, date) =>
{
    Console.WriteLine(
        $"Selected: {date:yyyy-MM-dd}");
};

Controls.Add(calendar);
```

---

# Notes Without Persistence

If you do not need persistent storage:

```csharp
var calendar = new FTRCalendarPlannerControl
{
    CalendarType = CalendarMode.Gregorian,
    Dock = DockStyle.Fill
};

Controls.Add(calendar);
```

Notes will be managed by the control itself during its lifetime.

---

# Theme Support

FTRCalendarPlanner integrates with the FTR Controls theme system.

The calendar automatically adapts to the active FTR theme.

Supported theme modes include:

* Light
* Dark
* Color
* Duotone

The calendar updates its:

* Background
* Header
* Weekday colors
* Text colors
* Border colors

according to the active theme.

---

# Applying the Theme

The control participates in the FTR Controls theme system automatically.

In normal usage, the customer does not need to manually configure calendar colors.

If the application's FTR theme changes, the calendar updates its appearance accordingly.

---

# Gregorian Calendar Example

```csharp
var calendar = new FTRCalendarPlannerControl
{
    CalendarType = CalendarMode.Gregorian,
    Dock = DockStyle.Fill
};

calendar.DateSelected += (sender, date) =>
{
    MessageBox.Show(
        $"Selected: {date:yyyy-MM-dd}");
};

Controls.Add(calendar);
```

---

# Persian Calendar Example

```csharp
var calendar = new FTRCalendarPlannerControl
{
    CalendarType = CalendarMode.Persian,
    Dock = DockStyle.Fill
};

calendar.DateSelected += (sender, date) =>
{
    MessageBox.Show(
        $"Selected date: {date:yyyy-MM-dd}");
};

Controls.Add(calendar);
```

---

# Maintenance Planning Example

The control can be used as a simple maintenance planner.

```csharp
public class MaintenanceNoteProvider
    : ICalendarNoteProvider
{
    public Dictionary<DateTime, List<NoteItem>>
        LoadAllNotes(DateTime month)
    {
        // Load maintenance activities
        // from the database.
        return new Dictionary<DateTime, List<NoteItem>>();
    }

    public void SaveNotes(
        DateTime date,
        List<NoteItem> notes)
    {
        // Save maintenance notes.
    }

    public void DeleteNotes(DateTime date)
    {
        // Delete maintenance notes.
    }
}
```

Usage:

```csharp
var calendar =
    new FTRCalendarPlannerControl(
        new MaintenanceNoteProvider())
    {
        CalendarType = CalendarMode.Persian,
        Dock = DockStyle.Fill
    };

calendar.DateSelected += (sender, date) =>
{
    LoadMaintenanceDetails(date);
};

Controls.Add(calendar);
```

---

# Events

## DateSelected

```csharp
public event EventHandler<DateTime> DateSelected;
```

Raised when the user selects a valid date.

Example:

```csharp
calendar.DateSelected += (sender, date) =>
{
    LoadDataForDate(date);
};
```

The supplied `DateTime` can be used directly with:

* SQL Server
* Entity Framework
* LINQ
* .NET date APIs
* Application business logic

---

# Properties

## CalendarType

```csharp
CalendarMode CalendarType
```

Controls the calendar system.

Available values:

```text
Gregorian
Persian
```

Default:

```text
Gregorian
```

`Persian` requires an activated Premium license.

---

## NoteProvider

```csharp
ICalendarNoteProvider? NoteProvider
```

Specifies the storage provider used to load and save notes.

Set this property when persistent storage is required.

Example:

```csharp
calendar.NoteProvider =
    new MyNoteProvider();
```

If `null`, notes remain in memory only.

---

# Constructors

## Default Constructor

```csharp
public FTRCalendarPlannerControl()
```

Creates a calendar without an external note provider.

Example:

```csharp
var calendar =
    new FTRCalendarPlannerControl();
```

---

## Provider Constructor

```csharp
public FTRCalendarPlannerControl(
    ICalendarNoteProvider provider)
```

Creates a calendar using the specified note provider.

Example:

```csharp
var calendar =
    new FTRCalendarPlannerControl(
        new MyNoteProvider());
```

This is the recommended constructor when the application requires persistent notes.

---

# User Interaction

| Action                      | Result                             |
| --------------------------- | ---------------------------------- |
| Left-click date             | Selects date and opens note editor |
| Left-click previous arrow   | Previous month                     |
| Left-click next arrow       | Next month                         |
| Mouse wheel up              | Previous month                     |
| Mouse wheel down            | Next month                         |
| Right-click date with notes | Opens note context menu            |
| Hover over date with notes  | Shows note tooltip                 |

---

# Right-Click Menu

Right-clicking a date that contains notes displays:

```text
Edit Notes
Delete All Notes
```

## Edit Notes

Opens the note editor for the selected date.

## Delete All Notes

Deletes all notes associated with the selected date.

---

# Note Editor

The built-in note editor allows users to:

* Add notes
* Edit notes
* Delete notes
* Choose a note color
* Save changes

The editor can contain multiple note entries for the same date.

When the user clicks **Save**, only non-empty note texts are collected and stored.

---

# Important Storage Behavior

The control maintains notes in memory and synchronizes them with `NoteProvider` when available.

When the displayed month changes:

1. Existing in-memory notes are cleared.
2. `LoadAllNotes(currentMonth)` is called.
3. Returned notes are loaded into the calendar.

When a user saves notes:

```text
SaveNotes(date, notes)
```

is called.

When a user deletes all notes:

```text
DeleteNotes(date)
```

is called.

---

# Recommended Database Design

When using a relational database, a simple structure is:

```text
CalendarNotes
------------------------------
Id
NoteDate
NoteText
NoteColor
```

For multiple calendars or users, add application-specific fields such as:

```text
UserId
CalendarId
TenantId
```

The FTRCalendarPlanner control does not impose a database schema. The application controls persistence through `ICalendarNoteProvider`.

---

# Best Practices

## Use a NoteProvider for Persistent Applications

If notes need to survive application restarts, always configure a provider.

```csharp
new FTRCalendarPlannerControl(
    new DatabaseNoteProvider());
```

---

## Store Dates as Date/DateTime

Use the `DateTime` received from `DateSelected` when saving the date.

Do not store the displayed Persian date string as the primary date value.

For example:

```csharp
date.ToString("yyyy-MM-dd")
```

can be used for display or formatting, but the actual `DateTime` should normally be stored in the database as a date value.

---

## Load Only the Required Month

`LoadAllNotes(DateTime month)` is called for the currently displayed month.

For database-backed implementations, it is recommended to query only the required month instead of loading all historical notes.

This keeps the control responsive and reduces database traffic.

---

# Complete Example

The following example demonstrates a typical production setup:

```csharp
public partial class CalendarForm : Form
{
    private readonly FTRCalendarPlannerControl calendar;

    public CalendarForm()
    {
        InitializeComponent();

        var provider = new DatabaseNoteProvider();

        calendar = new FTRCalendarPlannerControl(provider)
        {
            CalendarType = CalendarMode.Persian,
            Dock = DockStyle.Fill
        };

        calendar.DateSelected += Calendar_DateSelected;

        Controls.Add(calendar);
    }

    private void Calendar_DateSelected(
        object sender,
        DateTime date)
    {
        LoadDayInformation(date);
    }

    private void LoadDayInformation(DateTime date)
    {
        // Load application-specific information
        // for the selected date.
    }
}
```

---

# API Reference

## Class

```csharp
FTRCalendarPlannerControl
```

## Namespace

```csharp
FTRControls
```

## Base Class

```csharp
FTRBaseUserControl
```

---

## Properties

| Property       | Type                     | Default     | Description           |
| -------------- | ------------------------ | ----------- | --------------------- |
| `CalendarType` | `CalendarMode`           | `Gregorian` | Calendar system       |
| `NoteProvider` | `ICalendarNoteProvider?` | `null`      | External note storage |

---

## Events

| Event          | Type                     | Description                    |
| -------------- | ------------------------ | ------------------------------ |
| `DateSelected` | `EventHandler<DateTime>` | Raised when a date is selected |

---

## Related Types

### CalendarMode

```csharp
public enum CalendarMode
{
    Gregorian,
    Persian
}
```

### NoteItem

```csharp
public class NoteItem
{
    public string Text { get; set; }
    public Color Color { get; set; }
}
```

### ICalendarNoteProvider

```csharp
public interface ICalendarNoteProvider
{
    Dictionary<DateTime, List<NoteItem>> LoadAllNotes(
        DateTime month);

    void SaveNotes(
        DateTime date,
        List<NoteItem> notes);

    void DeleteNotes(
        DateTime date);
}
```

---

# Troubleshooting

## Notes are not saved after restarting the application

Make sure a persistent `ICalendarNoteProvider` has been assigned.

Without a provider:

```csharp
var calendar =
    new FTRCalendarPlannerControl();
```

notes are maintained only in memory.

---

## Notes are not displayed after changing the month

Verify that `LoadAllNotes()` returns the notes belonging to the requested month.

The provider should return dates as `DateTime` keys.

---

## Persian mode cannot be selected

`CalendarMode.Persian` is a Premium feature.

Verify that the FTR Controls license is activated.

---

## DateSelected gives a Gregorian DateTime in Persian mode

This is expected behavior.

The control uses the Persian calendar for display, while the event exposes a standard .NET `DateTime`.

This makes the value directly usable with .NET and database APIs.

---

# Summary

`FTRCalendarPlannerControl` provides a ready-to-use monthly calendar with built-in note management.

For a simple application:

```csharp
var calendar =
    new FTRCalendarPlannerControl();
```

For a persistent application:

```csharp
var calendar =
    new FTRCalendarPlannerControl(
        new DatabaseNoteProvider());
```

For a Persian application:

```csharp
calendar.CalendarType =
    CalendarMode.Persian;
```

The control handles the calendar UI, date selection, note editing, note display, navigation and theme integration, while the application remains responsible for permanent note storage through `ICalendarNoteProvider`.
