Skip to content

Commit 0160d0e

Browse files
committed
Nullability support
1 parent ee6e682 commit 0160d0e

16 files changed

+367
-408
lines changed

DrawnTableControl.Demo/Form1.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private void Table_CellWithValueClick(object sender, CellClickEventArgs e)
226226
private void Table_CellOverlapPlaceholderClick(object sender, CellOverlapEventArgs e)
227227
{
228228
List<Event> events = e.OverlappingCells.Select(oc => (Event)oc.Value).ToList();
229-
MessageBox.Show($"{events.Count} events are overlaping", "Overlapped cell clicked");
229+
MessageBox.Show($"{events.Count} events are overlapping", "Overlapped cell clicked");
230230
}
231231

232232
private void Table_CellCreating(object sender, CellChangedEventArgs e)

DrawnTableControl/DrawnTable.cs

Lines changed: 33 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using DrawnTableControl.Services;
55
using System;
66
using System.Collections.Generic;
7+
using System.Diagnostics.CodeAnalysis;
78
using System.Drawing;
89
using System.Drawing.Drawing2D;
910
using System.Linq;
@@ -41,7 +42,7 @@ public bool AllowDragDrop
4142
private DrawnTableOverlapOptions ifCellsOverlap = DrawnTableOverlapOptions.ThrowError;
4243
/// <summary>
4344
/// Attention! This option allow cell to be overlapped by another cell been added via AddCell method only.
44-
/// If option "Hide" is chosen, once cells overlapped each other they got removed from table and basicly became impossible to interact with.
45+
/// If option "Hide" is chosen, once cells overlapped each other they got removed from table and basically became impossible to interact with.
4546
/// If option "Merge" is chosen, once cells overlapped each other their values need to be merged manually by CellsMerging event.
4647
/// </summary>
4748
public DrawnTableOverlapOptions IfCellsOverlap
@@ -92,6 +93,7 @@ public DrawnTableCopyMode CellCopyMode
9293
}
9394

9495
// Table information
96+
[MemberNotNullWhen(true, nameof(table))]
9597
public bool IsEnabled { get; private set; } = false;
9698
public RectangleF CellsArea { get; private set; }
9799
public RectangleF TableArea { get; private set; }
@@ -116,7 +118,7 @@ public Color BorderColor
116118
public DrawnTableCells Cells { get; private set; }
117119
//public int CellMargin { get; set; } = 2;
118120

119-
internal Bitmap table { get; private set; }
121+
internal Bitmap? table { get; private set; }
120122

121123
private readonly PBDrawnTable Owner;
122124
internal DeferredExecution dRedrawEx;
@@ -126,52 +128,25 @@ public Color BorderColor
126128
#endregion
127129

