Add accessibility

This commit is contained in:
Robert McRackan 2024-05-07 10:39:30 -04:00
parent d19fe2250c
commit 27b2fe741c
10 changed files with 220 additions and 101 deletions

View File

@ -0,0 +1,49 @@
using System.Windows.Forms;
namespace LibationWinForms
{
public class AccessibleDataGridViewButtonCell : DataGridViewButtonCell
{
protected string AccessibilityName
{
get => MyAccessibilityObject.AccessibilityName;
set => MyAccessibilityObject.AccessibilityName = value;
}
/// <summary>
/// Get or set description for accessibility. eg: screen readers. Also sets the ToolTipText
/// </summary>
protected string AccessibilityDescription
{
get => MyAccessibilityObject.AccessibilityDescription;
set
{
MyAccessibilityObject.AccessibilityDescription = value;
MyAccessibilityObject.Owner.ToolTipText = value;
}
}
protected ButtonCellAccessibilityObject MyAccessibilityObject { get; set; }
protected override AccessibleObject CreateAccessibilityInstance() => MyAccessibilityObject;
public AccessibleDataGridViewButtonCell(string accessibilityName) : base()
{
MyAccessibilityObject = new(this, name: accessibilityName, description: "");
}
protected class ButtonCellAccessibilityObject : DataGridViewButtonCellAccessibleObject
{
public string AccessibilityName { get; set; }
public string AccessibilityDescription { get; set; }
public override string Name => AccessibilityName;
public override string Description => AccessibilityDescription;
public ButtonCellAccessibilityObject(DataGridViewCell owner, string name, string description) : base(owner)
{
AccessibilityName = name;
AccessibilityDescription = description;
}
}
}
}

View File

@ -0,0 +1,49 @@
using System.Windows.Forms;
namespace LibationWinForms
{
internal class AccessibleDataGridViewTextBoxCell : DataGridViewTextBoxCell
{
protected virtual string AccessibilityName
{
get => MyAccessibilityObject.AccessibilityName;
set => MyAccessibilityObject.AccessibilityName = value;
}
/// <summary>
/// Get or set description for accessibility. eg: screen readers. Also sets the ToolTipText
/// </summary>
protected string AccessibilityDescription
{
get => MyAccessibilityObject.AccessibilityDescription;
set
{
MyAccessibilityObject.AccessibilityDescription = value;
MyAccessibilityObject.Owner.ToolTipText = value;
}
}
protected ButtonCellAccessibilityObject MyAccessibilityObject { get; set; }
protected override AccessibleObject CreateAccessibilityInstance() => MyAccessibilityObject;
public AccessibleDataGridViewTextBoxCell(string accessibilityName) : base()
{
MyAccessibilityObject = new(this, name: accessibilityName, description: "");
}
protected class ButtonCellAccessibilityObject : DataGridViewTextBoxCellAccessibleObject
{
public string AccessibilityName { get; set; }
public string AccessibilityDescription { get; set; }
public override string Name => AccessibilityName;
public override string Description => AccessibilityDescription;
public ButtonCellAccessibilityObject(DataGridViewCell owner, string name, string description) : base(owner)
{
AccessibilityName = name;
AccessibilityDescription = description;
}
}
}
}

View File

