mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-09-20 20:07:57 +08:00
#24 make some fields public
This commit is contained in:
@@ -31,5 +31,15 @@
|
|||||||
|
|
||||||
Assert.Throws<ObjectDisposedException>(action);
|
Assert.Throws<ObjectDisposedException>(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetsAllFormFields()
|
||||||
|
{
|
||||||
|
using (var document = PdfDocument.Open(GetFilename(), new ParsingOptions { UseLenientParsing = false }))
|
||||||
|
{
|
||||||
|
var form = document.GetForm();
|
||||||
|
Assert.Equal(16, form.Fields.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,8 +51,8 @@
|
|||||||
|
|
||||||
var text = OtherEncodings.BytesAsLatin1String(stream.ToArray());
|
var text = OtherEncodings.BytesAsLatin1String(stream.ToArray());
|
||||||
|
|
||||||
text = text.Replace("\n", " ");
|
text = LineEndingsToWhiteSpace(text);
|
||||||
content = content.Replace("\r\n", " ");
|
content = LineEndingsToWhiteSpace(content);
|
||||||
content = replacementRegex.Replace(content, " 0$1");
|
content = replacementRegex.Replace(content, " 0$1");
|
||||||
|
|
||||||
Assert.Equal(content, text);
|
Assert.Equal(content, text);
|
||||||
@@ -82,8 +82,8 @@ ET";
|
|||||||
|
|
||||||
var text = OtherEncodings.BytesAsLatin1String(stream.ToArray());
|
var text = OtherEncodings.BytesAsLatin1String(stream.ToArray());
|
||||||
|
|
||||||
text = text.Replace("\n", " ").Trim();
|
text = LineEndingsToWhiteSpace(text).Trim();
|
||||||
var expected = s.Replace("\r\n", " ");
|
var expected = LineEndingsToWhiteSpace(s);
|
||||||
|
|
||||||
Assert.Equal(expected, text);
|
Assert.Equal(expected, text);
|
||||||
}
|
}
|
||||||
@@ -152,5 +152,10 @@ ET";
|
|||||||
|
|
||||||
Assert.Equal(EndText.Value, result[3]);
|
Assert.Equal(EndText.Value, result[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string LineEndingsToWhiteSpace(string str)
|
||||||
|
{
|
||||||
|
return str.Replace("\r\n", " ").Replace('\n', ' ').Replace('\r', ' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,12 @@
|
|||||||
|
|
||||||
var expected = new List<string>
|
var expected = new List<string>
|
||||||
{
|
{
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroChoiceFieldFlags",
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroChoiceOption",
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroComboBoxField",
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroFieldBase",
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroFieldCommonInformation",
|
||||||
|
"UglyToad.PdfPig.AcroForms.Fields.AcroListBoxField",
|
||||||
"UglyToad.PdfPig.Annotations.Annotation",
|
"UglyToad.PdfPig.Annotations.Annotation",
|
||||||
"UglyToad.PdfPig.Annotations.AnnotationBorder",
|
"UglyToad.PdfPig.Annotations.AnnotationBorder",
|
||||||
"UglyToad.PdfPig.Annotations.AnnotationFlags",
|
"UglyToad.PdfPig.Annotations.AnnotationFlags",
|
||||||
@@ -143,6 +149,11 @@
|
|||||||
{
|
{
|
||||||
Assert.True(expected.Contains(publicTypeName), $"Type should not be public: {publicTypeName}.");
|
Assert.True(expected.Contains(publicTypeName), $"Type should not be public: {publicTypeName}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var expectedPublicType in expected)
|
||||||
|
{
|
||||||
|
Assert.True(publicTypeNames.Contains(expectedPublicType), $"Type should be public: {expectedPublicType}.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -176,27 +176,7 @@
|
|||||||
}
|
}
|
||||||
else if (fieldType == NameToken.Tx)
|
else if (fieldType == NameToken.Tx)
|
||||||
{
|
{
|
||||||
var textFlags = (AcroTextFieldFlags)fieldFlags;
|
result = GetTextField(fieldDictionary, fieldType, fieldFlags, information);
|
||||||
|
|
||||||
var textValue = default(string);
|
|
||||||
if (fieldDictionary.TryGet(NameToken.V, out var textValueToken))
|
|
||||||
{
|
|
||||||
if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StringToken valueStringToken))
|
|
||||||
{
|
|
||||||
textValue = valueStringToken.Data;
|
|
||||||
}
|
|
||||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out HexToken valueHexToken))
|
|
||||||
{
|
|
||||||
textValue = valueHexToken.Data;
|
|
||||||
}
|
|
||||||
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken valueStreamToken))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var field = new AcroTextField(fieldDictionary, fieldType, textFlags, information, textValue);
|
|
||||||
result = field;
|
|
||||||
}
|
}
|
||||||
else if (fieldType == NameToken.Ch)
|
else if (fieldType == NameToken.Ch)
|
||||||
{
|
{
|
||||||
@@ -215,6 +195,38 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AcroFieldBase GetTextField(DictionaryToken fieldDictionary, NameToken fieldType, uint fieldFlags, AcroFieldCommonInformation information)
|
||||||
|
{
|
||||||
|
var textFlags = (AcroTextFieldFlags)fieldFlags;
|
||||||
|
|
||||||
|
var textValue = default(string);
|
||||||
|
if (fieldDictionary.TryGet(NameToken.V, out var textValueToken))
|
||||||
|
{
|
||||||
|
if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StringToken valueStringToken))
|
||||||
|
{
|
||||||
|
textValue = valueStringToken.Data;
|
||||||
|
}
|
||||||
|
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out HexToken valueHexToken))
|
||||||
|
{
|
||||||
|
textValue = valueHexToken.Data;
|
||||||
|
}
|
||||||
|
else if (DirectObjectFinder.TryGet(textValueToken, tokenScanner, out StreamToken valueStreamToken))
|
||||||
|
{
|
||||||
|
textValue = OtherEncodings.BytesAsLatin1String(valueStreamToken.Decode(filterProvider).ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxLength = default(int?);
|
||||||
|
if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.MaxLen, tokenScanner, out NumericToken maxLenToken))
|
||||||
|
{
|
||||||
|
maxLength = maxLenToken.Int;
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = new AcroTextField(fieldDictionary, fieldType, textFlags, information, textValue, maxLength);
|
||||||
|
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken fieldType, uint fieldFlags, AcroFieldCommonInformation information)
|
private AcroFieldBase GetChoiceField(DictionaryToken fieldDictionary, NameToken fieldType, uint fieldFlags, AcroFieldCommonInformation information)
|
||||||
{
|
{
|
||||||
var selectedOptions = Array.Empty<string>();
|
var selectedOptions = Array.Empty<string>();
|
||||||
|
40
src/UglyToad.PdfPig/AcroForms/Fields/AcroButtonFieldFlags.cs
Normal file
40
src/UglyToad.PdfPig/AcroForms/Fields/AcroButtonFieldFlags.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags specifying various characteristics of a button type field in an <see cref="AcroFieldBase"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
internal enum AcroButtonFieldFlags : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The user may not change the value of the field.
|
||||||
|
/// </summary>
|
||||||
|
ReadOnly = 1 << 0,
|
||||||
|
/// <summary>
|
||||||
|
/// The field must have a value before the form can be submitted.
|
||||||
|
/// </summary>
|
||||||
|
Required = 1 << 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Must not be exported by the submit form action.
|
||||||
|
/// </summary>
|
||||||
|
NoExport = 1 << 2,
|
||||||
|
/// <summary>
|
||||||
|
/// For radio buttons, one radio button must be set at all times.
|
||||||
|
/// </summary>
|
||||||
|
NoToggleToOff = 1 << 14,
|
||||||
|
/// <summary>
|
||||||
|
/// The field is a set of radio buttons.
|
||||||
|
/// </summary>
|
||||||
|
Radio = 1 << 15,
|
||||||
|
/// <summary>
|
||||||
|
/// The field is a push button.
|
||||||
|
/// </summary>
|
||||||
|
PushButton = 1 << 16,
|
||||||
|
/// <summary>
|
||||||
|
/// For radio buttons a group of radio buttons will toggle on/off at the same time based on their initial value.
|
||||||
|
/// </summary>
|
||||||
|
RadiosInUnison = 1 << 25
|
||||||
|
}
|
||||||
|
}
|
19
src/UglyToad.PdfPig/AcroForms/Fields/AcroCheckboxField.cs
Normal file
19
src/UglyToad.PdfPig/AcroForms/Fields/AcroCheckboxField.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
internal class AcroCheckboxField : AcroFieldBase
|
||||||
|
{
|
||||||
|
public AcroButtonFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
public NameToken CurrentValue { get; }
|
||||||
|
|
||||||
|
public AcroCheckboxField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information, NameToken currentValue) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
CurrentValue = currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceFieldFlags.cs
Normal file
48
src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceFieldFlags.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags specifying various characteristics of a choice type field in an <see cref="AcroFieldBase"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AcroChoiceFieldFlags : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The user may not change the value of the field.
|
||||||
|
/// </summary>
|
||||||
|
ReadOnly = 1 << 0,
|
||||||
|
/// <summary>
|
||||||
|
/// The field must have a value before the form can be submitted.
|
||||||
|
/// </summary>
|
||||||
|
Required = 1 << 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Must not be exported by the submit form action.
|
||||||
|
/// </summary>
|
||||||
|
NoExport = 1 << 2,
|
||||||
|
/// <summary>
|
||||||
|
/// The field is a combo box.
|
||||||
|
/// </summary>
|
||||||
|
Combo = 1 << 17,
|
||||||
|
/// <summary>
|
||||||
|
/// The combo box includes an editable text box. <see cref="Combo"/> must be set.
|
||||||
|
/// </summary>
|
||||||
|
Edit = 1 << 18,
|
||||||
|
/// <summary>
|
||||||
|
/// The options should be sorted alphabetically, this should be ignored by viewer applications.
|
||||||
|
/// </summary>
|
||||||
|
Sort = 1 << 19,
|
||||||
|
/// <summary>
|
||||||
|
/// The field allows multiple options to be selected.
|
||||||
|
/// </summary>
|
||||||
|
MultiSelect = 1 << 21,
|
||||||
|
/// <summary>
|
||||||
|
/// The text entered in the field is not spell checked. <see cref="Combo"/> and <see cref="Edit"/> must be set.
|
||||||
|
/// </summary>
|
||||||
|
DoNotSpellCheck = 1 << 22,
|
||||||
|
/// <summary>
|
||||||
|
/// Any associated field action is fired when the selection is changed rather than on losing focus.
|
||||||
|
/// </summary>
|
||||||
|
CommitOnSelectionChange = 1 << 26
|
||||||
|
}
|
||||||
|
}
|
51
src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs
Normal file
51
src/UglyToad.PdfPig/AcroForms/Fields/AcroChoiceOption.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An option in a choice field, either <see cref="AcroComboBoxField"/> or <see cref="AcroListBoxField"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class AcroChoiceOption
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The index of this option in the array.
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this option is selected.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSelected { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The text of the option.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the option when the form is exported.
|
||||||
|
/// </summary>
|
||||||
|
public string ExportValue { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the field defined an export value for this option.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasExportValue { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="AcroChoiceOption"/>.
|
||||||
|
/// </summary>
|
||||||
|
public AcroChoiceOption(int index, bool isSelected, string name, string exportValue = null)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
IsSelected = isSelected;
|
||||||
|
Name = name;
|
||||||
|
ExportValue = exportValue;
|
||||||
|
HasExportValue = exportValue != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Index}: {Name} ({IsSelected}).";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs
Normal file
60
src/UglyToad.PdfPig/AcroForms/Fields/AcroComboBoxField.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Tokens;
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// A combo box consisting of a drop-down list optionally accompanied by an editable text box in which the
|
||||||
|
/// user can type a value other than the predefined choices.
|
||||||
|
/// </summary>
|
||||||
|
public class AcroComboBoxField : AcroFieldBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The flags specifying the behaviour of this field.
|
||||||
|
/// </summary>
|
||||||
|
public AcroChoiceFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The options to be presented to the user.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The names of any currently selected options.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<string> SelectedOptions { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="AcroComboBoxField"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dictionary">The dictionary for this field.</param>
|
||||||
|
/// <param name="fieldType">The type of this field, must be <see cref="NameToken.Ch"/>.</param>
|
||||||
|
/// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
|
||||||
|
/// <param name="information">Additional information for this field.</param>
|
||||||
|
/// <param name="options">The options in this field.</param>
|
||||||
|
/// <param name="selectedOptionIndices">The indices of the selected options where there are multiple with the same name.</param>
|
||||||
|
/// <param name="selectedOptions">The names of the selected options.</param>
|
||||||
|
public AcroComboBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
||||||
|
IReadOnlyList<string> selectedOptions,
|
||||||
|
IReadOnlyList<int> selectedOptionIndices) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
SelectedOptions = selectedOptions ?? throw new ArgumentNullException(nameof(selectedOptions));
|
||||||
|
SelectedOptionIndices = selectedOptionIndices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,23 +1,24 @@
|
|||||||
namespace UglyToad.PdfPig.AcroForms.Fields
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Tokens;
|
using Tokens;
|
||||||
using Util.JetBrains.Annotations;
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A field in an interactive <see cref="AcroForm"/>.
|
/// A field in an interactive <see cref="AcroForm"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal abstract class AcroFieldBase
|
public abstract class AcroFieldBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The raw PDF dictionary for this field.
|
/// The raw PDF dictionary for this field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public DictionaryToken Dictionary { get; }
|
public DictionaryToken Dictionary { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="string"/> representing the type of this field.
|
/// The <see cref="string"/> representing the type of this field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public string FieldType { get; }
|
public string FieldType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,405 +26,25 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public uint FieldFlags { get; }
|
public uint FieldFlags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The optional information common to all types of field.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
public AcroFieldCommonInformation Information { get; }
|
public AcroFieldCommonInformation Information { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="AcroFieldBase"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dictionary">The dictionary for this field.</param>
|
||||||
|
/// <param name="fieldType">The type of this field.</param>
|
||||||
|
/// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
|
||||||
|
/// <param name="information">Additional information for this field.</param>
|
||||||
protected AcroFieldBase(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information)
|
protected AcroFieldBase(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information)
|
||||||
{
|
{
|
||||||
Dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
|
Dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
|
||||||
FieldType = fieldType ?? throw new ArgumentNullException(nameof(fieldType));
|
FieldType = fieldType ?? throw new ArgumentNullException(nameof(fieldType));
|
||||||
FieldFlags = fieldFlags;
|
FieldFlags = fieldFlags;
|
||||||
Information = information;
|
Information = information ?? new AcroFieldCommonInformation(null, null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A non-leaf field in the form's structure.
|
|
||||||
/// </summary>
|
|
||||||
internal class NonTerminalAcroField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public IReadOnlyList<AcroFieldBase> Children { get; }
|
|
||||||
|
|
||||||
public NonTerminalAcroField(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information,
|
|
||||||
IReadOnlyList<AcroFieldBase> children) :
|
|
||||||
base(dictionary, fieldType, fieldFlags, information)
|
|
||||||
{
|
|
||||||
Children = children ?? throw new ArgumentNullException(nameof(children));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroRadioButtonsField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public AcroButtonFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
public AcroRadioButtonsField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroPushButtonField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public AcroButtonFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
public AcroPushButtonField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroCheckboxField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public AcroButtonFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
public NameToken CurrentValue { get; }
|
|
||||||
|
|
||||||
public AcroCheckboxField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information, NameToken currentValue) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
CurrentValue = currentValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroTextField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public AcroTextFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
public AcroTextField(DictionaryToken dictionary, string fieldType, AcroTextFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information, string textValue) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroSignatureField : AcroFieldBase
|
|
||||||
{
|
|
||||||
public AcroSignatureField(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information) :
|
|
||||||
base(dictionary, fieldType, fieldFlags, information)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
/// <summary>
|
|
||||||
/// A scrollable list box field.
|
|
||||||
/// </summary>
|
|
||||||
internal class AcroListBoxField : AcroFieldBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The flags specifying the behaviour of this field.
|
|
||||||
/// </summary>
|
|
||||||
public AcroChoiceFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The options to be presented to the user.
|
|
||||||
/// </summary>
|
|
||||||
[NotNull]
|
|
||||||
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The names of any currently selected options.
|
|
||||||
/// </summary>
|
|
||||||
[NotNull]
|
|
||||||
public IReadOnlyList<string> SelectedOptions { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For scrollable list boxes gives the index of the first visible option.
|
|
||||||
/// </summary>
|
|
||||||
public int TopIndex { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the field allows multiple selections.
|
|
||||||
/// </summary>
|
|
||||||
public bool SupportsMultiSelect => Flags.Equals(AcroChoiceFieldFlags.MultiSelect);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new <see cref="AcroListBoxField"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dictionary">The dictionary for this field.</param>
|
|
||||||
/// <param name="fieldType">The type of this field, must be <see cref="NameToken.Ch"/>.</param>
|
|
||||||
/// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
|
|
||||||
/// <param name="information">Additional information for this field.</param>
|
|
||||||
/// <param name="options">The options in this field.</param>
|
|
||||||
/// <param name="selectedOptionIndices"></param>
|
|
||||||
/// <param name="topIndex">The first visible option index.</param>
|
|
||||||
/// <param name="selectedOptions"></param>
|
|
||||||
public AcroListBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
|
||||||
IReadOnlyList<string> selectedOptions,
|
|
||||||
IReadOnlyList<int> selectedOptionIndices,
|
|
||||||
int? topIndex) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
SelectedOptions = selectedOptions ?? throw new ArgumentNullException(nameof(selectedOptions));
|
|
||||||
SelectedOptionIndices = selectedOptionIndices;
|
|
||||||
TopIndex = topIndex ?? 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class AcroComboBoxField : AcroFieldBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The flags specifying the behaviour of this field.
|
|
||||||
/// </summary>
|
|
||||||
public AcroChoiceFieldFlags Flags { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The options to be presented to the user.
|
|
||||||
/// </summary>
|
|
||||||
[NotNull]
|
|
||||||
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The names of any currently selected options.
|
|
||||||
/// </summary>
|
|
||||||
[NotNull]
|
|
||||||
public IReadOnlyList<string> SelectedOptions { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
|
||||||
|
|
||||||
public AcroComboBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
|
||||||
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
|
||||||
IReadOnlyList<string> selectedOptions,
|
|
||||||
IReadOnlyList<int> selectedOptionIndices) :
|
|
||||||
base(dictionary, fieldType, (uint)fieldFlags, information)
|
|
||||||
{
|
|
||||||
Flags = fieldFlags;
|
|
||||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
|
||||||
SelectedOptions = selectedOptions ?? throw new ArgumentNullException(nameof(selectedOptions));
|
|
||||||
SelectedOptionIndices = selectedOptionIndices;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An option in a choice field, either <see cref="AcroComboBoxField"/> or <see cref="AcroListBoxField"/>.
|
|
||||||
/// </summary>
|
|
||||||
internal class AcroChoiceOption
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The index of this option in the array.
|
|
||||||
/// </summary>
|
|
||||||
public int Index { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether this option is selected.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsSelected { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The text of the option.
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The value of the option when the form is exported.
|
|
||||||
/// </summary>
|
|
||||||
public string ExportValue { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new <see cref="AcroChoiceOption"/>.
|
|
||||||
/// </summary>
|
|
||||||
public AcroChoiceOption(int index, bool isSelected, string name, string exportValue = null)
|
|
||||||
{
|
|
||||||
Index = index;
|
|
||||||
IsSelected = isSelected;
|
|
||||||
Name = name;
|
|
||||||
ExportValue = exportValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Information from the field dictionary which is common across all field types.
|
|
||||||
/// </summary>
|
|
||||||
internal class AcroFieldCommonInformation
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The reference to the field which is the parent of this one, if applicable.
|
|
||||||
/// </summary>
|
|
||||||
public IndirectReference? Parent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The partial field name for this field. The fully qualified field name is the
|
|
||||||
/// period '.' joined name of all parents' partial names and this field's partial name.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public string PartialName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The alternate field name to be used instead of the fully qualified field name where
|
|
||||||
/// the field is being identified on the user interface or by screen readers.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public string AlternateName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The mapping name used when exporting form field data from the document.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public string MappingName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new <see cref="AcroFieldCommonInformation"/>.
|
|
||||||
/// </summary>
|
|
||||||
public AcroFieldCommonInformation(IndirectReference? parent, string partialName, string alternateName, string mappingName)
|
|
||||||
{
|
|
||||||
Parent = parent;
|
|
||||||
PartialName = partialName;
|
|
||||||
AlternateName = alternateName;
|
|
||||||
MappingName = mappingName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"Parent: {Parent}. Partial: {PartialName}. Alternate: {AlternateName}. Mapping: {MappingName}.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flags specifying various characteristics of a button type field in an <see cref="AcroFieldBase"/>.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
internal enum AcroButtonFieldFlags : uint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The user may not change the value of the field.
|
|
||||||
/// </summary>
|
|
||||||
ReadOnly = 1 << 0,
|
|
||||||
/// <summary>
|
|
||||||
/// The field must have a value before the form can be submitted.
|
|
||||||
/// </summary>
|
|
||||||
Required = 1 << 1,
|
|
||||||
/// <summary>
|
|
||||||
/// Must not be exported by the submit form action.
|
|
||||||
/// </summary>
|
|
||||||
NoExport = 1 << 2,
|
|
||||||
/// <summary>
|
|
||||||
/// For radio buttons, one radio button must be set at all times.
|
|
||||||
/// </summary>
|
|
||||||
NoToggleToOff = 1 << 14,
|
|
||||||
/// <summary>
|
|
||||||
/// The field is a set of radio buttons.
|
|
||||||
/// </summary>
|
|
||||||
Radio = 1 << 15,
|
|
||||||
/// <summary>
|
|
||||||
/// The field is a push button.
|
|
||||||
/// </summary>
|
|
||||||
PushButton = 1 << 16,
|
|
||||||
/// <summary>
|
|
||||||
/// For radio buttons a group of radio buttons will toggle on/off at the same time based on their initial value.
|
|
||||||
/// </summary>
|
|
||||||
RadiosInUnison = 1 << 25
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flags specifying various characteristics of a text type field in an <see cref="AcroFieldBase"/>.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
internal enum AcroTextFieldFlags : uint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The user may not change the value of the field.
|
|
||||||
/// </summary>
|
|
||||||
ReadOnly = 1 << 0,
|
|
||||||
/// <summary>
|
|
||||||
/// The field must have a value before the form can be submitted.
|
|
||||||
/// </summary>
|
|
||||||
Required = 1 << 1,
|
|
||||||
/// <summary>
|
|
||||||
/// Must not be exported by the submit form action.
|
|
||||||
/// </summary>
|
|
||||||
NoExport = 1 << 2,
|
|
||||||
/// <summary>
|
|
||||||
/// The field can contain multiple lines of text.
|
|
||||||
/// </summary>
|
|
||||||
Multiline = 1 << 12,
|
|
||||||
/// <summary>
|
|
||||||
/// The field is for a password and should not be displayed as text and should not be stored to file.
|
|
||||||
/// </summary>
|
|
||||||
Password = 1 << 13,
|
|
||||||
/// <summary>
|
|
||||||
/// The field represents a file path selection.
|
|
||||||
/// </summary>
|
|
||||||
FileSelect = 1 << 20,
|
|
||||||
/// <summary>
|
|
||||||
/// The text entered is not spell checked.
|
|
||||||
/// </summary>
|
|
||||||
DoNotSpellCheck = 1 << 22,
|
|
||||||
/// <summary>
|
|
||||||
/// The field does not scroll if the text exceeds the bounds of the field.
|
|
||||||
/// </summary>
|
|
||||||
DoNotScroll = 1 << 23,
|
|
||||||
/// <summary>
|
|
||||||
/// For a text field which is not a <see cref="Password"/>, <see cref="Multiline"/> or <see cref="FileSelect"/>
|
|
||||||
/// the field text is evenly spaced by splitting into 'combs' based on the MaxLen entry in the field dictionary.
|
|
||||||
/// </summary>
|
|
||||||
Comb = 1 << 24,
|
|
||||||
/// <summary>
|
|
||||||
/// The value of the field is a rich text string.
|
|
||||||
/// </summary>
|
|
||||||
RichText = 1 << 25
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flags specifying various characteristics of a choice type field in an <see cref="AcroFieldBase"/>.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
internal enum AcroChoiceFieldFlags : uint
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The user may not change the value of the field.
|
|
||||||
/// </summary>
|
|
||||||
ReadOnly = 1 << 0,
|
|
||||||
/// <summary>
|
|
||||||
/// The field must have a value before the form can be submitted.
|
|
||||||
/// </summary>
|
|
||||||
Required = 1 << 1,
|
|
||||||
/// <summary>
|
|
||||||
/// Must not be exported by the submit form action.
|
|
||||||
/// </summary>
|
|
||||||
NoExport = 1 << 2,
|
|
||||||
/// <summary>
|
|
||||||
/// The field is a combo box.
|
|
||||||
/// </summary>
|
|
||||||
Combo = 1 << 17,
|
|
||||||
/// <summary>
|
|
||||||
/// The combo box includes an editable text box. <see cref="Combo"/> must be set.
|
|
||||||
/// </summary>
|
|
||||||
Edit = 1 << 18,
|
|
||||||
/// <summary>
|
|
||||||
/// The options should be sorted alphabetically, this should be ignored by viewer applications.
|
|
||||||
/// </summary>
|
|
||||||
Sort = 1 << 19,
|
|
||||||
/// <summary>
|
|
||||||
/// The field allows multiple options to be selected.
|
|
||||||
/// </summary>
|
|
||||||
MultiSelect = 1 << 21,
|
|
||||||
/// <summary>
|
|
||||||
/// The text entered in the field is not spell checked. <see cref="Combo"/> and <see cref="Edit"/> must be set.
|
|
||||||
/// </summary>
|
|
||||||
DoNotSpellCheck = 1 << 22,
|
|
||||||
/// <summary>
|
|
||||||
/// Any associated field action is fired when the selection is changed rather than on losing focus.
|
|
||||||
/// </summary>
|
|
||||||
CommitOnSelectionChange = 1 << 26
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information from the field dictionary which is common across all field types.
|
||||||
|
/// All of this information is optional.
|
||||||
|
/// </summary>
|
||||||
|
public class AcroFieldCommonInformation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The reference to the field which is the parent of this one, if applicable.
|
||||||
|
/// </summary>
|
||||||
|
public IndirectReference? Parent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The partial field name for this field. The fully qualified field name is the
|
||||||
|
/// period '.' joined name of all parents' partial names and this field's partial name.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public string PartialName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The alternate field name to be used instead of the fully qualified field name where
|
||||||
|
/// the field is being identified on the user interface or by screen readers.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public string AlternateName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The mapping name used when exporting form field data from the document.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public string MappingName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="AcroFieldCommonInformation"/>.
|
||||||
|
/// </summary>
|
||||||
|
public AcroFieldCommonInformation(IndirectReference? parent, string partialName, string alternateName, string mappingName)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
PartialName = partialName;
|
||||||
|
AlternateName = alternateName;
|
||||||
|
MappingName = mappingName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Parent: {Parent}. Partial: {PartialName}. Alternate: {AlternateName}. Mapping: {MappingName}.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs
Normal file
72
src/UglyToad.PdfPig/AcroForms/Fields/AcroListBoxField.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Tokens;
|
||||||
|
using Util.JetBrains.Annotations;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// A scrollable list box field.
|
||||||
|
/// </summary>
|
||||||
|
public class AcroListBoxField : AcroFieldBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The flags specifying the behaviour of this field.
|
||||||
|
/// </summary>
|
||||||
|
public AcroChoiceFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The options to be presented to the user.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<AcroChoiceOption> Options { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The names of any currently selected options.
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public IReadOnlyList<string> SelectedOptions { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For multiple select lists with duplicate names gives the indices of the selected options.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public IReadOnlyList<int> SelectedOptionIndices { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For scrollable list boxes gives the index of the first visible option.
|
||||||
|
/// </summary>
|
||||||
|
public int TopIndex { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the field allows multiple selections.
|
||||||
|
/// </summary>
|
||||||
|
public bool SupportsMultiSelect => Flags.Equals(AcroChoiceFieldFlags.MultiSelect);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="AcroListBoxField"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dictionary">The dictionary for this field.</param>
|
||||||
|
/// <param name="fieldType">The type of this field, must be <see cref="NameToken.Ch"/>.</param>
|
||||||
|
/// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
|
||||||
|
/// <param name="information">Additional information for this field.</param>
|
||||||
|
/// <param name="options">The options in this field.</param>
|
||||||
|
/// <param name="selectedOptionIndices">The indices of the selected options where there are multiple with the same name.</param>
|
||||||
|
/// <param name="topIndex">The first visible option index.</param>
|
||||||
|
/// <param name="selectedOptions">The names of the selected options.</param>
|
||||||
|
public AcroListBoxField(DictionaryToken dictionary, string fieldType, AcroChoiceFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information, IReadOnlyList<AcroChoiceOption> options,
|
||||||
|
IReadOnlyList<string> selectedOptions,
|
||||||
|
IReadOnlyList<int> selectedOptionIndices,
|
||||||
|
int? topIndex) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
SelectedOptions = selectedOptions ?? throw new ArgumentNullException(nameof(selectedOptions));
|
||||||
|
SelectedOptionIndices = selectedOptionIndices;
|
||||||
|
TopIndex = topIndex ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/UglyToad.PdfPig/AcroForms/Fields/AcroPushButtonField.cs
Normal file
16
src/UglyToad.PdfPig/AcroForms/Fields/AcroPushButtonField.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
internal class AcroPushButtonField : AcroFieldBase
|
||||||
|
{
|
||||||
|
public AcroButtonFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
public AcroPushButtonField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
internal class AcroRadioButtonsField : AcroFieldBase
|
||||||
|
{
|
||||||
|
public AcroButtonFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
public AcroRadioButtonsField(DictionaryToken dictionary, string fieldType, AcroButtonFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
src/UglyToad.PdfPig/AcroForms/Fields/AcroSignatureField.cs
Normal file
12
src/UglyToad.PdfPig/AcroForms/Fields/AcroSignatureField.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
internal class AcroSignatureField : AcroFieldBase
|
||||||
|
{
|
||||||
|
public AcroSignatureField(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information) :
|
||||||
|
base(dictionary, fieldType, fieldFlags, information)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs
Normal file
65
src/UglyToad.PdfPig/AcroForms/Fields/AcroTextField.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// A text field is a box or space in which the user can enter text from the keyboard.
|
||||||
|
/// The text may be restricted to a single line or may be permitted to span multiple lines.
|
||||||
|
/// </summary>
|
||||||
|
internal class AcroTextField : AcroFieldBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The flags specifying the behaviour of this field.
|
||||||
|
/// </summary>
|
||||||
|
public AcroTextFieldFlags Flags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the text in this text field.
|
||||||
|
/// This can be <see langword="null"/> if no value has been set.
|
||||||
|
/// </summary>
|
||||||
|
public string Value { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The optional maximum length of the text field.
|
||||||
|
/// </summary>
|
||||||
|
public int? MaxLength { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the field supports rich text content.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRichText { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the field allows multiline text.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsMultiline { get;}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="T:UglyToad.PdfPig.AcroForms.Fields.AcroTextField" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dictionary">The dictionary for this field.</param>
|
||||||
|
/// <param name="fieldType">The type of this field, must be <see cref="F:UglyToad.PdfPig.Tokens.NameToken.Ch" />.</param>
|
||||||
|
/// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
|
||||||
|
/// <param name="information">Additional information for this field.</param>
|
||||||
|
/// <param name="value">The text value.</param>
|
||||||
|
/// <param name="maxLength">The maximum length.</param>
|
||||||
|
public AcroTextField(DictionaryToken dictionary, string fieldType, AcroTextFieldFlags fieldFlags,
|
||||||
|
AcroFieldCommonInformation information, string value, int? maxLength) :
|
||||||
|
base(dictionary, fieldType, (uint)fieldFlags, information)
|
||||||
|
{
|
||||||
|
Flags = fieldFlags;
|
||||||
|
Value = value;
|
||||||
|
MaxLength = maxLength;
|
||||||
|
IsRichText = Flags.HasFlag(AcroTextFieldFlags.RichText);
|
||||||
|
IsMultiline = Flags.HasFlag(AcroTextFieldFlags.Multiline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
src/UglyToad.PdfPig/AcroForms/Fields/AcroTextFieldFlags.cs
Normal file
53
src/UglyToad.PdfPig/AcroForms/Fields/AcroTextFieldFlags.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags specifying various characteristics of a text type field in an <see cref="AcroFieldBase"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AcroTextFieldFlags : uint
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The user may not change the value of the field.
|
||||||
|
/// </summary>
|
||||||
|
ReadOnly = 1 << 0,
|
||||||
|
/// <summary>
|
||||||
|
/// The field must have a value before the form can be submitted.
|
||||||
|
/// </summary>
|
||||||
|
Required = 1 << 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Must not be exported by the submit form action.
|
||||||
|
/// </summary>
|
||||||
|
NoExport = 1 << 2,
|
||||||
|
/// <summary>
|
||||||
|
/// The field can contain multiple lines of text.
|
||||||
|
/// </summary>
|
||||||
|
Multiline = 1 << 12,
|
||||||
|
/// <summary>
|
||||||
|
/// The field is for a password and should not be displayed as text and should not be stored to file.
|
||||||
|
/// </summary>
|
||||||
|
Password = 1 << 13,
|
||||||
|
/// <summary>
|
||||||
|
/// The field represents a file path selection.
|
||||||
|
/// </summary>
|
||||||
|
FileSelect = 1 << 20,
|
||||||
|
/// <summary>
|
||||||
|
/// The text entered is not spell checked.
|
||||||
|
/// </summary>
|
||||||
|
DoNotSpellCheck = 1 << 22,
|
||||||
|
/// <summary>
|
||||||
|
/// The field does not scroll if the text exceeds the bounds of the field.
|
||||||
|
/// </summary>
|
||||||
|
DoNotScroll = 1 << 23,
|
||||||
|
/// <summary>
|
||||||
|
/// For a text field which is not a <see cref="Password"/>, <see cref="Multiline"/> or <see cref="FileSelect"/>
|
||||||
|
/// the field text is evenly spaced by splitting into 'combs' based on the MaxLen entry in the field dictionary.
|
||||||
|
/// </summary>
|
||||||
|
Comb = 1 << 24,
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the field is a rich text string.
|
||||||
|
/// </summary>
|
||||||
|
RichText = 1 << 25
|
||||||
|
}
|
||||||
|
}
|
21
src/UglyToad.PdfPig/AcroForms/Fields/NonTerminalAcroField.cs
Normal file
21
src/UglyToad.PdfPig/AcroForms/Fields/NonTerminalAcroField.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace UglyToad.PdfPig.AcroForms.Fields
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Tokens;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A non-leaf field in the form's structure.
|
||||||
|
/// </summary>
|
||||||
|
internal class NonTerminalAcroField : AcroFieldBase
|
||||||
|
{
|
||||||
|
public IReadOnlyList<AcroFieldBase> Children { get; }
|
||||||
|
|
||||||
|
public NonTerminalAcroField(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information,
|
||||||
|
IReadOnlyList<AcroFieldBase> children) :
|
||||||
|
base(dictionary, fieldType, fieldFlags, information)
|
||||||
|
{
|
||||||
|
Children = children ?? throw new ArgumentNullException(nameof(children));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user