128130
#region Events
129-
public event EventHandler<CellMovedEventArgs> CellDragOver;
130-
public event EventHandler<CellMovedEventArgs> CellDragDropFinished;
131-
public event EventHandler<CellClickEventArgs> CellWithValueClick;
132-
public event EventHandler<CellChangedEventArgs> CellCreated;
133-
public event EventHandler<CellChangedEventArgs> CellCreating;
134-
public event EventHandler<CellOverlapEventArgs> CellOverlapPlaceholderClick;
135-
public event EventHandler<CellsMergingEventArgs> CellsMerging;
136-
public event EventHandler<CellCopiedEventArgs> CellCopied;
137-
public event EventHandler<CellPastedEventArgs> CellPasted;
138-
139-
internal virtual void OnCellDragOver(CellMovedEventArgs e)
140-
{
141-
CellDragOver?.Invoke(this, e);
142-
}
143-
internal virtual void OnCellDragDropFinished(CellMovedEventArgs e)
144-
{
145-
CellDragDropFinished?.Invoke(this, e);
146-
}
147-
internal virtual void OnCellWithValueClick(CellClickEventArgs e)
148-
{
149-
CellWithValueClick?.Invoke(this, e);
150-
}
151-
internal virtual void OnCellCreating(CellChangedEventArgs e)
152-
{
153-
CellCreating?.Invoke(this, e);
154-
}
155-
internal virtual void OnCellCreated(CellChangedEventArgs e)
156-
{
157-
CellCreated?.Invoke(this, e);
158-
}
159-
internal virtual void OnCellOverlapPlaceholderClick(CellOverlapEventArgs e)
160-
{
161-
CellOverlapPlaceholderClick?.Invoke(this, e);
162-
}
163-
internal virtual void OnCellsMerging(CellsMergingEventArgs e)
164-
{
165-
CellsMerging?.Invoke(this, e);
166-
}
167-
internal virtual void OnCellCopied(CellCopiedEventArgs e)
168-
{
169-
CellCopied?.Invoke(this, e);
170-
}
171-
internal virtual void OnCellPasted(CellPastedEventArgs e)
172-
{
173-
CellPasted?.Invoke(this, e);
174-
}
131+
public event EventHandler<CellMovedEventArgs>? CellDragOver;
132+
public event EventHandler<CellMovedEventArgs>? CellDragDropFinished;
133+
public event EventHandler<CellClickEventArgs>? CellWithValueClick;
134+
public event EventHandler<CellChangedEventArgs>? CellCreated;
135+
public event EventHandler<CellChangedEventArgs>? CellCreating;
136+
public event EventHandler<CellOverlapEventArgs>? CellOverlapPlaceholderClick;
137+
public event EventHandler<CellsMergingEventArgs>? CellsMerging;
138+
public event EventHandler<CellCopiedEventArgs>? CellCopied;
139+
public event EventHandler<CellPastedEventArgs>? CellPasted;
140+
141+
internal virtual void OnCellDragOver(CellMovedEventArgs e) => CellDragOver?.Invoke(this, e);
142+
internal virtual void OnCellDragDropFinished(CellMovedEventArgs e) => CellDragDropFinished?.Invoke(this, e);
143+
internal virtual void OnCellWithValueClick(CellClickEventArgs e) => CellWithValueClick?.Invoke(this, e);
144+
internal virtual void OnCellCreating(CellChangedEventArgs e) => CellCreating?.Invoke(this, e);
145+
internal virtual void OnCellCreated(CellChangedEventArgs e) => CellCreated?.Invoke(this, e);
146+
internal virtual void OnCellOverlapPlaceholderClick(CellOverlapEventArgs e) => CellOverlapPlaceholderClick?.Invoke(this, e);
147+
internal virtual void OnCellsMerging(CellsMergingEventArgs e) => CellsMerging?.Invoke(this, e);
148+
internal virtual void OnCellCopied(CellCopiedEventArgs e) => CellCopied?.Invoke(this, e);
149+
internal virtual void OnCellPasted(CellPastedEventArgs e) => CellPasted?.Invoke(this, e);
175150
#endregion
176151

177152
internal DrawnTable(PBDrawnTable owner)
@@ -203,7 +178,7 @@ public void Create(List<DrawnTableHeader> rows, List<DrawnTableHeader> cols)
203178
public void Remove()
204179
{
205180
IsEnabled = false;
206-
Cells = null;
181+
Cells = new DrawnTableCells(this);
207182
table?.Dispose();
208183
table = null;
209184
Owner.mouseDown = false;
@@ -224,16 +199,10 @@ public void Remove()
224199
CellPasted = null;
225200
}
226201

227-
private RectangleF GetDefaultArea()
228-
{
229-
return new RectangleF(0, 0, Owner.Width, Owner.Height);
230-
}
202+
private RectangleF GetDefaultArea() => new(0, 0, Owner.Width, Owner.Height);
231203

232204
internal void Resize() => Resize(GetDefaultArea());
233-
internal void Resize(RectangleF newTableArea)
234-
{
235-
dRedrawEx.Execute(() => ActualRedraw(newTableArea));
236-
}
205+
internal void Resize(RectangleF newTableArea) => dRedrawEx.Execute(() => ActualRedraw(newTableArea));
237206

238207
public Font GetDefaultFont()
239208
{
@@ -260,10 +229,7 @@ internal static Graphics GetGraphics(Image image)
260229
return graphics;
261230
}
262231

263-
public void Redraw()
264-
{
265-
dRedrawEx.Execute(() => ActualRedraw());
266-
}
232+
public void Redraw() => dRedrawEx.Execute(() => ActualRedraw());
267233