@ -51,7 +51,7 @@ namespace LibationWinForms.Dialogs
private void AddAccountToGrid(Account account) private void AddAccountToGrid(Account account)
{ {
int row = dataGridView1.Rows.Add( var row = dataGridView1.Rows.Add(
"X", "X",
"Export", "Export",
account.LibraryScan, account.LibraryScan,

View File

@ -24,23 +24,39 @@ namespace LibationWinForms.Dialogs
private const string COL_MoveUp = nameof(MoveUp); private const string COL_MoveUp = nameof(MoveUp);
private const string COL_MoveDown = nameof(MoveDown); private const string COL_MoveDown = nameof(MoveDown);
internal class DisableButtonCell : DataGridViewButtonCell internal class DisableButtonCell : AccessibleDataGridViewButtonCell
{ {
private int LastRowIndex => DataGridView.Rows[^1].IsNewRow ? DataGridView.Rows[^1].Index - 1 : DataGridView.Rows[^1].Index;
public DisableButtonCell() : base("Edit Filter button") { }
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{ {
if ((OwningColumn.Name == COL_MoveUp && rowIndex == 0) var isMoveUp = OwningColumn.Name == COL_MoveUp;
|| (OwningColumn.Name == COL_MoveDown && rowIndex == LastRowIndex) var isMoveDown = OwningColumn.Name == COL_MoveDown;
|| OwningRow.IsNewRow) var isDelete = OwningColumn.Name == COL_Delete;
var isNewRow = OwningRow.IsNewRow;
if (isNewRow
|| (isMoveUp && rowIndex == 0)
|| (isMoveDown && rowIndex == LastRowIndex))
{ {
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts ^ (DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.SelectionBackground)); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts ^ (DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.SelectionBackground));
ButtonRenderer.DrawButton(graphics, cellBounds, value as string, cellStyle.Font, false, System.Windows.Forms.VisualStyles.PushButtonState.Disabled); ButtonRenderer.DrawButton(graphics, cellBounds, value as string, cellStyle.Font, false, System.Windows.Forms.VisualStyles.PushButtonState.Disabled);
} }
else else
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
}
int LastRowIndex => DataGridView.Rows[^1].IsNewRow ? DataGridView.Rows[^1].Index - 1 : DataGridView.Rows[^1].Index; if (isMoveUp)
AccessibilityDescription = "Move up";
else if (isMoveDown)
AccessibilityDescription = "Move down";
else if (isDelete)
AccessibilityDescription = "Delete";
}
}
} }
public EditQuickFilters() public EditQuickFilters()

View File

@ -1,10 +1,11 @@
using System.Drawing; using System.Drawing;
using System.Windows.Forms;
namespace LibationWinForms.GridView namespace LibationWinForms.GridView
{ {
public class DataGridViewImageButtonCell : DataGridViewButtonCell public class DataGridViewImageButtonCell : AccessibleDataGridViewButtonCell
{ {
public DataGridViewImageButtonCell(string accessibilityName) : base(accessibilityName) { }
protected void DrawButtonImage(Graphics graphics, Image image, Rectangle cellBounds) protected void DrawButtonImage(Graphics graphics, Image image, Rectangle cellBounds)
{ {
var scaleFactor = OwningColumn is IDataGridScaleColumn scCol ? scCol.ScaleFactor : 1f; var scaleFactor = OwningColumn is IDataGridScaleColumn scCol ? scCol.ScaleFactor : 1f;

View File

@ -21,19 +21,32 @@ namespace LibationWinForms.GridView
internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell
{ {
public EditTagsDataGridViewImageButtonCell() : base("Edit Tags button") { }
private static Image ButtonImage { get; } = Properties.Resources.edit_25x25; private static Image ButtonImage { get; } = Properties.Resources.edit_25x25;
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{ {
// series
if (rowIndex >= 0 && DataGridView.GetBoundItem<IGridEntry>(rowIndex) is ISeriesEntry) if (rowIndex >= 0 && DataGridView.GetBoundItem<IGridEntry>(rowIndex) is ISeriesEntry)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
}
// tag: empty
else if (value is string tagStr && tagStr.Length == 0) else if (value is string tagStr && tagStr.Length == 0)
{ {
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
DrawButtonImage(graphics, ButtonImage, cellBounds); DrawButtonImage(graphics, ButtonImage, cellBounds);
AccessibilityDescription = "Click to edit tags";
} }
// tag: not empty
else else
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
AccessibilityDescription = (string)value;
}
} }
} }
} }

View File

@ -1,7 +1,7 @@
using LibationUiBase.GridView; using System;
using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using LibationUiBase.GridView;
namespace LibationWinForms.GridView namespace LibationWinForms.GridView
{ {
@ -21,14 +21,18 @@ namespace LibationWinForms.GridView
} }
} }
internal class LastDownloadedGridViewCell : DataGridViewTextBoxCell internal class LastDownloadedGridViewCell : AccessibleDataGridViewTextBoxCell
{ {
private LastDownloadStatus LastDownload => (LastDownloadStatus)Value; private LastDownloadStatus LastDownload => (LastDownloadStatus)Value;
public LastDownloadedGridViewCell() : base("Last Downloaded") { }
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{ {
if (value is LastDownloadStatus lastDl)
ToolTipText = lastDl.ToolTipText;
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
if (value is LastDownloadStatus lastDl)
AccessibilityDescription = lastDl.ToolTipText;
} }
protected override void OnDoubleClick(DataGridViewCellEventArgs e) protected override void OnDoubleClick(DataGridViewCellEventArgs e)

View File

@ -16,25 +16,7 @@ namespace LibationWinForms.GridView
internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell internal class LiberateDataGridViewImageButtonCell : DataGridViewImageButtonCell
{ {
#region Accessibility public LiberateDataGridViewImageButtonCell() : base("Liberate button") { }
private string accessibilityName => "Liberate Image Button";
private string accessibilityDescription = "undefined";
protected override AccessibleObject CreateAccessibilityInstance() => new MyAccessibilityObject(accessibilityName, accessibilityDescription);
protected class MyAccessibilityObject : DataGridViewCellAccessibleObject
{
public override string Name => _name;
public override string Description => _description;
private string _name { get; }
private string _description { get; }
public MyAccessibilityObject(string name, string description) : base()
{
_name = name;
_description = description;
}
}
#endregion
private static readonly Brush DISABLED_GRAY = new SolidBrush(Color.FromArgb(0x60, Color.LightGray)); private static readonly Brush DISABLED_GRAY = new SolidBrush(Color.FromArgb(0x60, Color.LightGray));
private static readonly Color HiddenForeColor = Color.LightGray; private static readonly Color HiddenForeColor = Color.LightGray;
@ -51,8 +33,7 @@ namespace LibationWinForms.GridView
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
DrawButtonImage(graphics, (Image)status.ButtonImage, cellBounds); DrawButtonImage(graphics, (Image)status.ButtonImage, cellBounds);
accessibilityDescription = status.ToolTip; AccessibilityDescription = status.ToolTip;
ToolTipText = status.ToolTip;
if (status.IsUnavailable || status.Opacity < 1) if (status.IsUnavailable || status.Opacity < 1)
graphics.FillRectangle(DISABLED_GRAY, cellBounds); graphics.FillRectangle(DISABLED_GRAY, cellBounds);

View File

@ -1,9 +1,9 @@
using DataLayer; using System;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using DataLayer;
namespace LibationWinForms.GridView namespace LibationWinForms.GridView
{ {
@ -24,14 +24,17 @@ namespace LibationWinForms.GridView
} }
} }
internal class MyRatingGridViewCell : DataGridViewTextBoxCell internal class MyRatingGridViewCell : AccessibleDataGridViewTextBoxCell
{ {
private static Rating DefaultRating => new Rating(0, 0, 0); private static Rating DefaultRating => new Rating(0, 0, 0);
public override object DefaultNewRowValue => DefaultRating; public override object DefaultNewRowValue => DefaultRating;
public override Type EditType => typeof(MyRatingCellEditor); public override Type EditType => typeof(MyRatingCellEditor);
public override Type ValueType => typeof(Rating); public override Type ValueType => typeof(Rating);
public MyRatingGridViewCell() { ToolTipText = ReadOnly ? "" : "Click to change ratings"; } public MyRatingGridViewCell() : base("My Rating")
{
AccessibilityDescription = ReadOnly ? "" : "Click to change ratings";
}
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{ {
@ -46,10 +49,10 @@ namespace LibationWinForms.GridView
{ {
if (value is Rating rating) if (value is Rating rating)
{ {
ToolTipText = ReadOnly ? "" : "Click to change ratings";
var starString = rating.ToStarString(); var starString = rating.ToStarString();
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, starString, starString, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, starString, starString, errorText, cellStyle, advancedBorderStyle, paintParts);
AccessibilityDescription = ReadOnly ? "" : "Click to change ratings";
} }
else else
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, string.Empty, string.Empty, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, string.Empty, string.Empty, errorText, cellStyle, advancedBorderStyle, paintParts);

View File

@ -13,14 +13,22 @@ namespace LibationWinForms.SeriesView
CellTemplate.Style.WrapMode = DataGridViewTriState.True; CellTemplate.Style.WrapMode = DataGridViewTriState.True;
} }
} }
internal class DownloadButtonColumnCell : DataGridViewButtonCell internal class DownloadButtonColumnCell : AccessibleDataGridViewButtonCell
{ {
public DownloadButtonColumnCell() : base("Download Series button") { }
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{ {
if (value is SeriesButton sentry) if (value is not SeriesButton seriesEntry)
{ {
string cellValue = sentry.DisplayText; base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
if (!sentry.Enabled) return;
}
string cellValue = seriesEntry.DisplayText;
AccessibilityDescription = cellValue;
if (!seriesEntry.Enabled)
{ {
//Draw disabled button //Draw disabled button
Rectangle buttonArea = cellBounds; Rectangle buttonArea = cellBounds;
@ -29,10 +37,10 @@ namespace LibationWinForms.SeriesView
buttonArea.Y += buttonAdjustment.Y; buttonArea.Y += buttonAdjustment.Y;
buttonArea.Height -= buttonAdjustment.Height; buttonArea.Height -= buttonAdjustment.Height;
buttonArea.Width -= buttonAdjustment.Width; buttonArea.Width -= buttonAdjustment.Width;
ButtonRenderer.DrawButton(graphics, buttonArea, cellValue, cellStyle.Font, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak, focused: false, PushButtonState.Disabled);
ButtonRenderer.DrawButton(graphics, buttonArea, cellValue, cellStyle.Font, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak, focused: false, PushButtonState.Disabled);
} }
else if (sentry.HasButtonAction) else if (seriesEntry.HasButtonAction)
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, cellValue, cellValue, errorText, cellStyle, advancedBorderStyle, paintParts); base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, cellValue, cellValue, errorText, cellStyle, advancedBorderStyle, paintParts);
else else
{ {
@ -40,10 +48,5 @@ namespace LibationWinForms.SeriesView
TextRenderer.DrawText(graphics, cellValue, cellStyle.Font, cellBounds, cellStyle.ForeColor); TextRenderer.DrawText(graphics, cellValue, cellStyle.Font, cellBounds, cellStyle.ForeColor);
} }
} }
else
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
}
}
} }
} }