Migrated all previous cap methods to new CapabilityControl.

This commit is contained in:
soukoku 2014-09-17 19:33:18 -04:00
parent 8508bbb764
commit 450f8aa5b0
2 changed files with 251 additions and 189 deletions

View File

@ -13,29 +13,69 @@ namespace NTwain
public class CapabilityControl<TValue> public class CapabilityControl<TValue>
{ {
DataSource _source; DataSource _source;
Func<object, TValue> _converter; Func<object, TValue> _convertRoutine;
Func<TValue, TWCapability> _setProvider; Func<TValue, ReturnCode> _setCustomRoutine;
Func<TValue, TWCapability> _setProvider; // an simplified way to set() that only needs on cap value
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CapabilityControl"/> class. /// Initializes a new instance of the <see cref="CapabilityControl{TValue}" /> class.
/// </summary> /// </summary>
/// <param name="source">The source.</param> /// <param name="source">The source.</param>
/// <param name="capability">The capability.</param> /// <param name="capability">The capability.</param>
/// <param name="valueConversionRoutine">The value conversion routine.</param> /// <param name="getConversionRoutine">The value conversion routine in Get methods.</param>
/// <param name="setCapProvider">Callback to provide the capability object for set method.</param> /// <param name="setValueProvider">Callback to provide the capability object for set method.</param>
/// <exception cref="System.ArgumentNullException">source</exception> /// <exception cref="System.ArgumentNullException">
public CapabilityControl(DataSource source, CapabilityId capability, Func<object, TValue> valueConversionRoutine, Func<TValue, TWCapability> setCapProvider) /// source
/// or
/// valueConversionRoutine
/// or
/// setValueProvider
/// </exception>
public CapabilityControl(DataSource source, CapabilityId capability,
Func<object, TValue> getConversionRoutine,
Func<TValue, TWCapability> setValueProvider)
{ {
if (source == null) { throw new ArgumentNullException("source"); } if (source == null) { throw new ArgumentNullException("source"); }
if (valueConversionRoutine == null) { throw new ArgumentNullException("valueConversionRoutine"); } if (getConversionRoutine == null) { throw new ArgumentNullException("valueConversionRoutine"); }
if (setValueProvider == null) { throw new ArgumentNullException("setValueProvider"); }
_source = source; _source = source;
_converter = valueConversionRoutine; _convertRoutine = getConversionRoutine;
_setProvider = setCapProvider; _setProvider = setValueProvider;
Capability = capability; Capability = capability;
SupportedActions = source.CapQuerySupport(capability); SupportedActions = source.CapQuerySupport(capability);
} }
/// <summary>
/// Initializes a new instance of the <see cref="CapabilityControl{TValue}" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="capability">The capability.</param>
/// <param name="getConversionRoutine">The value conversion routine in Get methods.</param>
/// <param name="setValueRoutine">Callback to perform set value.</param>
/// <exception cref="System.ArgumentNullException">
/// source
/// or
/// valueConversionRoutine
/// or
/// setValueRoutine
/// </exception>
public CapabilityControl(DataSource source, CapabilityId capability,
Func<object, TValue> getConversionRoutine,
Func<TValue, ReturnCode> setValueRoutine)
{
if (source == null) { throw new ArgumentNullException("source"); }
if (getConversionRoutine == null) { throw new ArgumentNullException("valueConversionRoutine"); }
if (setValueRoutine == null) { throw new ArgumentNullException("setValueRoutine"); }
_source = source;
_convertRoutine = getConversionRoutine;
_setCustomRoutine = setValueRoutine;
Capability = capability;
SupportedActions = source.CapQuerySupport(capability);
}
bool Supports(QuerySupports flag) bool Supports(QuerySupports flag)
{ {
return (SupportedActions & flag) == flag; return (SupportedActions & flag) == flag;
@ -59,16 +99,85 @@ namespace NTwain
/// </value> /// </value>
public QuerySupports SupportedActions { get; private set; } public QuerySupports SupportedActions { get; private set; }
/// <summary>
/// Gets a value indicating whether this capability is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability is supported; otherwise, <c>false</c>.
/// </value>
public bool IsSupported { get { return SupportedActions > QuerySupports.None; } } public bool IsSupported { get { return SupportedActions > QuerySupports.None; } }
/// <summary>
/// Gets a value indicating whether <see cref="Get"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get values; otherwise, <c>false</c>.
/// </value>
public bool CanGet { get { return Supports(QuerySupports.Get); } } public bool CanGet { get { return Supports(QuerySupports.Get); } }
/// <summary>
/// Gets a value indicating whether <see cref="GetDefault"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get default value; otherwise, <c>false</c>.
/// </value>
public bool CanGetDefault { get { return Supports(QuerySupports.GetDefault); } } public bool CanGetDefault { get { return Supports(QuerySupports.GetDefault); } }
/// <summary>
/// Gets a value indicating whether <see cref="GetCurrent"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get current value; otherwise, <c>false</c>.
/// </value>
public bool CanGetCurrent { get { return Supports(QuerySupports.GetCurrent); } } public bool CanGetCurrent { get { return Supports(QuerySupports.GetCurrent); } }
/// <summary>
/// Gets a value indicating whether <see cref="GetLabel"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get label; otherwise, <c>false</c>.
/// </value>
public bool CanGetLabel { get { return Supports(QuerySupports.GetLabel); } } public bool CanGetLabel { get { return Supports(QuerySupports.GetLabel); } }
/// <summary>
/// Gets a value indicating whether <see cref="GetHelp"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get help; otherwise, <c>false</c>.
/// </value>
public bool CanGetHelp { get { return Supports(QuerySupports.GetHelp); } } public bool CanGetHelp { get { return Supports(QuerySupports.GetHelp); } }
/// <summary>
/// Gets a value indicating whether <see cref="GetLabelEnum"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can get label enum; otherwise, <c>false</c>.
/// </value>
public bool CanGetLabelEnum { get { return Supports(QuerySupports.GetLabelEnum); } } public bool CanGetLabelEnum { get { return Supports(QuerySupports.GetLabelEnum); } }
/// <summary>
/// Gets a value indicating whether <see cref="Reset"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can reset; otherwise, <c>false</c>.
/// </value>
public bool CanReset { get { return Supports(QuerySupports.Reset); } } public bool CanReset { get { return Supports(QuerySupports.Reset); } }
/// <summary>
/// Gets a value indicating whether <see cref="Set"/> is supported.
/// </summary>
/// <value>
/// <c>true</c> if this capability can set; otherwise, <c>false</c>.
/// </value>
public bool CanSet { get { return Supports(QuerySupports.Set); } } public bool CanSet { get { return Supports(QuerySupports.Set); } }
public bool CanSetConstraint { get { return Supports(QuerySupports.SetConstraint); } }
///// <summary>
///// Gets a value indicating whether <see cref="SetConstraint"/> is supported.
///// </summary>
///// <value>
///// <c>true</c> if this capability can set constraint; otherwise, <c>false</c>.
///// </value>
//public bool CanSetConstraint { get { return Supports(QuerySupports.SetConstraint); } }
#endregion #endregion
@ -82,7 +191,7 @@ namespace NTwain
{ {
if (CanGetDefault) if (CanGetDefault)
{ {
return _converter(_source.CapGetDefault(Capability)); return _convertRoutine(_source.CapGetDefault(Capability));
} }
return default(TValue); return default(TValue);
} }
@ -95,7 +204,7 @@ namespace NTwain
{ {
if (CanGetCurrent) if (CanGetCurrent)
{ {
return _converter(_source.CapGetCurrent(Capability)); return _convertRoutine(_source.CapGetCurrent(Capability));
} }
return default(TValue); return default(TValue);
} }
@ -108,7 +217,7 @@ namespace NTwain
{ {
if (CanGet) if (CanGet)
{ {
return _source.CapGet(Capability).Select(o => _converter(o)).ToList(); return _source.CapGet(Capability).Select(o => _convertRoutine(o)).ToList();
} }
return new List<TValue>(); return new List<TValue>();
} }
@ -222,11 +331,18 @@ namespace NTwain
public ReturnCode Set(TValue value) public ReturnCode Set(TValue value)
{ {
ReturnCode rc = ReturnCode.Failure; ReturnCode rc = ReturnCode.Failure;
if (CanSet && _setProvider != null) if (CanSet)
{ {
using (var cap = _setProvider(value)) if (_setCustomRoutine != null)
{ {
rc = _source.DGControl.Capability.Set(cap); rc = _setCustomRoutine(value);
}
else if (_setProvider != null)
{
using (var cap = _setProvider(value))
{
rc = _source.DGControl.Capability.Set(cap);
}
} }
} }
return rc; return rc;
@ -234,12 +350,5 @@ namespace NTwain
#endregion #endregion
public enum SetStrategy
{
Once,
Cascade,
Custom
}
} }
} }

View File

@ -170,7 +170,7 @@ namespace NTwain
#endregion #endregion
#region high-level caps #region frequently used high-level caps stuff
#region audio caps #region audio caps
@ -348,25 +348,11 @@ namespace NTwain
if (_autoDeskew == null) if (_autoDeskew == null)
{ {
_autoDeskew = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticDeskew, ValueExtensions.ConvertToEnum<BoolType>, value => _autoDeskew = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticDeskew, ValueExtensions.ConvertToEnum<BoolType>, value =>
{ new TWCapability(CapabilityId.ICapAutomaticRotate, new TWOneValue
if (Identity.ProtocolMajor >= 2)
{ {
// if using twain 2.0 will need to use enum instead of onevalue (yuck) Item = (uint)value,
TWEnumeration en = new TWEnumeration(); ItemType = ItemType.Bool
en.ItemList = new object[] { (uint)value }; }));
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticDeskew, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticDeskew, one);
}
});
} }
return _autoDeskew; return _autoDeskew;
} }
@ -388,25 +374,11 @@ namespace NTwain
if (_autoRotate == null) if (_autoRotate == null)
{ {
_autoRotate = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticRotate, ValueExtensions.ConvertToEnum<BoolType>, value => _autoRotate = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticRotate, ValueExtensions.ConvertToEnum<BoolType>, value =>
{ new TWCapability(CapabilityId.ICapAutomaticRotate, new TWOneValue
if (Identity.ProtocolMajor >= 2)
{ {
// if using twain 2.0 will need to use enum instead of onevalue (yuck) Item = (uint)value,
TWEnumeration en = new TWEnumeration(); ItemType = ItemType.Bool
en.ItemList = new object[] { (uint)value }; }));
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticRotate, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.ICapAutomaticRotate, one);
}
});
} }
return _autoRotate; return _autoRotate;
} }
@ -464,6 +436,47 @@ namespace NTwain
} }
} }
private CapabilityControl<BoolType> _borderDetect;
/// <summary>
/// Gets the property to work with auto border detection flag for the current source.
/// </summary>
/// <value>
/// The auto border detection flag.
/// </value>
public CapabilityControl<BoolType> CapImageAutomaticBorderDetection
{
get
{
if (_borderDetect == null)
{
_borderDetect = new CapabilityControl<BoolType>(this, CapabilityId.ICapAutomaticBorderDetection, ValueExtensions.ConvertToEnum<BoolType>, value =>
{
var rc = ReturnCode.Failure;
var one = new TWOneValue
{
Item = (uint)value,
ItemType = ItemType.Bool
};
using (TWCapability capValue = new TWCapability(CapabilityId.ICapUndefinedImageSize, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
using (TWCapability capValue = new TWCapability(CapabilityId.ICapAutomaticBorderDetection, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
return rc;
});
}
return _borderDetect;
}
}
#endregion #endregion
#region other caps #region other caps
@ -483,164 +496,104 @@ namespace NTwain
if (_duplexEnabled == null) if (_duplexEnabled == null)
{ {
_duplexEnabled = new CapabilityControl<BoolType>(this, CapabilityId.CapDuplexEnabled, ValueExtensions.ConvertToEnum<BoolType>, value => _duplexEnabled = new CapabilityControl<BoolType>(this, CapabilityId.CapDuplexEnabled, ValueExtensions.ConvertToEnum<BoolType>, value =>
{ new TWCapability(CapabilityId.CapDuplexEnabled, new TWOneValue
if (Identity.ProtocolMajor >= 2)
{ {
// if using twain 2.0 will need to use enum instead of onevalue (yuck) Item = (uint)value,
TWEnumeration en = new TWEnumeration(); ItemType = ItemType.Bool
en.ItemList = new object[] { (uint)value }; }));
en.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.CapDuplexEnabled, en);
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)value;
one.ItemType = ItemType.Bool;
return new TWCapability(CapabilityId.CapDuplexEnabled, one);
}
});
} }
return _duplexEnabled; return _duplexEnabled;
} }
} }
#endregion
#endregion
#region onesie flags
private CapabilityControl<int> _xferCount;
/// <summary> /// <summary>
/// Change the auto border detection flag for the current source. /// Gets the property to work with xfer count for the current source.
/// </summary> /// </summary>
/// <param name="useIt">if set to <c>true</c> use it.</param> /// <value>
/// <returns></returns> /// The xfer count.
public ReturnCode CapSetBorderDetection(bool useIt) /// </value>
public CapabilityControl<int> CapXferCount
{ {
var rc = ReturnCode.Failure; get
if (SupportedCaps.Contains(CapabilityId.ICapAutomaticBorderDetection))
{ {
// this goes along with undefinedimagesize so that also if (_xferCount == null)
// needs to be set
if (Identity.ProtocolMajor >= 2)
{ {
// if using twain 2.0 will need to use enum instead of onevalue (yuck) _xferCount = new CapabilityControl<int>(this, CapabilityId.CapXferCount, ValueExtensions.ConvertToEnum<int>, value =>
TWEnumeration en = new TWEnumeration(); new TWCapability(CapabilityId.CapXferCount, new TWOneValue
en.ItemList = new object[] { (uint)(useIt ? 1 : 0) }; {
en.ItemType = ItemType.Bool; Item = value > 0 ? (uint)value : uint.MaxValue,
ItemType = ItemType.UInt16
using (TWCapability dx = new TWCapability(CapabilityId.ICapUndefinedImageSize, en)) }));
{
rc = _session.DGControl.Capability.Set(dx);
}
using (TWCapability dx = new TWCapability(CapabilityId.ICapAutomaticBorderDetection, en))
{
rc = _session.DGControl.Capability.Set(dx);
}
}
else
{
TWOneValue one = new TWOneValue();
one.Item = (uint)(useIt ? 1 : 0);
one.ItemType = ItemType.Bool;
using (TWCapability capValue = new TWCapability(CapabilityId.ICapUndefinedImageSize, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
using (TWCapability capValue = new TWCapability(CapabilityId.ICapAutomaticBorderDetection, one))
{
rc = _session.DGControl.Capability.Set(capValue);
}
} }
return _xferCount;
} }
return rc;
} }
private CapabilityControl<BoolType> _feederEnabled;
/// <summary> /// <summary>
/// Change the use feeder flag for the current source. /// Gets the property to work with feeder enabled flag for the current source.
/// </summary> /// </summary>
/// <param name="useIt">if set to <c>true</c> use it.</param> /// <value>
/// <returns></returns> /// The feeder enabled flag.
public ReturnCode CapSetFeeder(bool useIt) /// </value>
public CapabilityControl<BoolType> CapFeederEnabled
{ {
var rc = ReturnCode.Failure; get
if (SupportedCaps.Contains(CapabilityId.CapFeederEnabled))
{ {
if (Identity.ProtocolMajor >= 2) if (_feederEnabled == null)
{ {
// if using twain 2.0 will need to use enum instead of onevalue (yuck) _feederEnabled = new CapabilityControl<BoolType>(this, CapabilityId.CapFeederEnabled, ValueExtensions.ConvertToEnum<BoolType>, value =>
TWEnumeration en = new TWEnumeration();
en.ItemList = new object[] { (ushort)(useIt ? 1 : 0) };
en.ItemType = ItemType.Bool;
// we will never set feeder off, only autofeed and autoscan
// but if it is to SET then enable feeder needs to be set first
if (useIt)
{ {
using (TWCapability dx = new TWCapability(CapabilityId.CapFeederEnabled, en)) var rc = ReturnCode.Failure;
{
rc = _session.DGControl.Capability.Set(dx);
}
}
// to really use feeder we must also set autofeed or autoscan, but only var one = new TWOneValue
// for one of them since setting autoscan also sets autofeed
if (SupportedCaps.Contains(CapabilityId.CapAutoScan))
{
using (TWCapability dx = new TWCapability(CapabilityId.CapAutoScan, en))
{ {
rc = _session.DGControl.Capability.Set(dx); Item = (uint)value,
} ItemType = ItemType.Bool
} };
else if (SupportedCaps.Contains(CapabilityId.CapAutoFeed))
{ // we will never set feeder off, only autofeed and autoscan
using (TWCapability dx = new TWCapability(CapabilityId.CapAutoFeed, en)) // but if it is true then enable feeder needs to be set first
if (value == BoolType.True)
{ {
rc = _session.DGControl.Capability.Set(dx); using (TWCapability enabled = new TWCapability(CapabilityId.CapFeederEnabled, one))
{
rc = _session.DGControl.Capability.Set(enabled);
}
} }
} // to really use feeder we must also set autofeed or autoscan, but only
} // for one of them since setting autoscan also sets autofeed
else if (SupportedCaps.Contains(CapabilityId.CapAutoScan))
{ {
TWOneValue one = new TWOneValue(); using (TWCapability autoScan = new TWCapability(CapabilityId.CapAutoScan, one))
one.Item = (uint)(useIt ? 1 : 0); {
one.ItemType = ItemType.Bool; rc = _session.DGControl.Capability.Set(autoScan);
}
if (useIt) }
{ else if (SupportedCaps.Contains(CapabilityId.CapAutoFeed))
using (TWCapability enabled = new TWCapability(CapabilityId.CapFeederEnabled, one)) {
{ using (TWCapability autoScan = new TWCapability(CapabilityId.CapAutoFeed, one))
rc = _session.DGControl.Capability.Set(enabled); {
} rc = _session.DGControl.Capability.Set(autoScan);
} }
// to really use feeder we must also set autofeed or autoscan, but only }
// for one of them since setting autoscan also sets autofeed
if (SupportedCaps.Contains(CapabilityId.CapAutoScan)) return rc;
{ });
using (TWCapability autoScan = new TWCapability(CapabilityId.CapAutoScan, one))
{
rc = _session.DGControl.Capability.Set(autoScan);
}
}
else if (SupportedCaps.Contains(CapabilityId.CapAutoFeed))
{
using (TWCapability autoScan = new TWCapability(CapabilityId.CapAutoFeed, one))
{
rc = _session.DGControl.Capability.Set(autoScan);
}
}
} }
return _feederEnabled;
} }
return rc;
} }
#endregion #endregion
#endregion
} }
} }