268234
private void ActualRedraw(RectangleF area = default)
269235
{
@@ -305,7 +271,7 @@ internal void ActualRedraw(Graphics g, RectangleF area)
305271
g.DrawImage(table, TableArea);
306272

307273
// Coping cells and back colors to draw them in the separate thread
308-
Dictionary<DrawnTableCell, RectangleF> currCells = null;
274+
Dictionary<DrawnTableCell, RectangleF> currCells = null!;
309275
Owner.Invoke(new Action(() =>
310276
{
311277
currCells = Cells.Select(c => (DrawnTableCell)c.Clone(true)).ToDictionary(x => x, i => RectangleF.Empty);
@@ -374,10 +340,7 @@ private Bitmap RedrawBackground()
374340

375341
private void DrawTable(Graphics g, SizeF size, List<DrawnTableHeader> cols, List<DrawnTableHeader> rows, Font font)
376342
{
377-
if (cols.Count == 0 || rows.Count == 0)
378-
{
379-
return;
380-
}
343+
if (cols.Count == 0 || rows.Count == 0) return;
381344

382345
const int div = 1;
383346
float colHeaderH = cols.Max(c => TextRenderer.MeasureText(c.Text, font).Height);
@@ -475,7 +438,7 @@ private void DrawTable(Graphics g, SizeF size, List<DrawnTableHeader> cols, List
475438
RowHeight = rowH;
476439
}
477440

478-
internal RectangleF DrawCell(DrawnTableCell cell, Graphics g = null)
441+
internal RectangleF DrawCell(DrawnTableCell cell, Graphics? g = null)
479442
{
480443
RectangleF cellArea = GetCellArea(cell.Location);
481444
if (cell.Rowspan != 1)
@@ -492,7 +455,8 @@ internal RectangleF DrawCell(DrawnTableCell cell, Graphics g = null)
492455

493456
return res;
494457
}
495-
internal static RectangleF DrawCell(string text, Font font, Brush brush, RectangleF area, StringFormat format = null, Graphics g = null)
458+
459+
internal static RectangleF DrawCell(string? text, Font font, Brush brush, RectangleF area, StringFormat? format = null, Graphics? g = null)
496460
{
497461
const int padding = 2;
498462

@@ -624,10 +588,7 @@ private static int CountHeaders(IEnumerable<DrawnTableHeader> headers)
624588
return headerCount;
625589
}
626590

627-
public void SuspendRedrawing()
628-
{
629-
isRedrawingSuspended = true;
630-
}
591+
public void SuspendRedrawing() => isRedrawingSuspended = true;
631592

632593
public void ResumeRedrawing()
633594
{
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net40;net5.0-windows</TargetFrameworks>
4+
<TargetFrameworks>net40;net45;net5.0-windows</TargetFrameworks>
55
<LangVersion>latest</LangVersion>
6+
<Nullable>enable</Nullable>
67
<OutputType>Library</OutputType>
78
<UseWindowsForms>true</UseWindowsForms>
89
<EnableNETAnalyzers>true</EnableNETAnalyzers>
@@ -13,20 +14,22 @@
1314
<RepositoryUrl>https://github.com/maxkoshevoi/DrawnTable</RepositoryUrl>
1415
<PackageTags>WinForms, table, datagrid, custom-control</PackageTags>
1516
<RepositoryType>git</RepositoryType>
16-
<Version>1.0.2</Version>
17+
<Version>1.0.3</Version>
1718
<Description>Custom WinForms control based on PictureBox for creating versatile tables</Description>
1819
</PropertyGroup>
19-
20+
21+
<ItemGroup Condition="'$(TargetFramework)' == 'net40' Or '$(TargetFramework)' == 'net45'">
22+
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
23+
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
24+
</ItemGroup>
25+
2026
<ItemGroup Condition="'$(TargetFramework)' == 'net40'">
2127
<Reference Include="System.Windows.Forms" />
22-
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
28+
<PackageReference Include="Microsoft.Bcl.Async" Version="1.0.168" />
2329
</ItemGroup>
2430

2531
<ItemGroup>
26-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
27-
<PrivateAssets>all</PrivateAssets>
28-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
29-
</PackageReference>
32+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="all" />
3033
</ItemGroup>
3134

3235
</Project>

DrawnTableControl/HeaderHelpers/CustomH.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal CustomH()
1717
public void Add(string text) =>
1818
Headers.Add(new DrawnTableHeader(text));
1919

20-
public void Add(string text, object tag) =>
20+
public void Add(string text, object? tag) =>
2121
Headers.Add(new DrawnTableHeader(text, tag: tag));
2222

2323
public void Add(DrawnTableHeader header) =>
@@ -26,7 +26,7 @@ public void Add(DrawnTableHeader header) =>
2626
public void AddRange(IEnumerable<string> dataCollection) =>
2727
Headers.AddRange(dataCollection.Select(d => new DrawnTableHeader(d)));
2828

29-
public void AddRange(IEnumerable<(string text, object tag)> dataTagCollection) =>
29+
public void AddRange(IEnumerable<(string text, object? tag)> dataTagCollection) =>
3030
Headers.AddRange(dataTagCollection.Select(dt => new DrawnTableHeader(dt.text, tag: dt.tag)));
3131

3232
public void AddRange(IEnumerable<DrawnTableHeader> headerCollection) =>
@@ -49,15 +49,15 @@ public int GetIndexByHeaderText(string headerText)
4949
return GetIndexByHeader(match[0]);
5050
}
5151

52-
public int GetIndexByHeaderTag(object tag)
52+
public int GetIndexByHeaderTag(object? tag)
5353
{
5454
var match = Headers.Where(x => x.Tag?.Equals(tag) == true).ToList();
5555
if (match.Count == 0) return -1;
5656

5757
return GetIndexByHeader(match[0]);
5858
}
5959

60-
public DrawnTableHeader this[int index]
60+
public DrawnTableHeader? this[int index]
6161
{
6262
get
6363
{

DrawnTableControl/HeaderHelpers/DayH.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public IEnumerable<DrawnTableHeader> GenerateHeadersWeek(DateTime start, string
3838
return GenerateHeaders(start, start.AddDays(6), null, format, toTitleCase);
3939
}
4040

41-
public IEnumerable<DrawnTableHeader> GenerateHeaders(DateTime start, DateTime end, Func<DateTime, bool> condition = null, string format = "dddd", bool toTitleCase = true)
41+
public IEnumerable<DrawnTableHeader> GenerateHeaders(DateTime start, DateTime end, Func<DateTime, bool>? condition = null, string format = "dddd", bool toTitleCase = true)
4242
{
4343
start = start.Date;
4444
end = end.Date;
@@ -72,7 +72,7 @@ public IEnumerable<DrawnTableHeader> GenerateHeaders(DateTime start, DateTime en
7272

7373
public int GetIndexByValue(DateTime day) => lastResult.IndexOf(day.Date);
7474

75-
public int GetNearestIndexByDay(DateTime day, Func<DateTime, bool> predicate = null)
75+
public int GetNearestIndexByDay(DateTime day, Func<DateTime, bool>? predicate = null)
7676
{
7777
predicate ??= _ => true;
7878

DrawnTableControl/HeaderHelpers/HeaderCreator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ public class HeaderCreator
1313
public CustomH Custom2 { get; } = new();
1414

1515
public static List<DrawnTableHeader> ParseList(IEnumerable<string> collection) =>
16-
ParseList(collection.Select(c => (c, (object)null)));
16+
ParseList(collection.Select(c => (c, (object?)null)));
1717

18-
public static List<DrawnTableHeader> ParseList(IEnumerable<(string text, object tag)> collection) =>
18+
public static List<DrawnTableHeader> ParseList(IEnumerable<(string text, object? tag)> collection) =>
1919
collection.Select(item => new DrawnTableHeader(item.text, tag: item.tag)).ToList();
2020

2121
public int GetRealIndex(List<DrawnTableHeader> headers, int headerIndex, int subheaderIndex)
@@ -45,7 +45,7 @@ public int GetRealIndex(List<DrawnTableHeader> headers, int headerIndex, int sub
4545
return realIndex;
4646
}
4747

48-
public (DrawnTableHeader, DrawnTableSubheader) GetHeadersByRealIndex(List<DrawnTableHeader> headers, int realIndex)
48+
public (DrawnTableHeader?, DrawnTableSubheader?) GetHeadersByRealIndex(List<DrawnTableHeader> headers, int realIndex)
4949
{
5050
if (realIndex < 0)
5151
{

DrawnTableControl/Models/CellLocation.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,18 @@ public CellLocation(int row, int col)
1111
Column = col;
1212
}
1313

14-
public override string ToString()
15-
{
16-
return $"{{ {nameof(Row)} = {Row}; {nameof(Column)} = {Column} }}";
17-
}
14+
public override string ToString() => $"{{ {nameof(Row)} = {Row}; {nameof(Column)} = {Column} }}";
1815

19-
public static bool operator ==(CellLocation one, CellLocation other) => one.Row == other.Row && one.Column == other.Column;
20-
public static bool operator !=(CellLocation one, CellLocation other) => !(one == other);
21-
public override bool Equals(object obj)
22-
{
23-
if (obj is CellLocation location)
24-
{
25-
return location == this;
26-
}
27-
return base.Equals(obj);
28-
}
29-
public override int GetHashCode()
16+
public static bool operator ==(CellLocation? one, CellLocation? other) => one?.Equals(other) ?? other is null;
17+
public static bool operator !=(CellLocation? one, CellLocation? other) => !(one == other);
18+
19+
public override bool Equals(object? obj)
3020
{
31-
return base.GetHashCode();
21+
return obj is CellLocation location &&
22+
Row == location.Row &&
23+
Column == location.Column;
3224
}
25+
26+
public override int GetHashCode() => base.GetHashCode();
3327
}
3428
}

0 commit comments

Comments
 (0)