mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-22 03:02:35 +01:00
Merge pull request #7931 from Flitskikker/feature/btc-improvements-20240205
Some "Beautify time codes" improvements
This commit is contained in:
commit
386a1047ab
@ -2979,15 +2979,19 @@ $HorzAlign = Center
|
||||
public int ChainingGeneralMaxGap { get; set; }
|
||||
public int ChainingGeneralLeftGreenZone { get; set; }
|
||||
public int ChainingGeneralLeftRedZone { get; set; }
|
||||
public ChainingGeneralShotChangeBehaviorEnum ChainingGeneralShotChangeBehavior { get; set; }
|
||||
public ChainingShotChangeBehaviorEnum ChainingGeneralShotChangeBehavior { get; set; }
|
||||
public bool ChainingInCueOnShotUseZones { get; set; }
|
||||
public int ChainingInCueOnShotMaxGap { get; set; }
|
||||
public int ChainingInCueOnShotLeftGreenZone { get; set; }
|
||||
public int ChainingInCueOnShotLeftRedZone { get; set; }
|
||||
public ChainingShotChangeBehaviorEnum ChainingInCueOnShotShotChangeBehavior { get; set; }
|
||||
public bool ChainingInCueOnShotCheckGeneral { get; set; }
|
||||
public bool ChainingOutCueOnShotUseZones { get; set; }
|
||||
public int ChainingOutCueOnShotMaxGap { get; set; }
|
||||
public int ChainingOutCueOnShotRightRedZone { get; set; }
|
||||
public int ChainingOutCueOnShotRightGreenZone { get; set; }
|
||||
public ChainingShotChangeBehaviorEnum ChainingOutCueOnShotShotChangeBehavior { get; set; }
|
||||
public bool ChainingOutCueOnShotCheckGeneral { get; set; }
|
||||
|
||||
public enum Preset : int
|
||||
{
|
||||
@ -2996,7 +3000,7 @@ $HorzAlign = Center
|
||||
SDI = 2,
|
||||
}
|
||||
|
||||
public enum ChainingGeneralShotChangeBehaviorEnum : int
|
||||
public enum ChainingShotChangeBehaviorEnum : int
|
||||
{
|
||||
DontChain = 0,
|
||||
ExtendCrossingShotChange = 1,
|
||||
@ -3036,15 +3040,19 @@ $HorzAlign = Center
|
||||
ChainingGeneralMaxGap = 500;
|
||||
ChainingGeneralLeftGreenZone = 12;
|
||||
ChainingGeneralLeftRedZone = 11;
|
||||
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingGeneralShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingInCueOnShotUseZones = false;
|
||||
ChainingInCueOnShotMaxGap = 500;
|
||||
ChainingInCueOnShotLeftGreenZone = 12;
|
||||
ChainingInCueOnShotLeftRedZone = 11;
|
||||
ChainingInCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingInCueOnShotCheckGeneral = true;
|
||||
ChainingOutCueOnShotUseZones = false;
|
||||
ChainingOutCueOnShotMaxGap = 500;
|
||||
ChainingOutCueOnShotRightRedZone = 11;
|
||||
ChainingOutCueOnShotRightGreenZone = 12;
|
||||
ChainingOutCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingOutCueOnShotCheckGeneral = true;
|
||||
break;
|
||||
case Preset.SDI:
|
||||
Gap = 4;
|
||||
@ -3075,15 +3083,19 @@ $HorzAlign = Center
|
||||
ChainingGeneralMaxGap = 1000;
|
||||
ChainingGeneralLeftGreenZone = 25;
|
||||
ChainingGeneralLeftRedZone = 24;
|
||||
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendCrossingShotChange;
|
||||
ChainingGeneralShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange;
|
||||
ChainingInCueOnShotUseZones = false;
|
||||
ChainingInCueOnShotMaxGap = 1000;
|
||||
ChainingInCueOnShotLeftGreenZone = 25;
|
||||
ChainingInCueOnShotLeftRedZone = 24;
|
||||
ChainingOutCueOnShotUseZones = false;
|
||||
ChainingOutCueOnShotMaxGap = 1000;
|
||||
ChainingOutCueOnShotRightRedZone = 24;
|
||||
ChainingOutCueOnShotRightGreenZone = 25;
|
||||
ChainingInCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange;
|
||||
ChainingInCueOnShotCheckGeneral = true;
|
||||
ChainingOutCueOnShotUseZones = true;
|
||||
ChainingOutCueOnShotMaxGap = 500;
|
||||
ChainingOutCueOnShotRightRedZone = 7;
|
||||
ChainingOutCueOnShotRightGreenZone = 12;
|
||||
ChainingOutCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange;
|
||||
ChainingOutCueOnShotCheckGeneral = true;
|
||||
break;
|
||||
default:
|
||||
Gap = 3;
|
||||
@ -3114,15 +3126,19 @@ $HorzAlign = Center
|
||||
ChainingGeneralMaxGap = 1000;
|
||||
ChainingGeneralLeftGreenZone = 25;
|
||||
ChainingGeneralLeftRedZone = 24;
|
||||
ChainingGeneralShotChangeBehavior = ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingGeneralShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingInCueOnShotUseZones = false;
|
||||
ChainingInCueOnShotMaxGap = 1000;
|
||||
ChainingInCueOnShotLeftGreenZone = 25;
|
||||
ChainingInCueOnShotLeftRedZone = 24;
|
||||
ChainingInCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingInCueOnShotCheckGeneral = true;
|
||||
ChainingOutCueOnShotUseZones = false;
|
||||
ChainingOutCueOnShotMaxGap = 500;
|
||||
ChainingOutCueOnShotRightRedZone = 11;
|
||||
ChainingOutCueOnShotRightGreenZone = 12;
|
||||
ChainingOutCueOnShotShotChangeBehavior = ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
ChainingOutCueOnShotCheckGeneral = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -8961,7 +8977,7 @@ $HorzAlign = Center
|
||||
subNode = profileNode.SelectSingleNode("ChainingGeneralShotChangeBehavior");
|
||||
if (subNode != null)
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum)Enum.Parse(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum), subNode.InnerText);
|
||||
settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum)Enum.Parse(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum), subNode.InnerText);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotUseZones");
|
||||
@ -8988,6 +9004,18 @@ $HorzAlign = Center
|
||||
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotShotChangeBehavior");
|
||||
if (subNode != null)
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum)Enum.Parse(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum), subNode.InnerText);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingInCueOnShotCheckGeneral");
|
||||
if (subNode != null)
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotCheckGeneral = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotUseZones");
|
||||
if (subNode != null)
|
||||
{
|
||||
@ -9011,6 +9039,18 @@ $HorzAlign = Center
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotShotChangeBehavior");
|
||||
if (subNode != null)
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum)Enum.Parse(typeof(BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum), subNode.InnerText);
|
||||
}
|
||||
|
||||
subNode = profileNode.SelectSingleNode("ChainingOutCueOnShotCheckGeneral");
|
||||
if (subNode != null)
|
||||
{
|
||||
settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotCheckGeneral = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12436,10 +12476,14 @@ $HorzAlign = Center
|
||||
textWriter.WriteElementString("ChainingInCueOnShotMaxGap", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingInCueOnShotLeftGreenZone", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingInCueOnShotLeftRedZone", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingInCueOnShotShotChangeBehavior", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotShotChangeBehavior.ToString());
|
||||
textWriter.WriteElementString("ChainingInCueOnShotCheckGeneral", settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotCheckGeneral.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotUseZones", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotMaxGap", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotRightRedZone", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotRightGreenZone", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotShotChangeBehavior", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotShotChangeBehavior.ToString());
|
||||
textWriter.WriteElementString("ChainingOutCueOnShotCheckGeneral", settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotCheckGeneral.ToString(CultureInfo.InvariantCulture));
|
||||
textWriter.WriteEndElement();
|
||||
textWriter.WriteEndElement();
|
||||
|
||||
|
@ -518,6 +518,8 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
var isLeftOutCueOnShotChange = IsCueOnShotChange(bestLeftOutCueFrame, false);
|
||||
var isRightInCueOnShotChange = IsCueOnShotChange(bestRightInCueFrame, true);
|
||||
|
||||
var performGeneralChaining = false;
|
||||
|
||||
if (isRightInCueOnShotChange)
|
||||
{
|
||||
// The right in cue is on a shot change
|
||||
@ -525,40 +527,121 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
var fixedLeftOutCueFrame = GetFixedChainableSubtitlesLeftOutCueFrameInCueOnShot(bestLeftOutCueFrame, bestRightInCueFrame);
|
||||
if (fixedLeftOutCueFrame != null)
|
||||
{
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
// Check if there are any other shot changes *before* the shot change we want to chain towards
|
||||
var firstShotChangeInBetween = GetFirstShotChangeFrameInBetween(bestLeftOutCueFrame, bestRightInCueFrame);
|
||||
if (firstShotChangeInBetween != null && !IsCueOnShotChange(bestRightInCueFrame, true, firstShotChangeInBetween.Value)) {
|
||||
// There is another shot change in between. Check behaviors
|
||||
switch (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotShotChangeBehavior)
|
||||
{
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.DontChain:
|
||||
// Don't do anything
|
||||
return false;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange:
|
||||
// Apply the chaining
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
break;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendUntilShotChange:
|
||||
// Put the left out cue on the shot change, minus gap
|
||||
newLeftOutCueFrame = firstShotChangeInBetween.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No shot changes in between, just apply the chaining
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chaining wasn't needed
|
||||
return false;
|
||||
// If set, we will still check the general rules
|
||||
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotCheckGeneral)
|
||||
{
|
||||
performGeneralChaining = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chaining wasn't needed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isLeftOutCueOnShotChange)
|
||||
{
|
||||
// The left out cue in on a shot change
|
||||
// The left out cue is on a shot change
|
||||
// Try to chain the subtitles
|
||||
var fixedRightInCueFrame = GetFixedChainableSubtitlesRightInCueFrameOutCueOnShot(bestLeftOutCueFrame, bestRightInCueFrame);
|
||||
if (fixedRightInCueFrame != null)
|
||||
{
|
||||
newLeftOutCueFrame = bestLeftOutCueFrame;
|
||||
newRightInCueFrame = fixedRightInCueFrame.Value;
|
||||
// Check if there are any other shot changes *after* the shot change we want to chain towards
|
||||
var lastShotChangeInBetween = GetLastShotChangeFrameInBetween(bestLeftOutCueFrame, bestRightInCueFrame);
|
||||
if (lastShotChangeInBetween != null && !IsCueOnShotChange(bestLeftOutCueFrame, false, lastShotChangeInBetween.Value))
|
||||
{
|
||||
// There is another shot change in between. Check behaviors
|
||||
switch (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotShotChangeBehavior)
|
||||
{
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.DontChain:
|
||||
// Don't do anything
|
||||
return false;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange:
|
||||
// Apply the chaining
|
||||
newLeftOutCueFrame = bestLeftOutCueFrame;
|
||||
newRightInCueFrame = fixedRightInCueFrame.Value;
|
||||
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
break;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendUntilShotChange:
|
||||
// Put the right in cue on the shot change, plus gap
|
||||
newLeftOutCueFrame = bestLeftOutCueFrame;
|
||||
newRightInCueFrame = lastShotChangeInBetween.Value + Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No shot changes in between, just apply the chaining
|
||||
newLeftOutCueFrame = bestLeftOutCueFrame;
|
||||
newRightInCueFrame = fixedRightInCueFrame.Value;
|
||||
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chaining wasn't needed
|
||||
return false;
|
||||
// If set, we will still check the general rules
|
||||
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotCheckGeneral)
|
||||
{
|
||||
performGeneralChaining = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chaining wasn't needed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The cues are not on shot changes
|
||||
// So, perform general chaining
|
||||
performGeneralChaining = true;
|
||||
}
|
||||
|
||||
if (performGeneralChaining)
|
||||
{
|
||||
// Try to chain the subtitles already, maybe chaining is not needed
|
||||
var fixedLeftOutCueFrame = GetFixedChainableSubtitlesLeftOutCueFrameGeneral(bestLeftOutCueFrame, bestRightInCueFrame);
|
||||
if (fixedLeftOutCueFrame != null)
|
||||
@ -570,18 +653,28 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
// There are shot changes in between. Check behaviors
|
||||
switch (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior)
|
||||
{
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.DontChain:
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.DontChain:
|
||||
// Don't do anything
|
||||
return false;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendCrossingShotChange:
|
||||
// Apply the chaining
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendCrossingShotChange:
|
||||
// Check if the right in cue was moved forward
|
||||
if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
|
||||
{
|
||||
// Yes, then we'll want to use the original position instead: after chaining, the connected subtitles might partially end up in a red zone,
|
||||
// leading to both being snapped to a shot change before (moving backward). Consequently, only the left out cue needs to be changed.
|
||||
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply the chaining normally
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
}
|
||||
|
||||
// Make sure the newly connected subtitles get fixed
|
||||
shouldFixConnectedSubtitles = true;
|
||||
break;
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange:
|
||||
case BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendUntilShotChange:
|
||||
// Put the left out cue on the shot change, minus gap
|
||||
newLeftOutCueFrame = firstShotChangeInBetween.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
@ -590,7 +683,7 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply the chaining
|
||||
// No shot changes in between, just apply the chaining
|
||||
newLeftOutCueFrame = fixedLeftOutCueFrame.Value;
|
||||
newRightInCueFrame = bestRightInCueFrame;
|
||||
}
|
||||
@ -731,7 +824,7 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
{
|
||||
var leftOutCueWithGreenZone = leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone;
|
||||
var isInGreenZone = rightInCueFrame < leftOutCueWithGreenZone && rightInCueFrame > (leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone);
|
||||
var isInRedZone = rightInCueFrame <= (leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone) && rightInCueFrame >= leftOutCueFrame;
|
||||
var isInRedZone = rightInCueFrame <= (leftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone) && rightInCueFrame >= leftOutCueFrame;
|
||||
|
||||
if (isInRedZone)
|
||||
{
|
||||
@ -1026,14 +1119,7 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
var closestShotChangeFrame = GetClosestShotChangeFrame(cueFrame);
|
||||
if (closestShotChangeFrame != null)
|
||||
{
|
||||
if (isInCue)
|
||||
{
|
||||
return cueFrame >= closestShotChangeFrame.Value && cueFrame <= closestShotChangeFrame.Value + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
|
||||
}
|
||||
else
|
||||
{
|
||||
return cueFrame <= closestShotChangeFrame.Value && cueFrame >= closestShotChangeFrame.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
}
|
||||
return IsCueOnShotChange(cueFrame, isInCue, closestShotChangeFrame.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1041,6 +1127,18 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsCueOnShotChange(int cueFrame, bool isInCue, int shotChangeFrame)
|
||||
{
|
||||
if (isInCue)
|
||||
{
|
||||
return cueFrame >= shotChangeFrame && cueFrame <= shotChangeFrame + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap;
|
||||
}
|
||||
else
|
||||
{
|
||||
return cueFrame <= shotChangeFrame && cueFrame >= shotChangeFrame - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Delegates
|
||||
|
||||
@ -1063,5 +1161,43 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
||||
{
|
||||
return GetFrameDurationMs(frameRate) * Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap;
|
||||
}
|
||||
|
||||
public static int GetSmallestMaxGapFrames(double? frameRate = null)
|
||||
{
|
||||
var frameDurationMs = GetFrameDurationMs(frameRate);
|
||||
int smallestMaxGapFrames = int.MaxValue;
|
||||
|
||||
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones)
|
||||
{
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxGap = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap / frameDurationMs;
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Convert.ToInt32(Math.Round(maxGap)));
|
||||
}
|
||||
|
||||
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones)
|
||||
{
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxGap = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap / frameDurationMs;
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Convert.ToInt32(Math.Round(maxGap)));
|
||||
}
|
||||
|
||||
if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones)
|
||||
{
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone);
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxGap = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap / frameDurationMs;
|
||||
smallestMaxGapFrames = Math.Min(smallestMaxGapFrames, Convert.ToInt32(Math.Round(maxGap)));
|
||||
}
|
||||
|
||||
return smallestMaxGapFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Core.Forms;
|
||||
using Nikse.SubtitleEdit.Core.SubtitleFormats;
|
||||
using Nikse.SubtitleEdit.Forms.ShotChanges;
|
||||
using Nikse.SubtitleEdit.Logic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using MessageBox = Nikse.SubtitleEdit.Forms.SeMsgBox.MessageBox;
|
||||
|
||||
@ -25,6 +27,14 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
public List<double> ShotChangesInSeconds = new List<double>(); // For storing imported/generated shot changes that will be returned to the main form
|
||||
public Subtitle FixedSubtitle { get; private set; }
|
||||
|
||||
public List<UnfixableParagraphsPair> UnfixableParagraphs { get; private set; }
|
||||
public struct UnfixableParagraphsPair
|
||||
{
|
||||
public Paragraph leftParagraph;
|
||||
public Paragraph rightParagraph;
|
||||
public int gapFrames;
|
||||
}
|
||||
|
||||
private bool _abortTimeCodes;
|
||||
private TimeCodesGenerator _timeCodesGenerator;
|
||||
|
||||
@ -287,6 +297,9 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
};
|
||||
timeCodesBeautifier.Beautify();
|
||||
|
||||
// Check for any paragraphs that still have a gap smaller than the smallest max. gap
|
||||
CheckUnfixableParagraphs();
|
||||
|
||||
// Re-enable group boxes, otherwise child controls are also disabled, and we need their original state for the checks below
|
||||
groupBoxTimeCodes.Enabled = true;
|
||||
groupBoxShotChanges.Enabled = true;
|
||||
@ -307,6 +320,36 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void CheckUnfixableParagraphs()
|
||||
{
|
||||
var minGap = Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
|
||||
var minGapInCueClosest = Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestLeftGap + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesInCueClosestRightGap;
|
||||
var minGapOutCueClosest = Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestLeftGap + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesOutCueClosestRightGap;
|
||||
var smallestMaxGapFrames = TimeCodesBeautifierUtils.GetSmallestMaxGapFrames(_frameRate);
|
||||
|
||||
UnfixableParagraphs = new List<UnfixableParagraphsPair>();
|
||||
|
||||
for (var p = 0; p < FixedSubtitle.Paragraphs.Count - 2; p++)
|
||||
{
|
||||
var paragraph = FixedSubtitle.Paragraphs.ElementAtOrDefault(p);
|
||||
var nextParagraph = FixedSubtitle.Paragraphs.ElementAtOrDefault(p + 1);
|
||||
|
||||
if (paragraph != null && nextParagraph != null)
|
||||
{
|
||||
var gapFrames = SubtitleFormat.MillisecondsToFrames(nextParagraph.StartTime.TotalMilliseconds - paragraph.EndTime.TotalMilliseconds, _frameRate);
|
||||
if (gapFrames < smallestMaxGapFrames && gapFrames != minGap && gapFrames != minGapInCueClosest && gapFrames != minGapOutCueClosest)
|
||||
{
|
||||
UnfixableParagraphs.Add(new UnfixableParagraphsPair()
|
||||
{
|
||||
leftParagraph = paragraph,
|
||||
rightParagraph = nextParagraph,
|
||||
gapFrames = gapFrames
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBoxAlignTimeCodes_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshControls();
|
||||
|
@ -104,6 +104,8 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
this.radioButtonChainingOutCueOnShotMaxGap = new System.Windows.Forms.RadioButton();
|
||||
this.numericUpDownChainingOutCueOnShotMaxGap = new Nikse.SubtitleEdit.Controls.NikseUpDown();
|
||||
this.buttonCreateSimple = new System.Windows.Forms.Button();
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral = new System.Windows.Forms.CheckBox();
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral = new System.Windows.Forms.CheckBox();
|
||||
this.menuStrip.SuspendLayout();
|
||||
this.groupBoxGeneral.SuspendLayout();
|
||||
this.groupBoxInCues.SuspendLayout();
|
||||
@ -1482,6 +1484,7 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
//
|
||||
// tabPageChainingInCueOnShot
|
||||
//
|
||||
this.tabPageChainingInCueOnShot.Controls.Add(this.checkBoxChainingInCueOnShotCheckGeneral);
|
||||
this.tabPageChainingInCueOnShot.Controls.Add(this.labelChainingInCueOnShotMaxGapSuffix);
|
||||
this.tabPageChainingInCueOnShot.Controls.Add(this.radioButtonChainingInCueOnShotZones);
|
||||
this.tabPageChainingInCueOnShot.Controls.Add(this.radioButtonChainingInCueOnShotMaxGap);
|
||||
@ -1646,6 +1649,7 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
//
|
||||
// tabPageChainingOutCueOnShot
|
||||
//
|
||||
this.tabPageChainingOutCueOnShot.Controls.Add(this.checkBoxChainingOutCueOnShotCheckGeneral);
|
||||
this.tabPageChainingOutCueOnShot.Controls.Add(this.numericUpDownChainingOutCueOnShotRightGreenZone);
|
||||
this.tabPageChainingOutCueOnShot.Controls.Add(this.numericUpDownChainingOutCueOnShotRightRedZone);
|
||||
this.tabPageChainingOutCueOnShot.Controls.Add(this.labelChainingOutCueOnShotMaxGapSuffix);
|
||||
@ -1816,6 +1820,30 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
this.buttonCreateSimple.UseVisualStyleBackColor = true;
|
||||
this.buttonCreateSimple.Click += new System.EventHandler(this.buttonCreateSimple_Click);
|
||||
//
|
||||
// checkBoxChainingInCueOnShotCheckGeneral
|
||||
//
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.AutoSize = true;
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.Checked = true;
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.Location = new System.Drawing.Point(0, 78);
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.Name = "checkBoxChainingInCueOnShotCheckGeneral";
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.Size = new System.Drawing.Size(251, 19);
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.TabIndex = 16;
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.Text = "Still enforce General rules when unaffected";
|
||||
this.checkBoxChainingInCueOnShotCheckGeneral.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// checkBoxChainingOutCueOnShotCheckGeneral
|
||||
//
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.AutoSize = true;
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.Checked = true;
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.Location = new System.Drawing.Point(0, 78);
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.Name = "checkBoxChainingOutCueOnShotCheckGeneral";
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.Size = new System.Drawing.Size(251, 19);
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.TabIndex = 26;
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.Text = "Still enforce General rules when unaffected";
|
||||
this.checkBoxChainingOutCueOnShotCheckGeneral.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// BeautifyTimeCodesProfile
|
||||
//
|
||||
this.AcceptButton = this.buttonOK;
|
||||
@ -1950,5 +1978,7 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
private System.Windows.Forms.Label labelConnectedSubtitlesOutCueClosestGaps;
|
||||
private Controls.CuesPreviewView cuesPreviewViewConnectedSubtitlesOutCueClosest;
|
||||
private System.Windows.Forms.Button buttonCreateSimple;
|
||||
private System.Windows.Forms.CheckBox checkBoxChainingInCueOnShotCheckGeneral;
|
||||
private System.Windows.Forms.CheckBox checkBoxChainingOutCueOnShotCheckGeneral;
|
||||
}
|
||||
}
|
@ -64,10 +64,12 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
radioButtonChainingInCueOnShotMaxGap.Text = language.MaxGap;
|
||||
labelChainingInCueOnShotMaxGapSuffix.Text = language.Milliseconds;
|
||||
radioButtonChainingInCueOnShotZones.Text = language.Zones;
|
||||
checkBoxChainingInCueOnShotCheckGeneral.Text = language.CheckGeneral;
|
||||
tabPageChainingOutCueOnShot.Text = language.OutCueOnShot;
|
||||
radioButtonChainingOutCueOnShotMaxGap.Text = language.MaxGap;
|
||||
labelChainingOutCueOnShotMaxGapSuffix.Text = language.Milliseconds;
|
||||
radioButtonChainingOutCueOnShotZones.Text = language.Zones;
|
||||
checkBoxChainingOutCueOnShotCheckGeneral.Text = language.CheckGeneral;
|
||||
|
||||
cuesPreviewViewInCues.PreviewText = language.SubtitlePreviewText;
|
||||
cuesPreviewViewOutCues.PreviewText = language.SubtitlePreviewText;
|
||||
@ -155,12 +157,14 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
numericUpDownChainingInCueOnShotMaxGap.Value = settings.ChainingInCueOnShotMaxGap;
|
||||
numericUpDownChainingInCueOnShotLeftRedZone.Value = settings.ChainingInCueOnShotLeftRedZone;
|
||||
numericUpDownChainingInCueOnShotLeftGreenZone.Value = settings.ChainingInCueOnShotLeftGreenZone;
|
||||
checkBoxChainingInCueOnShotCheckGeneral.Checked = settings.ChainingInCueOnShotCheckGeneral;
|
||||
|
||||
radioButtonChainingOutCueOnShotZones.Checked = settings.ChainingOutCueOnShotUseZones;
|
||||
radioButtonChainingOutCueOnShotMaxGap.Checked = !settings.ChainingOutCueOnShotUseZones;
|
||||
numericUpDownChainingOutCueOnShotMaxGap.Value = settings.ChainingOutCueOnShotMaxGap;
|
||||
numericUpDownChainingOutCueOnShotRightRedZone.Value = settings.ChainingOutCueOnShotRightRedZone;
|
||||
numericUpDownChainingOutCueOnShotRightGreenZone.Value = settings.ChainingOutCueOnShotRightGreenZone;
|
||||
checkBoxChainingOutCueOnShotCheckGeneral.Checked = settings.ChainingOutCueOnShotCheckGeneral;
|
||||
|
||||
RefreshControls();
|
||||
}
|
||||
@ -233,6 +237,9 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
|
||||
private void buttonOK_Click(object sender, EventArgs e)
|
||||
{
|
||||
// Remember value for check later on
|
||||
var previousGeneralShotChangeBehavior = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior;
|
||||
|
||||
// Save settings
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.Gap = Convert.ToInt32(numericUpDownGap.Value);
|
||||
|
||||
@ -262,17 +269,26 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap = Convert.ToInt32(numericUpDownChainingGeneralMaxGap.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone = Convert.ToInt32(numericUpDownChainingGeneralLeftGreenZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone = Convert.ToInt32(numericUpDownChainingGeneralLeftRedZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum)comboBoxChainingGeneralShotChangeBehavior.SelectedIndex;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = (BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum)comboBoxChainingGeneralShotChangeBehavior.SelectedIndex;
|
||||
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones = radioButtonChainingInCueOnShotZones.Checked;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingInCueOnShotMaxGap.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftGreenZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftRedZone = Convert.ToInt32(numericUpDownChainingInCueOnShotLeftRedZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotCheckGeneral = checkBoxChainingInCueOnShotCheckGeneral.Checked;
|
||||
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones = radioButtonChainingOutCueOnShotZones.Checked;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingOutCueOnShotMaxGap.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightRedZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightRedZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone = Convert.ToInt32(numericUpDownChainingOutCueOnShotRightGreenZone.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotCheckGeneral = checkBoxChainingOutCueOnShotCheckGeneral.Checked;
|
||||
|
||||
// Update hidden shot change behavior settings if value for general bahavior has changed
|
||||
if (previousGeneralShotChangeBehavior != Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior)
|
||||
{
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotShotChangeBehavior = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotShotChangeBehavior = Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior;
|
||||
}
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap = Convert.ToInt32(numericUpDownChainingGap.Value);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap);
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftRedZone = GetChainingZoneFrames(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap) - 1;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingGeneralShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralShotChangeBehavior = BeautifyTimeCodesSettings.BeautifyTimeCodesProfile.ChainingShotChangeBehaviorEnum.ExtendUntilShotChange;
|
||||
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones = false;
|
||||
Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap = Convert.ToInt32(numericUpDownChainingGap.Value);
|
||||
|
120
src/ui/Forms/BeautifyTimeCodes/BeautifyTimeCodesUnfixableParagraphs.Designer.cs
generated
Normal file
120
src/ui/Forms/BeautifyTimeCodes/BeautifyTimeCodesUnfixableParagraphs.Designer.cs
generated
Normal file
@ -0,0 +1,120 @@
|
||||
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
{
|
||||
partial class BeautifyTimeCodesUnfixableParagraphs
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BeautifyTimeCodesUnfixableParagraphs));
|
||||
this.buttonClose = new System.Windows.Forms.Button();
|
||||
this.labelInstructions = new System.Windows.Forms.Label();
|
||||
this.listView = new System.Windows.Forms.ListView();
|
||||
this.columnHeaderParagraphs = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeaderGap = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// buttonClose
|
||||
//
|
||||
this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.buttonClose.Location = new System.Drawing.Point(397, 356);
|
||||
this.buttonClose.Name = "buttonClose";
|
||||
this.buttonClose.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonClose.TabIndex = 10;
|
||||
this.buttonClose.Text = "Close";
|
||||
this.buttonClose.UseVisualStyleBackColor = true;
|
||||
this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click);
|
||||
//
|
||||
// labelInstructions
|
||||
//
|
||||
this.labelInstructions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.labelInstructions.AutoEllipsis = true;
|
||||
this.labelInstructions.Location = new System.Drawing.Point(12, 9);
|
||||
this.labelInstructions.Name = "labelInstructions";
|
||||
this.labelInstructions.Size = new System.Drawing.Size(460, 80);
|
||||
this.labelInstructions.TabIndex = 1;
|
||||
this.labelInstructions.Text = resources.GetString("labelInstructions.Text");
|
||||
//
|
||||
// listView
|
||||
//
|
||||
this.listView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeaderParagraphs,
|
||||
this.columnHeaderGap});
|
||||
this.listView.FullRowSelect = true;
|
||||
this.listView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
|
||||
this.listView.HideSelection = false;
|
||||
this.listView.Location = new System.Drawing.Point(13, 92);
|
||||
this.listView.MultiSelect = false;
|
||||
this.listView.Name = "listView";
|
||||
this.listView.Size = new System.Drawing.Size(458, 258);
|
||||
this.listView.TabIndex = 2;
|
||||
this.listView.UseCompatibleStateImageBehavior = false;
|
||||
this.listView.View = System.Windows.Forms.View.Details;
|
||||
this.listView.SelectedIndexChanged += new System.EventHandler(this.listView_SelectedIndexChanged);
|
||||
this.listView.Click += new System.EventHandler(this.listView_Click);
|
||||
//
|
||||
// columnHeaderParagraphs
|
||||
//
|
||||
this.columnHeaderParagraphs.Width = 150;
|
||||
//
|
||||
// columnHeaderGap
|
||||
//
|
||||
this.columnHeaderGap.Width = 150;
|
||||
//
|
||||
// BeautifyTimeCodesUnfixableParagraphs
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(484, 391);
|
||||
this.Controls.Add(this.listView);
|
||||
this.Controls.Add(this.labelInstructions);
|
||||
this.Controls.Add(this.buttonClose);
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimumSize = new System.Drawing.Size(460, 250);
|
||||
this.Name = "BeautifyTimeCodesUnfixableParagraphs";
|
||||
this.ShowIcon = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Review not fully chained subtitles";
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.BeautifyTimeCodesUnfixableParagraphs_KeyDown);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button buttonClose;
|
||||
private System.Windows.Forms.Label labelInstructions;
|
||||
private System.Windows.Forms.ListView listView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeaderParagraphs;
|
||||
private System.Windows.Forms.ColumnHeader columnHeaderGap;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Logic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using static Nikse.SubtitleEdit.Forms.BeautifyTimeCodes.BeautifyTimeCodes;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Forms.BeautifyTimeCodes
|
||||
{
|
||||
public partial class BeautifyTimeCodesUnfixableParagraphs : Form
|
||||
{
|
||||
private readonly List<UnfixableParagraphsPair> _paragraphs;
|
||||
private readonly Action<Paragraph> _selectParagraphAction;
|
||||
|
||||
public BeautifyTimeCodesUnfixableParagraphs(List<UnfixableParagraphsPair> paragraphs, Action<Paragraph> selectParagraphAction)
|
||||
{
|
||||
_paragraphs = paragraphs;
|
||||
_selectParagraphAction = selectParagraphAction;
|
||||
|
||||
UiUtil.PreInitialize(this);
|
||||
InitializeComponent();
|
||||
UiUtil.FixFonts(this);
|
||||
|
||||
var language = LanguageSettings.Current.BeautifyTimeCodes;
|
||||
Text = language.UnfixableParagraphsTitle;
|
||||
labelInstructions.Text = language.UnfixableParagraphsInstructions;
|
||||
columnHeaderParagraphs.Text = language.UnfixableParagraphsColumnParagraphs;
|
||||
columnHeaderGap.Text = language.UnfixableParagraphsColumnGap;
|
||||
|
||||
buttonClose.Text = LanguageSettings.Current.General.Close;
|
||||
UiUtil.FixLargeFonts(this, buttonClose);
|
||||
|
||||
PopulateListView();
|
||||
}
|
||||
|
||||
private void PopulateListView()
|
||||
{
|
||||
listView.BeginUpdate();
|
||||
foreach (var pair in _paragraphs)
|
||||
{
|
||||
listView.Items.Add(new ListViewItem(new[] {
|
||||
String.Format(LanguageSettings.Current.BeautifyTimeCodes.UnfixableParagraphsColumnParagraphsFormat, pair.leftParagraph.Number, pair.rightParagraph.Number),
|
||||
pair.gapFrames.ToString()
|
||||
}));
|
||||
}
|
||||
listView.EndUpdate();
|
||||
}
|
||||
|
||||
private void BeautifyTimeCodesUnfixableParagraphs_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Escape)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void listView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (listView.SelectedIndices.Count > 0)
|
||||
{
|
||||
var index = listView.SelectedIndices[0];
|
||||
var pair = _paragraphs[index];
|
||||
|
||||
_selectParagraphAction.Invoke(pair.rightParagraph);
|
||||
}
|
||||
}
|
||||
|
||||
private void listView_Click(object sender, EventArgs e)
|
||||
{
|
||||
listView_SelectedIndexChanged(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="labelInstructions.Text" xml:space="preserve">
|
||||
<value>Some subtitles were not fully chained in accordance with your profile, most likely due to too tightly clustered shot changes (possibly false positives).
|
||||
|
||||
You might want to review these cases manually to ensure your cues are snapped to the correct (real) shot changes.
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
@ -119,6 +119,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private FindReplaceDialogHelper _findHelper;
|
||||
private FindDialog _findDialog;
|
||||
private ReplaceDialog _replaceDialog;
|
||||
private Form _dialog;
|
||||
private bool _sourceViewChange;
|
||||
private int _changeSubtitleHash = -1;
|
||||
private int _changeOriginalSubtitleHash = -1;
|
||||
@ -36213,6 +36214,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
var unfixableParagraphs = new List<BeautifyTimeCodes.BeautifyTimeCodes.UnfixableParagraphsPair>();
|
||||
|
||||
if (onlySelectedLines)
|
||||
{
|
||||
var selectedIndices = SubtitleListview1.GetSelectedIndices();
|
||||
@ -36259,6 +36262,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
RestoreSubtitleListviewIndices();
|
||||
|
||||
ShowStatus(_language.BeautifiedTimeCodesSelectedLines);
|
||||
|
||||
unfixableParagraphs = form.UnfixableParagraphs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36291,9 +36296,24 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
RestoreSubtitleListviewIndices();
|
||||
|
||||
ShowStatus(_language.BeautifiedTimeCodes);
|
||||
|
||||
unfixableParagraphs = form.UnfixableParagraphs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unfixableParagraphs.Count > 0)
|
||||
{
|
||||
BeginInvoke(new Action(() => {
|
||||
_dialog?.Dispose();
|
||||
_dialog = new BeautifyTimeCodes.BeautifyTimeCodesUnfixableParagraphs(unfixableParagraphs, (paragraph) =>
|
||||
{
|
||||
SubtitleListview1.SelectIndexAndEnsureVisible(paragraph);
|
||||
GotoSubPositionAndPause();
|
||||
});
|
||||
_dialog.Show(this);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void ToolStripSplitButtonPlayRateClick(object sender, EventArgs e)
|
||||
|
@ -147,6 +147,7 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
Cancel = "C&ancel",
|
||||
Yes = "Yes",
|
||||
No = "No",
|
||||
Close = "Close",
|
||||
Apply = "Apply",
|
||||
ApplyTo = "Apply to",
|
||||
None = "None",
|
||||
@ -579,6 +580,13 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
BatchAlignTimeCodes = "Align time codes to frame time codes",
|
||||
BatchUseExactTimeCodes = "Use exact time codes (if available)",
|
||||
BatchSnapToShotChanges = "Snap cues to shot changes (if available)",
|
||||
UnfixableParagraphsTitle = "Review not fully chained subtitles",
|
||||
UnfixableParagraphsInstructions = "Some subtitles were not fully chained in accordance with your profile, most likely due to too tightly clustered shot changes (possibly false positives)." +
|
||||
Environment.NewLine + Environment.NewLine +
|
||||
"You might want to review these cases manually to ensure your cues are snapped to the correct (real) shot changes.",
|
||||
UnfixableParagraphsColumnParagraphs = "Lines",
|
||||
UnfixableParagraphsColumnParagraphsFormat = "#{0} – #{1}",
|
||||
UnfixableParagraphsColumnGap = "Gap (frames)"
|
||||
};
|
||||
|
||||
BeautifyTimeCodesProfile = new LanguageStructure.BeautifyTimeCodesProfile
|
||||
@ -604,6 +612,7 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
Chaining = "Chaining",
|
||||
InCueOnShot = "In cue on shot change",
|
||||
OutCueOnShot = "Out cue on shot change",
|
||||
CheckGeneral = "Still enforce General rules when unaffected",
|
||||
MaxGap = "Max. gap:",
|
||||
ShotChangeBehavior = "If there is a shot change in between:",
|
||||
DontChain = "Don't chain",
|
||||
|
@ -14,6 +14,7 @@
|
||||
public string Cancel { get; set; }
|
||||
public string Yes { get; set; }
|
||||
public string No { get; set; }
|
||||
public string Close { get; set; }
|
||||
public string Apply { get; set; }
|
||||
public string ApplyTo { get; set; }
|
||||
public string None { get; set; }
|
||||
@ -422,6 +423,11 @@
|
||||
public string BatchAlignTimeCodes { get; set; }
|
||||
public string BatchUseExactTimeCodes { get; set; }
|
||||
public string BatchSnapToShotChanges { get; set; }
|
||||
public string UnfixableParagraphsTitle { get; set; }
|
||||
public string UnfixableParagraphsInstructions { get; set; }
|
||||
public string UnfixableParagraphsColumnParagraphs { get; set; }
|
||||
public string UnfixableParagraphsColumnParagraphsFormat { get; set; }
|
||||
public string UnfixableParagraphsColumnGap { get; set; }
|
||||
}
|
||||
|
||||
public class BeautifyTimeCodesProfile
|
||||
@ -447,6 +453,7 @@
|
||||
public string Chaining { get; set; }
|
||||
public string InCueOnShot { get; set; }
|
||||
public string OutCueOnShot { get; set; }
|
||||
public string CheckGeneral { get; set; }
|
||||
public string MaxGap { get; set; }
|
||||
public string ShotChangeBehavior { get; set; }
|
||||
public string DontChain { get; set; }
|
||||
|
@ -322,6 +322,12 @@
|
||||
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfileSimple.Designer.cs">
|
||||
<DependentUpon>BeautifyTimeCodesProfileSimple.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesUnfixableParagraphs.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesUnfixableParagraphs.Designer.cs">
|
||||
<DependentUpon>BeautifyTimeCodesUnfixableParagraphs.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\BinaryEdit\BinEdit.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@ -1738,6 +1744,9 @@
|
||||
<EmbeddedResource Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesProfileSimple.resx">
|
||||
<DependentUpon>BeautifyTimeCodesProfileSimple.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\BeautifyTimeCodes\BeautifyTimeCodesUnfixableParagraphs.resx">
|
||||
<DependentUpon>BeautifyTimeCodesUnfixableParagraphs.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\BinaryEdit\BinEdit.resx">
|
||||
<DependentUpon>BinEdit.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
Loading…
Reference in New Issue
Block a user