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,13 +51,13 @@ 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,
account.AccountId, account.AccountId,
account.Locale.Name, account.Locale.Name,
account.AccountName); account.AccountName);
dataGridView1[COL_Export, row].ToolTipText = "Export account authorization to audible-cli"; dataGridView1[COL_Export, row].ToolTipText = "Export account authorization to audible-cli";
} }

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
{ {
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) 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)
{ {
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,11 +1,12 @@
using System.Drawing; using System.Drawing;
using System.Windows.Forms;
namespace LibationWinForms.GridView namespace LibationWinForms.GridView
{ {
public class DataGridViewImageButtonCell : DataGridViewButtonCell public class DataGridViewImageButtonCell : AccessibleDataGridViewButtonCell
{ {
protected void DrawButtonImage(Graphics graphics, Image image, Rectangle cellBounds) public DataGridViewImageButtonCell(string accessibilityName) : base(accessibilityName) { }
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

@ -20,20 +20,33 @@ namespace LibationWinForms.GridView
} }
internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell
{ {
private static Image ButtonImage { get; } = Properties.Resources.edit_25x25; public EditTagsDataGridViewImageButtonCell() : base("Edit Tags button") { }
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)
{ {
if (rowIndex >= 0 && DataGridView.GetBoundItem<IGridEntry>(rowIndex) is ISeriesEntry) // series
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); if (rowIndex >= 0 && DataGridView.GetBoundItem<IGridEntry>(rowIndex) is ISeriesEntry)
else if (value is string tagStr && tagStr.Length == 0) {
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)
{ {
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,15 +21,19 @@ namespace LibationWinForms.GridView
} }
} }
internal class LastDownloadedGridViewCell : DataGridViewTextBoxCell internal class LastDownloadedGridViewCell : AccessibleDataGridViewTextBoxCell
{ {
private LastDownloadStatus LastDownload => (LastDownloadStatus)Value; private LastDownloadStatus LastDownload => (LastDownloadStatus)Value;
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)
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)
{ {
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,14 +49,14 @@ 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);
}
else AccessibilityDescription = ReadOnly ? "" : "Click to change ratings";
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, string.Empty, string.Empty, errorText, cellStyle, advancedBorderStyle, paintParts); }
} else
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, string.Empty, string.Empty, errorText, cellStyle, advancedBorderStyle, paintParts);
}
protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
=> value is Rating rating ? rating.ToStarString() : value?.ToString(); => value is Rating rating ? rating.ToStarString() : value?.ToString();

View File

@ -13,37 +13,40 @@ namespace LibationWinForms.SeriesView
CellTemplate.Style.WrapMode = DataGridViewTriState.True; CellTemplate.Style.WrapMode = DataGridViewTriState.True;
} }
} }
internal class DownloadButtonColumnCell : DataGridViewButtonCell internal class DownloadButtonColumnCell : AccessibleDataGridViewButtonCell
{ {
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) public DownloadButtonColumnCell() : base("Download Series button") { }
{
if (value is SeriesButton sentry)
{
string cellValue = sentry.DisplayText;
if (!sentry.Enabled)
{
//Draw disabled button
Rectangle buttonArea = cellBounds;
Rectangle buttonAdjustment = BorderWidths(advancedBorderStyle);
buttonArea.X += buttonAdjustment.X;
buttonArea.Y += buttonAdjustment.Y;
buttonArea.Height -= buttonAdjustment.Height;
buttonArea.Width -= buttonAdjustment.Width;
ButtonRenderer.DrawButton(graphics, buttonArea, cellValue, cellStyle.Font, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak, focused: false, PushButtonState.Disabled);
} 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)
else if (sentry.HasButtonAction) {
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, cellValue, cellValue, errorText, cellStyle, advancedBorderStyle, paintParts); if (value is not SeriesButton seriesEntry)
else {
{ 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); return;
TextRenderer.DrawText(graphics, cellValue, cellStyle.Font, cellBounds, cellStyle.ForeColor); }
}
} string cellValue = seriesEntry.DisplayText;
else AccessibilityDescription = cellValue;
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border); if (!seriesEntry.Enabled)
} {
} //Draw disabled button
Rectangle buttonArea = cellBounds;
Rectangle buttonAdjustment = BorderWidths(advancedBorderStyle);
buttonArea.X += buttonAdjustment.X;
buttonArea.Y += buttonAdjustment.Y;
buttonArea.Height -= buttonAdjustment.Height;
buttonArea.Width -= buttonAdjustment.Width;
ButtonRenderer.DrawButton(graphics, buttonArea, cellValue, cellStyle.Font, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak, focused: false, PushButtonState.Disabled);
}
else if (seriesEntry.HasButtonAction)
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, cellValue, cellValue, errorText, cellStyle, advancedBorderStyle, paintParts);
else
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
TextRenderer.DrawText(graphics, cellValue, cellStyle.Font, cellBounds, cellStyle.ForeColor);
}
}
} }
} }