mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2025-01-31 13:01:39 +01:00
Merge branch 'main' into feature/beautify-timecodes-2023
This commit is contained in:
commit
0c692e3f85
30
src/Test/Core/LanguageAutoDetectLanguagesTest.cs
Normal file
30
src/Test/Core/LanguageAutoDetectLanguagesTest.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
|
||||
namespace Test.Core
|
||||
{
|
||||
[TestClass]
|
||||
public class LanguageAutoDetectLanguagesTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void AutoDetectEnglish()
|
||||
{
|
||||
var res = LanguageAutoDetect.AutoDetectGoogleLanguageOrNull2(new Subtitle(new List<Paragraph>
|
||||
{
|
||||
new Paragraph("In this tutorial, I'll show you how to add", 0,0)
|
||||
}));
|
||||
Assert.AreEqual("en", res);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AutoDetectDanish()
|
||||
{
|
||||
var res = LanguageAutoDetect.AutoDetectGoogleLanguageOrNull2(new Subtitle(new List<Paragraph>
|
||||
{
|
||||
new Paragraph("Jeg kan ikke finde på noget at lave i dag. Kun at være glad.", 0,0)
|
||||
}));
|
||||
Assert.AreEqual("da", res);
|
||||
}
|
||||
}
|
||||
}
|
@ -71,6 +71,7 @@
|
||||
<Compile Include="LanguageFiles\LanguageFileTest.cs" />
|
||||
<Compile Include="Logic\BeautifyTimeCodesTest.cs" />
|
||||
<Compile Include="Logic\ConvertColorsToDialogTest.cs" />
|
||||
<Compile Include="Core\LanguageAutoDetectLanguagesTest.cs" />
|
||||
<Compile Include="Logic\NetflixHelperTest.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\EbuStlTest.cs" />
|
||||
<Compile Include="Logic\SubtitleFormats\NetflixTimedTextTest.cs" />
|
||||
|
@ -33,8 +33,14 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "cn",
|
||||
LanguageName = "Chinese (very large, 1.5G)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-cn-kaldi-multicn-2-lgraph.zip",
|
||||
LanguageName = "Chinese (small, 42 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "cn",
|
||||
LanguageName = "Chinese (very large, 1.3 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-cn-0.22.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
@ -51,8 +57,14 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "es",
|
||||
LanguageName = "Spanish",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-es-0.3.zip",
|
||||
LanguageName = "Spanish (small, 39 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-es-0.42.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "es",
|
||||
LanguageName = "Spanish (large, 1.4 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-es-0.42.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
@ -75,19 +87,31 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "pt",
|
||||
LanguageName = "Portuguese",
|
||||
LanguageName = "Portuguese (small, 31 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-pt-0.3.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "pt",
|
||||
LanguageName = "Portuguese (large, 1.6 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-pt-fb-v0.1.1-20220516_2113.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "it",
|
||||
LanguageName = "Italian",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-it-0.4.zip",
|
||||
LanguageName = "Italian (small, 48 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-it-0.22.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "it",
|
||||
LanguageName = "Italian (large, 1.2 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-it-0.22.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "nl",
|
||||
LanguageName = "Dutch",
|
||||
LanguageName = "Dutch (large, 860 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-nl-spraakherkenning-0.6-lgraph.zip",
|
||||
},
|
||||
new VoskModel
|
||||
@ -99,10 +123,16 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "ru",
|
||||
LanguageName = "Russian",
|
||||
LanguageName = "Russian (small, 45 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-ru-0.22.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "ru",
|
||||
LanguageName = "Russian (large, 1.8 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-ru-0.42.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "fa",
|
||||
LanguageName = "Farsi",
|
||||
@ -123,10 +153,16 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "ar",
|
||||
LanguageName = "Arabic",
|
||||
LanguageName = "Arabic (small, 318 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-ar-mgb2-0.4.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "ar",
|
||||
LanguageName = "Arabic (large, 1.3 GB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-ar-0.22-linto-1.1.0.zip",
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "uk",
|
||||
LanguageName = "Ukrainian (small, 133 MB)",
|
||||
@ -197,7 +233,13 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
|
||||
TwoLetterLanguageCode = "pl",
|
||||
LanguageName = "Polish",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-small-pl-0.22.zip",
|
||||
}
|
||||
},
|
||||
new VoskModel
|
||||
{
|
||||
TwoLetterLanguageCode = "br",
|
||||
LanguageName = "Breton (small, 70 MB)",
|
||||
Url = "https://alphacephei.com/vosk/models/vosk-model-br-0.7.zip",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
@ -77,14 +77,18 @@ namespace Nikse.SubtitleEdit.Core.Common
|
||||
|
||||
private static readonly string[] AutoDetectWordsEnglish =
|
||||
{
|
||||
"we", "are", "and", "your", "what", "[TW]hat's", "You're", "(any|some|every)thing", "money", "because", "human", "because", "welcome", "really", "something", "confusing", "about", "know", "people", "other", "which", "would",
|
||||
"these", "could"
|
||||
"we", "are", "and", "your", "what", "[TW]hat's", "You're", "(any|some|every)thing", "money", "because", "human", "abandon",
|
||||
"welcome", "really", "something", "confusing", "about", "know", "people", "other", "which", "would", "these", "could",
|
||||
"tutorial", "I'll", "show", "you", "about", "absolutely", "accept", "wrong", "thought", "training", "treatment", "successful",
|
||||
"strong", "simply", "situation","soldier", "somebody", "someone","something", "sometimes", "speak","statement", "perhaps",
|
||||
"piece", "picture", "police", "popular", "population", "suggest", "weapon", "water", "window", "woman", "talk", "security",
|
||||
"season", "remain", "relationship", "report" ,"user" ,"result", "this",
|
||||
};
|
||||
|
||||
private static readonly string[] AutoDetectWordsDanish =
|
||||
{
|
||||
"vi", "han", "og", "jeg", "var", "men", "gider", "bliver", "virkelig", "kommer", "tilbage", "Hej", "længere", "gjorde", "dig", "havde", "[Uu]ndskyld", "arbejder", "vidste", "troede", "stadigvæk", "[Mm]åske", "første", "gik",
|
||||
"fortælle", "begyndt", "spørgsmål", "pludselig"
|
||||
"fortælle", "begyndt", "spørgsmål", "pludselig", "være", "fordi", "været", "sidste","også", "løb", "sagde", "hjem",
|
||||
};
|
||||
|
||||
private static readonly string[] AutoDetectWordsNorwegian =
|
||||
@ -796,11 +800,275 @@ namespace Nikse.SubtitleEdit.Core.Common
|
||||
return languageId;
|
||||
}
|
||||
|
||||
public class LanguageForAutoDetect
|
||||
{
|
||||
public string LanguageCode { get; set; }
|
||||
public string[] Words { get; set; }
|
||||
public int WordCount { get; set; }
|
||||
}
|
||||
|
||||
public static LanguageForAutoDetect[] GetLanguagesWithCount(string text)
|
||||
{
|
||||
var list = new LanguageForAutoDetect[]
|
||||
{
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "en",
|
||||
Words = AutoDetectWordsEnglish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "da",
|
||||
Words = AutoDetectWordsDanish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "no",
|
||||
Words = AutoDetectWordsNorwegian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sv",
|
||||
Words = AutoDetectWordsSwedish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "es",
|
||||
Words = AutoDetectWordsSpanish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "it",
|
||||
Words = AutoDetectWordsItalian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "fr",
|
||||
Words = AutoDetectWordsFrench,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "pt",
|
||||
Words = AutoDetectWordsPortuguese,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "de",
|
||||
Words = AutoDetectWordsGerman,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "nl",
|
||||
Words = AutoDetectWordsDutch,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "pl",
|
||||
Words = AutoDetectWordsPolish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "el",
|
||||
Words = AutoDetectWordsGreek,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "ru",
|
||||
Words = AutoDetectWordsRussian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "bg",
|
||||
Words = AutoDetectWordsBulgarian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "uk",
|
||||
Words = AutoDetectWordsUkrainian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sq",
|
||||
Words = AutoDetectWordsAlbanian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "ar",
|
||||
Words = AutoDetectWordsArabic,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "fa",
|
||||
Words = AutoDetectWordsFarsi,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "he",
|
||||
Words = AutoDetectWordsHebrew,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "vi",
|
||||
Words = AutoDetectWordsVietnamese,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "hu",
|
||||
Words = AutoDetectWordsHungarian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "tr",
|
||||
Words = AutoDetectWordsTurkish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "-",
|
||||
Words = AutoDetectWordsCroatianAndSerbian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "hr",
|
||||
Words = AutoDetectWordsCroatian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sr",
|
||||
Words = AutoDetectWordsSerbian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sr",
|
||||
Words = AutoDetectWordsSerbianCyrillic,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sr-cy",
|
||||
Words = AutoDetectWordsSerbianCyrillicOnly,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "id",
|
||||
Words = AutoDetectWordsIndonesian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "th",
|
||||
Words = AutoDetectWordsThai,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "ko",
|
||||
Words = AutoDetectWordsKorean,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "mk",
|
||||
Words = AutoDetectWordsMacedonian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "fi",
|
||||
Words = AutoDetectWordsFinnish,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "ro",
|
||||
Words = AutoDetectWordsRomanian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "-",
|
||||
Words = AutoDetectWordsCzechAndSlovak,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "cs",
|
||||
Words = AutoDetectWordsCzech,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sk",
|
||||
Words = AutoDetectWordsSlovak,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "sl",
|
||||
Words = AutoDetectWordsSlovenian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "is",
|
||||
Words = AutoDetectWordsIcelandic,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "lv",
|
||||
Words = AutoDetectWordsLatvian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "lt",
|
||||
Words = AutoDetectWordsLithuanian,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "hi",
|
||||
Words = AutoDetectWordsHindi,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "ur",
|
||||
Words = AutoDetectWordsUrdu,
|
||||
},
|
||||
new LanguageForAutoDetect
|
||||
{
|
||||
LanguageCode = "si",
|
||||
Words = AutoDetectWordsSinhalese,
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
item.WordCount = GetCount(text, item.Words);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
//TODO: improve... a lot ;)
|
||||
public static string AutoDetectGoogleLanguageOrNull2(Subtitle subtitle)
|
||||
{
|
||||
var s = new Subtitle(subtitle);
|
||||
s.RemoveEmptyLines();
|
||||
var allText = s.GetAllTexts(500000).TrimEnd();
|
||||
var languagesAndWords = GetLanguagesWithCount(allText);
|
||||
var languageAndWordHitsOrdered = languagesAndWords
|
||||
.Where(p => p.WordCount > 0)
|
||||
.OrderByDescending(p => p.WordCount);
|
||||
var languageIdFromWordCount = languageAndWordHitsOrdered
|
||||
.FirstOrDefault(p => p.LanguageCode != "-")?.LanguageCode;
|
||||
|
||||
var languageIdViaLetters = GetEncodingViaLetter(allText);
|
||||
|
||||
if (languageIdFromWordCount != null)
|
||||
{
|
||||
return languageIdFromWordCount;
|
||||
}
|
||||
|
||||
if (languageIdViaLetters != null)
|
||||
{
|
||||
return languageIdViaLetters;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string AutoDetectGoogleLanguageOrNull(Subtitle subtitle)
|
||||
{
|
||||
var s = new Subtitle(subtitle);
|
||||
s.RemoveEmptyLines();
|
||||
var allText = s.GetAllTexts(500000);
|
||||
var allText = s.GetAllTexts(500000).TrimEnd();
|
||||
var languageId = AutoDetectGoogleLanguage(allText, s.Paragraphs.Count / 14);
|
||||
if (string.IsNullOrEmpty(languageId))
|
||||
{
|
||||
@ -811,6 +1079,7 @@ namespace Nikse.SubtitleEdit.Core.Common
|
||||
{
|
||||
languageId = null;
|
||||
}
|
||||
|
||||
return languageId;
|
||||
}
|
||||
|
||||
|
787
src/ui/Controls/NikseTimeUpDown.cs
Normal file
787
src/ui/Controls/NikseTimeUpDown.cs
Normal file
@ -0,0 +1,787 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Globalization;
|
||||
using System.Windows.Forms;
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Logic;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Controls
|
||||
{
|
||||
[Category("NikseTimeUpDown"), Description("Subtitle time with better support for color theme")]
|
||||
public sealed class NikseTimeUpDown : Control
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public EventHandler TimeCodeChanged;
|
||||
|
||||
public enum TimeMode
|
||||
{
|
||||
HHMMSSMS,
|
||||
HHMMSSFF
|
||||
}
|
||||
|
||||
private readonly bool _designMode = LicenseManager.UsageMode == LicenseUsageMode.Designtime;
|
||||
|
||||
private const int NumericUpDownValue = 50;
|
||||
|
||||
|
||||
private bool _forceHHMMSSFF;
|
||||
|
||||
public bool UseVideoOffset { get; set; }
|
||||
|
||||
private static readonly char[] SplitChars = GetSplitChars();
|
||||
|
||||
private bool _dirty;
|
||||
double _initialTotalMilliseconds;
|
||||
|
||||
internal void ForceHHMMSSFF()
|
||||
{
|
||||
_forceHHMMSSFF = true;
|
||||
_maskedTextBox.Mask = "00:00:00:00";
|
||||
}
|
||||
|
||||
public void SetAutoWidth()
|
||||
{
|
||||
using (var g = Graphics.FromHwnd(IntPtr.Zero))
|
||||
{
|
||||
var widthOfUpDown = 25;
|
||||
if (Configuration.IsRunningOnLinux)
|
||||
{
|
||||
widthOfUpDown += 20;
|
||||
}
|
||||
var actualWidth = g.MeasureString("00:00:00:000", Font).Width;
|
||||
Width = (int)Math.Round(actualWidth + ButtonsWidth + 6);
|
||||
}
|
||||
}
|
||||
|
||||
public TimeMode Mode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_forceHHMMSSFF || Configuration.Settings?.General.UseTimeFormatHHMMSSFF == true)
|
||||
{
|
||||
return TimeMode.HHMMSSFF;
|
||||
}
|
||||
|
||||
return TimeMode.HHMMSSMS;
|
||||
}
|
||||
}
|
||||
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the increment value")]
|
||||
public decimal Increment { get; set; } = 100;
|
||||
|
||||
[Category("NikseTimeUpDown"), Description("Allow arrow keys to set increment/decrement value")]
|
||||
[DefaultValue(true)]
|
||||
public bool InterceptArrowKeys { get; set; }
|
||||
|
||||
private Color _buttonForeColor;
|
||||
private Brush _buttonForeColorBrush;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the button foreground color"),
|
||||
RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColor
|
||||
{
|
||||
get => _buttonForeColor;
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColor = value;
|
||||
_buttonForeColorBrush?.Dispose();
|
||||
_buttonForeColorBrush = new SolidBrush(_buttonForeColor);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _buttonForeColorOver;
|
||||
private Brush _buttonForeColorOverBrush;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the button foreground mouse over color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColorOver
|
||||
{
|
||||
get => _buttonForeColorOver;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColorOver = value;
|
||||
_buttonForeColorOverBrush?.Dispose();
|
||||
_buttonForeColorOverBrush = new SolidBrush(_buttonForeColorOver);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _buttonForeColorDown;
|
||||
private Brush _buttonForeColorDownBrush;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the button foreground mouse down color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColorDown
|
||||
{
|
||||
get => _buttonForeColorDown;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColorDown = value;
|
||||
_buttonForeColorDownBrush?.Dispose();
|
||||
_buttonForeColorDownBrush = new SolidBrush(_buttonForeColorDown);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _borderColor;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the border color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BorderColor
|
||||
{
|
||||
get => _borderColor;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_borderColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _backColorDisabled;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the button foreground color"),
|
||||
RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BackColorDisabled
|
||||
{
|
||||
get => _backColorDisabled;
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_backColorDisabled = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _borderColorDisabled;
|
||||
[Category("NikseTimeUpDown"), Description("Gets or sets the disabled border color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BorderColorDisabled
|
||||
{
|
||||
get => _borderColorDisabled;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_borderColorDisabled = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly MaskedTextBox _maskedTextBox;
|
||||
|
||||
public NikseTimeUpDown()
|
||||
{
|
||||
_maskedTextBox = new MaskedTextBox();
|
||||
_maskedTextBox.Font = UiUtil.GetDefaultFont();
|
||||
_maskedTextBox.KeyPress += TextBox_KeyPress;
|
||||
_maskedTextBox.KeyDown += (sender, e) =>
|
||||
{
|
||||
if (InterceptArrowKeys && e.KeyCode == Keys.Down)
|
||||
{
|
||||
AddValue(-Increment);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (InterceptArrowKeys && e.KeyCode == Keys.Up)
|
||||
{
|
||||
AddValue(Increment);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.KeyData == Keys.Enter)
|
||||
{
|
||||
TimeCodeChanged?.Invoke(this, e);
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
else if (e.KeyData != (Keys.Tab | Keys.Shift) &&
|
||||
e.KeyData != Keys.Tab &&
|
||||
e.KeyData != Keys.Left &&
|
||||
e.KeyData != Keys.Right)
|
||||
{
|
||||
_dirty = true;
|
||||
}
|
||||
};
|
||||
_maskedTextBox.LostFocus += (sender, args) => Invalidate();
|
||||
_maskedTextBox.GotFocus += (sender, args) => Invalidate();
|
||||
_maskedTextBox.MouseDown += (sender, e) =>
|
||||
{
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
_dirty = true;
|
||||
}
|
||||
};
|
||||
_maskedTextBox.BorderStyle = BorderStyle.None;
|
||||
|
||||
Controls.Add(_maskedTextBox);
|
||||
BackColor = new TextBox().BackColor;
|
||||
ButtonForeColor = DefaultForeColor;
|
||||
ButtonForeColorOver = Color.FromArgb(0, 120, 215);
|
||||
ButtonForeColorDown = Color.Orange;
|
||||
BorderColor = Color.FromArgb(171, 173, 179);
|
||||
BorderColorDisabled = Color.FromArgb(120, 120, 120);
|
||||
BackColorDisabled = Color.FromArgb(240, 240, 240);
|
||||
DoubleBuffered = true;
|
||||
InterceptArrowKeys = true;
|
||||
Increment = 100;
|
||||
|
||||
_repeatTimer = new Timer();
|
||||
_repeatTimer.Tick += (sender, args) =>
|
||||
{
|
||||
if (_repeatTimerArrowUp)
|
||||
{
|
||||
AddValue(Increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddValue(-Increment);
|
||||
}
|
||||
|
||||
_repeatCount++;
|
||||
_repeatTimer.Interval = _repeatCount < 8 ? 75 : 10;
|
||||
};
|
||||
|
||||
LostFocus += (sender, args) => _repeatTimer.Stop();
|
||||
|
||||
_maskedTextBox.InsertKeyMode = InsertKeyMode.Overwrite;
|
||||
_maskedTextBox.LostFocus += (sender, args) =>
|
||||
{
|
||||
AddValue(0);
|
||||
};
|
||||
}
|
||||
|
||||
public MaskedTextBox MaskedTextBox => _maskedTextBox;
|
||||
|
||||
public void SetTotalMilliseconds(double milliseconds)
|
||||
{
|
||||
_dirty = false;
|
||||
_initialTotalMilliseconds = milliseconds;
|
||||
if (UseVideoOffset)
|
||||
{
|
||||
milliseconds += Configuration.Settings.General.CurrentVideoOffsetInMs;
|
||||
}
|
||||
if (Mode == TimeMode.HHMMSSMS)
|
||||
{
|
||||
_maskedTextBox.Mask = GetMask(milliseconds);
|
||||
_maskedTextBox.Text = new TimeCode(milliseconds).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
var tc = new TimeCode(milliseconds);
|
||||
_maskedTextBox.Mask = GetMaskFrames(milliseconds);
|
||||
_maskedTextBox.Text = tc.ToString().Substring(0, 9) + $"{Core.SubtitleFormats.SubtitleFormat.MillisecondsToFrames(tc.Milliseconds):00}";
|
||||
}
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
public double? GetTotalMilliseconds()
|
||||
{
|
||||
return _dirty ? TimeCode?.TotalMilliseconds : _initialTotalMilliseconds;
|
||||
}
|
||||
|
||||
public TimeCode TimeCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_designMode)
|
||||
{
|
||||
return new TimeCode();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_maskedTextBox.Text.RemoveChar('.').Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, string.Empty).RemoveChar(',', ':')))
|
||||
{
|
||||
return new TimeCode(TimeCode.MaxTimeTotalMilliseconds);
|
||||
}
|
||||
|
||||
if (!_dirty)
|
||||
{
|
||||
return new TimeCode(_initialTotalMilliseconds);
|
||||
}
|
||||
|
||||
string startTime = _maskedTextBox.Text;
|
||||
bool isNegative = startTime.StartsWith('-');
|
||||
startTime = startTime.TrimStart('-').Replace(' ', '0');
|
||||
if (Mode == TimeMode.HHMMSSMS)
|
||||
{
|
||||
if (startTime.EndsWith(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, StringComparison.Ordinal))
|
||||
{
|
||||
startTime += "000";
|
||||
}
|
||||
|
||||
var times = startTime.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (times.Length == 4)
|
||||
{
|
||||
int.TryParse(times[0], out var hours);
|
||||
|
||||
int.TryParse(times[1], out var minutes);
|
||||
if (minutes > 59)
|
||||
{
|
||||
minutes = 59;
|
||||
}
|
||||
|
||||
int.TryParse(times[2], out var seconds);
|
||||
if (seconds > 59)
|
||||
{
|
||||
seconds = 59;
|
||||
}
|
||||
|
||||
int.TryParse(times[3].PadRight(3, '0'), out var milliseconds);
|
||||
var tc = new TimeCode(hours, minutes, seconds, milliseconds);
|
||||
|
||||
if (UseVideoOffset)
|
||||
{
|
||||
tc.TotalMilliseconds -= Configuration.Settings.General.CurrentVideoOffsetInMs;
|
||||
}
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
tc.TotalMilliseconds *= -1;
|
||||
}
|
||||
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startTime.EndsWith(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, StringComparison.Ordinal) || startTime.EndsWith(':'))
|
||||
{
|
||||
startTime += "00";
|
||||
}
|
||||
|
||||
string[] times = startTime.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (times.Length == 4)
|
||||
{
|
||||
int.TryParse(times[0], out var hours);
|
||||
|
||||
int.TryParse(times[1], out var minutes);
|
||||
|
||||
int.TryParse(times[2], out var seconds);
|
||||
|
||||
if (int.TryParse(times[3], out var milliseconds))
|
||||
{
|
||||
milliseconds = Core.SubtitleFormats.SubtitleFormat.FramesToMillisecondsMax999(milliseconds);
|
||||
}
|
||||
|
||||
var tc = new TimeCode(hours, minutes, seconds, milliseconds);
|
||||
|
||||
if (UseVideoOffset)
|
||||
{
|
||||
tc.TotalMilliseconds -= Configuration.Settings.General.CurrentVideoOffsetInMs;
|
||||
}
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
tc.TotalMilliseconds *= -1;
|
||||
}
|
||||
|
||||
return tc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_designMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
_dirty = false;
|
||||
_initialTotalMilliseconds = value.TotalMilliseconds;
|
||||
}
|
||||
|
||||
if (value == null || value.TotalMilliseconds >= TimeCode.MaxTimeTotalMilliseconds - 0.1)
|
||||
{
|
||||
_maskedTextBox.Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
var v = new TimeCode(value.TotalMilliseconds);
|
||||
if (UseVideoOffset)
|
||||
{
|
||||
v.TotalMilliseconds += Configuration.Settings.General.CurrentVideoOffsetInMs;
|
||||
}
|
||||
|
||||
if (Mode == TimeMode.HHMMSSMS)
|
||||
{
|
||||
_maskedTextBox.Mask = GetMask(v.TotalMilliseconds);
|
||||
_maskedTextBox.Text = v.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
_maskedTextBox.Mask = GetMaskFrames(v.TotalMilliseconds);
|
||||
_maskedTextBox.Text = v.ToHHMMSSFF();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetMask(double val) => val >= 0 ? "00:00:00.000" : "-00:00:00.000";
|
||||
|
||||
private static string GetMaskFrames(double val) => val >= 0 ? "00:00:00:00" : "-00:00:00:00";
|
||||
|
||||
public void Theme()
|
||||
{
|
||||
var enabled = Enabled;
|
||||
Enabled = true;
|
||||
if (Configuration.Settings.General.UseDarkTheme)
|
||||
{
|
||||
BackColor = DarkTheme.BackColor;
|
||||
MaskedTextBox.BackColor = DarkTheme.BackColor;
|
||||
BackColor = DarkTheme.BackColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
BackColor = DefaultBackColor;
|
||||
using (var tb = new TextBox())
|
||||
{
|
||||
MaskedTextBox.BackColor = tb.BackColor;
|
||||
BackColor = tb.BackColor;
|
||||
}
|
||||
}
|
||||
|
||||
Enabled = enabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow only digits, Enter and Backspace key.
|
||||
/// </summary>
|
||||
private void TextBox_KeyPress(object sender, KeyPressEventArgs e)
|
||||
{
|
||||
if (e.KeyChar == (char)Keys.Enter)
|
||||
{
|
||||
AddValue(0);
|
||||
e.Handled = false;
|
||||
}
|
||||
else if (char.IsDigit(e.KeyChar) || e.KeyChar == (char)Keys.Back)
|
||||
{
|
||||
e.Handled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment or decrement the TextBox value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to increment/decrement</param>
|
||||
private void AddValue(decimal value)
|
||||
{
|
||||
_dirty = true;
|
||||
var milliseconds = GetTotalMilliseconds();
|
||||
if (milliseconds.HasValue)
|
||||
{
|
||||
if (milliseconds.Value >= TimeCode.MaxTimeTotalMilliseconds - 0.1)
|
||||
{
|
||||
milliseconds = 0;
|
||||
}
|
||||
|
||||
if (Mode == TimeMode.HHMMSSMS)
|
||||
{
|
||||
SetTotalMilliseconds(milliseconds.Value + (double)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value > NumericUpDownValue)
|
||||
{
|
||||
SetTotalMilliseconds(milliseconds.Value + Core.SubtitleFormats.SubtitleFormat.FramesToMilliseconds(1));
|
||||
}
|
||||
else if (value < NumericUpDownValue)
|
||||
{
|
||||
SetTotalMilliseconds(milliseconds.Value - Core.SubtitleFormats.SubtitleFormat.FramesToMilliseconds(1));
|
||||
}
|
||||
}
|
||||
TimeCodeChanged?.Invoke(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _buttonUpActive;
|
||||
private bool _buttonDownActive;
|
||||
|
||||
private bool _buttonLeftIsDown;
|
||||
|
||||
private int _mouseX;
|
||||
private int _mouseY;
|
||||
|
||||
private readonly Timer _repeatTimer;
|
||||
private bool _repeatTimerArrowUp;
|
||||
private int _repeatCount;
|
||||
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
base.OnMouseEnter(e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
base.OnMouseLeave(e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
_buttonLeftIsDown = true;
|
||||
|
||||
if (_buttonUpActive)
|
||||
{
|
||||
AddValue(Increment);
|
||||
_repeatTimerArrowUp = true;
|
||||
_repeatTimer.Interval = 300;
|
||||
_repeatCount = 0;
|
||||
_repeatTimer.Start();
|
||||
}
|
||||
else if (_buttonDownActive)
|
||||
{
|
||||
AddValue(-Increment);
|
||||
_repeatTimerArrowUp = false;
|
||||
_repeatTimer.Interval = 300;
|
||||
_repeatCount = 0;
|
||||
_repeatTimer.Start();
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
_repeatTimer.Stop();
|
||||
|
||||
if (_buttonLeftIsDown)
|
||||
{
|
||||
_buttonLeftIsDown = false;
|
||||
Invalidate();
|
||||
}
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
var left = RightToLeft == RightToLeft.Yes ? 0 : Width - ButtonsWidth;
|
||||
var right = RightToLeft == RightToLeft.Yes ? ButtonsWidth : Width;
|
||||
var height = Height / 2 - 3;
|
||||
const int top = 2;
|
||||
|
||||
_mouseX = e.X;
|
||||
_mouseY = e.Y;
|
||||
|
||||
if (_mouseX >= left && _mouseX <= right)
|
||||
{
|
||||
if (_mouseY > top + height)
|
||||
{
|
||||
if (!_buttonDownActive)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = true;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_buttonUpActive)
|
||||
{
|
||||
_buttonUpActive = true;
|
||||
_buttonDownActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_buttonUpActive || _buttonDownActive)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
_repeatTimer.Stop();
|
||||
}
|
||||
|
||||
base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
private const int ButtonsWidth = 13;
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
_maskedTextBox.BackColor = BackColor;
|
||||
_maskedTextBox.ForeColor = ButtonForeColor;
|
||||
_maskedTextBox.Top = 2;
|
||||
_maskedTextBox.Left = RightToLeft == RightToLeft.Yes ? ButtonsWidth : 3;
|
||||
_maskedTextBox.Height = Height - 4;
|
||||
_maskedTextBox.Width = Width - ButtonsWidth - 3;
|
||||
_maskedTextBox.Invalidate();
|
||||
|
||||
if (!Enabled)
|
||||
{
|
||||
DrawDisabled(e);
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnPaint(e);
|
||||
using (var pen = _maskedTextBox.Focused ? new Pen(_buttonForeColorOver, 1f) : new Pen(BorderColor, 1f))
|
||||
{
|
||||
var borderRectangle = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
|
||||
e.Graphics.DrawRectangle(pen, borderRectangle);
|
||||
}
|
||||
|
||||
var brush = _buttonForeColorBrush;
|
||||
var left = RightToLeft == RightToLeft.Yes ? 3 : Width - ButtonsWidth;
|
||||
var height = e.ClipRectangle.Height / 2 - 4;
|
||||
var top = 2;
|
||||
if (_buttonUpActive)
|
||||
{
|
||||
brush = _buttonLeftIsDown ? _buttonForeColorDownBrush : _buttonForeColorOverBrush;
|
||||
}
|
||||
|
||||
DrawArrowUp(e, brush, left, top, height);
|
||||
|
||||
if (_buttonDownActive)
|
||||
{
|
||||
brush = _buttonLeftIsDown ? _buttonForeColorDownBrush : _buttonForeColorOverBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
brush = _buttonForeColorBrush;
|
||||
}
|
||||
|
||||
top = height + 5;
|
||||
DrawArrowDown(e, brush, left, top, height);
|
||||
}
|
||||
|
||||
public override RightToLeft RightToLeft
|
||||
{
|
||||
get => base.RightToLeft;
|
||||
set
|
||||
{
|
||||
base.RightToLeft = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color ForeColor
|
||||
{
|
||||
get => base.ForeColor;
|
||||
set
|
||||
{
|
||||
base.ForeColor = value;
|
||||
_maskedTextBox.ForeColor = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color BackColor
|
||||
{
|
||||
get => base.BackColor;
|
||||
set
|
||||
{
|
||||
base.BackColor = value;
|
||||
_maskedTextBox.BackColor = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawArrowDown(PaintEventArgs e, Brush brush, int left, int top, int height)
|
||||
{
|
||||
e.Graphics.FillPolygon(brush,
|
||||
new[]
|
||||
{
|
||||
new Point(left + 5, top + height),
|
||||
new Point(left + 0, top + 0),
|
||||
new Point(left + 10, top + 0)
|
||||
});
|
||||
}
|
||||
|
||||
private static void DrawArrowUp(PaintEventArgs e, Brush brush, int left, int top, int height)
|
||||
{
|
||||
e.Graphics.FillPolygon(brush,
|
||||
new[]
|
||||
{
|
||||
new Point(left + 5, top + 0),
|
||||
new Point(left + 0, top + height),
|
||||
new Point(left + 10, top + height)
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawDisabled(PaintEventArgs e)
|
||||
{
|
||||
using (var brushBg = new SolidBrush(BackColorDisabled))
|
||||
{
|
||||
e.Graphics.FillRectangle(brushBg, e.ClipRectangle);
|
||||
}
|
||||
|
||||
using (var pen = new Pen(BorderColorDisabled, 1f))
|
||||
{
|
||||
var borderRectangle = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
|
||||
e.Graphics.DrawRectangle(pen, borderRectangle);
|
||||
}
|
||||
|
||||
var left = RightToLeft == RightToLeft.Yes ? 3 : e.ClipRectangle.Width - ButtonsWidth;
|
||||
var height = e.ClipRectangle.Height / 2 - 4;
|
||||
var top = 2;
|
||||
using (var brush = new SolidBrush(BorderColorDisabled))
|
||||
{
|
||||
DrawArrowUp(e, brush, left, top, height);
|
||||
top = height + 5;
|
||||
DrawArrowDown(e, brush, left, top, height);
|
||||
}
|
||||
}
|
||||
|
||||
private static char[] GetSplitChars()
|
||||
{
|
||||
var splitChars = new List<char> { ':', ',', '.' };
|
||||
string cultureSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||
if (cultureSeparator.Length == 1)
|
||||
{
|
||||
var ch = Convert.ToChar(cultureSeparator);
|
||||
if (!splitChars.Contains(ch))
|
||||
{
|
||||
splitChars.Add(ch);
|
||||
}
|
||||
}
|
||||
return splitChars.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
615
src/ui/Controls/NikseUpDown.cs
Normal file
615
src/ui/Controls/NikseUpDown.cs
Normal file
@ -0,0 +1,615 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Controls
|
||||
{
|
||||
[Category("NikseUpDown"), Description("Numeric Up/Down with better support for color theme")]
|
||||
public sealed class NikseUpDown : Control
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public event EventHandler ValueChanged;
|
||||
|
||||
private decimal _value;
|
||||
|
||||
[Category("NikseUpDown"), Description("Gets or sets the default value in textBox"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public decimal Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
if (DecimalPlaces == 0)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
else if (DecimalPlaces > 0)
|
||||
{
|
||||
_value = Math.Round(value, DecimalPlaces);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private int _decimalPlaces;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the decimal places (max 4)")]
|
||||
public int DecimalPlaces
|
||||
{
|
||||
get => _decimalPlaces;
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
_decimalPlaces = 0;
|
||||
}
|
||||
else if (value > 3)
|
||||
{
|
||||
_decimalPlaces = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
_decimalPlaces = value;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _thousandsSeparator;
|
||||
|
||||
[Category("NikseUpDown"), Description("Gets or sets the thousand seperator")]
|
||||
public bool ThousandsSeparator
|
||||
{
|
||||
get => _thousandsSeparator;
|
||||
set
|
||||
{
|
||||
_thousandsSeparator = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("NikseUpDown"), Description("Gets or sets the increment value")]
|
||||
public decimal Increment { get; set; } = 1;
|
||||
|
||||
[Category("NikseUpDown"), Description("Gets or sets the Maximum value (max 25 significant digits)")]
|
||||
public decimal Maximum { get; set; } = 100;
|
||||
|
||||
[Category("NikseUpDown"), Description("Gets or sets the Minimum value")]
|
||||
public decimal Minimum { get; set; } = 0;
|
||||
|
||||
[Category("NikseUpDown"), Description("Allow arrow keys to set increment/decrement value")]
|
||||
[DefaultValue(true)]
|
||||
public bool InterceptArrowKeys { get; set; }
|
||||
|
||||
private Color _buttonForeColor;
|
||||
private Brush _buttonForeColorBrush;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the button foreground color"),
|
||||
RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColor
|
||||
{
|
||||
get => _buttonForeColor;
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColor = value;
|
||||
_buttonForeColorBrush?.Dispose();
|
||||
_buttonForeColorBrush = new SolidBrush(_buttonForeColor);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _buttonForeColorOver;
|
||||
private Brush _buttonForeColorOverBrush;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the button foreground mouse over color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColorOver
|
||||
{
|
||||
get => _buttonForeColorOver;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColorOver = value;
|
||||
_buttonForeColorOverBrush?.Dispose();
|
||||
_buttonForeColorOverBrush = new SolidBrush(_buttonForeColorOver);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _buttonForeColorDown;
|
||||
private Brush _buttonForeColorDownBrush;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the button foreground mouse down color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color ButtonForeColorDown
|
||||
{
|
||||
get => _buttonForeColorDown;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonForeColorDown = value;
|
||||
_buttonForeColorDownBrush?.Dispose();
|
||||
_buttonForeColorDownBrush = new SolidBrush(_buttonForeColorDown);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _borderColor;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the border color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BorderColor
|
||||
{
|
||||
get => _borderColor;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_borderColor = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _backColorDisabled;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the button foreground color"),
|
||||
RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BackColorDisabled
|
||||
{
|
||||
get => _backColorDisabled;
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_backColorDisabled = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private Color _borderColorDisabled;
|
||||
[Category("NikseUpDown"), Description("Gets or sets the disabled border color"), RefreshProperties(RefreshProperties.Repaint)]
|
||||
public Color BorderColorDisabled
|
||||
{
|
||||
get => _borderColorDisabled;
|
||||
|
||||
set
|
||||
{
|
||||
if (value.A == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_borderColorDisabled = value;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly TextBox _textBox;
|
||||
|
||||
public NikseUpDown()
|
||||
{
|
||||
_textBox = new TextBox();
|
||||
_textBox.KeyPress += TextBox_KeyPress;
|
||||
_textBox.KeyDown += (sender, e) =>
|
||||
{
|
||||
if (InterceptArrowKeys && e.KeyCode == Keys.Down)
|
||||
{
|
||||
AddValue(-Increment);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (InterceptArrowKeys && e.KeyCode == Keys.Up)
|
||||
{
|
||||
AddValue(Increment);
|
||||
e.Handled = true;
|
||||
}
|
||||
};
|
||||
_textBox.LostFocus += (sender, args) => Invalidate();
|
||||
_textBox.GotFocus += (sender, args) => Invalidate();
|
||||
_textBox.TextChanged += _textBox_TextChanged;
|
||||
_textBox.BorderStyle = BorderStyle.None;
|
||||
|
||||
Controls.Add(_textBox);
|
||||
BackColor = new TextBox().BackColor;
|
||||
ButtonForeColor = DefaultForeColor;
|
||||
ButtonForeColorOver = Color.FromArgb(0, 120, 215);
|
||||
ButtonForeColorDown = Color.Orange;
|
||||
BorderColor = Color.FromArgb(171, 173, 179);
|
||||
BorderColorDisabled = Color.FromArgb(120, 120, 120);
|
||||
BackColorDisabled = Color.FromArgb(240, 240, 240);
|
||||
DoubleBuffered = true;
|
||||
InterceptArrowKeys = true;
|
||||
|
||||
_repeatTimer = new Timer();
|
||||
_repeatTimer.Tick += (sender, args) =>
|
||||
{
|
||||
if (_repeatTimerArrowUp)
|
||||
{
|
||||
AddValue(Increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddValue(-Increment);
|
||||
}
|
||||
|
||||
_repeatCount++;
|
||||
_repeatTimer.Interval = _repeatCount < 8 ? 75 : 10;
|
||||
};
|
||||
|
||||
LostFocus += (sender, args) => _repeatTimer.Stop();
|
||||
}
|
||||
|
||||
private void _textBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (decimal.TryParse(_textBox.Text, out var result))
|
||||
{
|
||||
Value = Math.Round(result, DecimalPlaces);
|
||||
|
||||
if (Value < Minimum)
|
||||
{
|
||||
Value = Minimum;
|
||||
Invalidate();
|
||||
}
|
||||
else if (Value > Maximum)
|
||||
{
|
||||
Value = Maximum;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow only digits, Enter and Backspace key.
|
||||
/// </summary>
|
||||
private void TextBox_KeyPress(object sender, KeyPressEventArgs e)
|
||||
{
|
||||
if (e.KeyChar == (char)Keys.Enter)
|
||||
{
|
||||
AddValue(0);
|
||||
e.Handled = false;
|
||||
}
|
||||
else if (char.IsDigit(e.KeyChar) || e.KeyChar == (char)Keys.Back)
|
||||
{
|
||||
e.Handled = false;
|
||||
}
|
||||
else if (e.KeyChar == '.' || e.KeyChar == ',')
|
||||
{
|
||||
e.Handled = !(DecimalPlaces > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment or decrement the TextBox value.
|
||||
/// </summary>
|
||||
/// <param name="value">Value to increment/decrement</param>
|
||||
private void AddValue(decimal value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_textBox.Text))
|
||||
{
|
||||
Value = 0 >= Minimum && 0 <= Maximum ? 0 : Minimum;
|
||||
SetText();
|
||||
ValueChanged?.Invoke(this, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_textBox.TextLength > 25)
|
||||
{
|
||||
Value = Maximum;
|
||||
SetText();
|
||||
ValueChanged?.Invoke(this, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (decimal.TryParse(_textBox.Text, out var result))
|
||||
{
|
||||
Value = Math.Round(result + value, DecimalPlaces);
|
||||
|
||||
if (Value < Minimum)
|
||||
{
|
||||
Value = Minimum;
|
||||
}
|
||||
else if (Value > Maximum)
|
||||
{
|
||||
Value = Maximum;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetText();
|
||||
ValueChanged?.Invoke(this, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetText();
|
||||
ValueChanged?.Invoke(this, null);
|
||||
}
|
||||
|
||||
private bool _buttonUpActive;
|
||||
private bool _buttonDownActive;
|
||||
|
||||
private bool _buttonLeftIsDown;
|
||||
|
||||
private int _mouseX;
|
||||
private int _mouseY;
|
||||
|
||||
private readonly Timer _repeatTimer;
|
||||
private bool _repeatTimerArrowUp;
|
||||
private int _repeatCount;
|
||||
|
||||
protected override void OnMouseEnter(EventArgs e)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
base.OnMouseEnter(e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
base.OnMouseLeave(e);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
_buttonLeftIsDown = true;
|
||||
|
||||
if (_buttonUpActive)
|
||||
{
|
||||
AddValue(Increment);
|
||||
_repeatTimerArrowUp = true;
|
||||
_repeatTimer.Interval = 300;
|
||||
_repeatCount = 0;
|
||||
_repeatTimer.Start();
|
||||
}
|
||||
else if (_buttonDownActive)
|
||||
{
|
||||
AddValue(-Increment);
|
||||
_repeatTimerArrowUp = false;
|
||||
_repeatTimer.Interval = 300;
|
||||
_repeatCount = 0;
|
||||
_repeatTimer.Start();
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
_repeatTimer.Stop();
|
||||
|
||||
if (_buttonLeftIsDown)
|
||||
{
|
||||
_buttonLeftIsDown = false;
|
||||
Invalidate();
|
||||
}
|
||||
base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
var left = RightToLeft == RightToLeft.Yes ? 0 : Width - ButtonsWidth;
|
||||
var right = RightToLeft == RightToLeft.Yes ? ButtonsWidth : Width;
|
||||
var height = Height / 2 - 3;
|
||||
const int top = 2;
|
||||
|
||||
_mouseX = e.X;
|
||||
_mouseY = e.Y;
|
||||
|
||||
if (_mouseX >= left && _mouseX <= right)
|
||||
{
|
||||
if (_mouseY > top + height)
|
||||
{
|
||||
if (!_buttonDownActive)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = true;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_buttonUpActive)
|
||||
{
|
||||
_buttonUpActive = true;
|
||||
_buttonDownActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_buttonUpActive || _buttonDownActive)
|
||||
{
|
||||
_buttonUpActive = false;
|
||||
_buttonDownActive = false;
|
||||
Invalidate();
|
||||
}
|
||||
_repeatTimer.Stop();
|
||||
}
|
||||
|
||||
base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
private const int ButtonsWidth = 13;
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
_textBox.BackColor = BackColor;
|
||||
_textBox.ForeColor = ButtonForeColor;
|
||||
_textBox.Top = 2;
|
||||
_textBox.Left = RightToLeft == RightToLeft.Yes ? ButtonsWidth : 3;
|
||||
_textBox.Height = Height - 4;
|
||||
_textBox.Width = Width - ButtonsWidth - 3;
|
||||
SetText();
|
||||
|
||||
if (!Enabled)
|
||||
{
|
||||
DrawDisabled(e);
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnPaint(e);
|
||||
using (var pen = _textBox.Focused ? new Pen(_buttonForeColorOver, 1f) : new Pen(BorderColor, 1f))
|
||||
{
|
||||
var borderRectangle = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
|
||||
e.Graphics.DrawRectangle(pen, borderRectangle);
|
||||
}
|
||||
|
||||
var brush = _buttonForeColorBrush;
|
||||
var left = RightToLeft == RightToLeft.Yes ? 3 : Width - ButtonsWidth;
|
||||
var height = e.ClipRectangle.Height / 2 - 4;
|
||||
var top = 2;
|
||||
if (_buttonUpActive)
|
||||
{
|
||||
brush = _buttonLeftIsDown ? _buttonForeColorDownBrush : _buttonForeColorOverBrush;
|
||||
}
|
||||
|
||||
DrawArrowUp(e, brush, left, top, height);
|
||||
|
||||
if (_buttonDownActive)
|
||||
{
|
||||
brush = _buttonLeftIsDown ? _buttonForeColorDownBrush : _buttonForeColorOverBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
brush = _buttonForeColorBrush;
|
||||
}
|
||||
|
||||
top = height + 5;
|
||||
DrawArrowDown(e, brush, left, top, height);
|
||||
}
|
||||
|
||||
public override RightToLeft RightToLeft
|
||||
{
|
||||
get => base.RightToLeft;
|
||||
set
|
||||
{
|
||||
base.RightToLeft = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color ForeColor
|
||||
{
|
||||
get => base.ForeColor;
|
||||
set
|
||||
{
|
||||
base.ForeColor = value;
|
||||
_textBox.ForeColor = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override Color BackColor
|
||||
{
|
||||
get => base.BackColor;
|
||||
set
|
||||
{
|
||||
base.BackColor = value;
|
||||
_textBox.BackColor = value;
|
||||
Application.DoEvents();
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetText()
|
||||
{
|
||||
if (DecimalPlaces <= 0)
|
||||
{
|
||||
_textBox.Text = ThousandsSeparator ? $"{Value:#,###,##0}" : $"{Value:########0}";
|
||||
}
|
||||
else if (DecimalPlaces == 1)
|
||||
{
|
||||
_textBox.Text = ThousandsSeparator ? $"{Value:#,###,##0.0}" : $"{Value:########0.0}";
|
||||
}
|
||||
else if (DecimalPlaces == 2)
|
||||
{
|
||||
_textBox.Text = ThousandsSeparator ? $"{Value:#,###,##0.00}" : $"{Value:#########0.00}";
|
||||
}
|
||||
else if (DecimalPlaces == 3)
|
||||
{
|
||||
_textBox.Text = ThousandsSeparator ? $"{Value:#,###,##0.000}" : $"{Value:#########0.000}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_textBox.Text = ThousandsSeparator ? $"{Value:#,###,##0.0000}" : $"{Value:#########0.0000}";
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawArrowDown(PaintEventArgs e, Brush brush, int left, int top, int height)
|
||||
{
|
||||
e.Graphics.FillPolygon(brush,
|
||||
new[]
|
||||
{
|
||||
new Point(left + 5, top + height),
|
||||
new Point(left + 0, top + 0),
|
||||
new Point(left + 10, top + 0)
|
||||
});
|
||||
}
|
||||
|
||||
private static void DrawArrowUp(PaintEventArgs e, Brush brush, int left, int top, int height)
|
||||
{
|
||||
e.Graphics.FillPolygon(brush,
|
||||
new[]
|
||||
{
|
||||
new Point(left + 5, top + 0),
|
||||
new Point(left + 0, top + height),
|
||||
new Point(left + 10, top + height)
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawDisabled(PaintEventArgs e)
|
||||
{
|
||||
using (var brushBg = new SolidBrush(BackColorDisabled))
|
||||
{
|
||||
e.Graphics.FillRectangle(brushBg, e.ClipRectangle);
|
||||
}
|
||||
|
||||
using (var pen = new Pen(BorderColorDisabled, 1f))
|
||||
{
|
||||
var borderRectangle = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
|
||||
e.Graphics.DrawRectangle(pen, borderRectangle);
|
||||
}
|
||||
|
||||
var left = RightToLeft == RightToLeft.Yes ? 3 : e.ClipRectangle.Width - ButtonsWidth;
|
||||
var height = e.ClipRectangle.Height / 2 - 4;
|
||||
var top = 2;
|
||||
using (var brush = new SolidBrush(BorderColorDisabled))
|
||||
{
|
||||
DrawArrowUp(e, brush, left, top, height);
|
||||
top = height + 5;
|
||||
DrawArrowDown(e, brush, left, top, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
src/ui/Forms/Main.Designer.cs
generated
42
src/ui/Forms/Main.Designer.cs
generated
@ -542,8 +542,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
this.labelTextLineTotal = new System.Windows.Forms.Label();
|
||||
this.labelCharactersPerSecond = new System.Windows.Forms.Label();
|
||||
this.buttonUnBreak = new System.Windows.Forms.Button();
|
||||
this.timeUpDownStartTime = new Nikse.SubtitleEdit.Controls.TimeUpDown();
|
||||
this.numericUpDownDuration = new System.Windows.Forms.NumericUpDown();
|
||||
this.timeUpDownStartTime = new Nikse.SubtitleEdit.Controls.NikseTimeUpDown();
|
||||
this.numericUpDownDuration = new Nikse.SubtitleEdit.Controls.NikseUpDown();
|
||||
this.buttonPrevious = new System.Windows.Forms.Button();
|
||||
this.buttonNext = new System.Windows.Forms.Button();
|
||||
this.labelStartTime = new System.Windows.Forms.Label();
|
||||
@ -616,7 +616,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
this.panelBookmark.SuspendLayout();
|
||||
this.contextMenuStripTextBoxListView.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBookmark)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDuration)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxRecord)).BeginInit();
|
||||
this.contextMenuStripTextBoxSourceView.SuspendLayout();
|
||||
this.panelVideoPlayer.SuspendLayout();
|
||||
@ -5302,15 +5301,24 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
//
|
||||
// timeUpDownStartTime
|
||||
//
|
||||
this.timeUpDownStartTime.AutoSize = true;
|
||||
this.timeUpDownStartTime.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.timeUpDownStartTime.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.timeUpDownStartTime.BackColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
||||
this.timeUpDownStartTime.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179)))));
|
||||
this.timeUpDownStartTime.BorderColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(120)))), ((int)(((byte)(120)))));
|
||||
this.timeUpDownStartTime.ButtonForeColor = System.Drawing.SystemColors.ControlText;
|
||||
this.timeUpDownStartTime.ButtonForeColorDown = System.Drawing.Color.Orange;
|
||||
this.timeUpDownStartTime.ButtonForeColorOver = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
|
||||
this.timeUpDownStartTime.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F);
|
||||
this.timeUpDownStartTime.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(155)))), ((int)(((byte)(155)))), ((int)(((byte)(155)))));
|
||||
this.timeUpDownStartTime.Increment = new decimal(new int[] {
|
||||
100,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.timeUpDownStartTime.Location = new System.Drawing.Point(8, 26);
|
||||
this.timeUpDownStartTime.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.timeUpDownStartTime.Name = "timeUpDownStartTime";
|
||||
this.timeUpDownStartTime.Size = new System.Drawing.Size(113, 27);
|
||||
this.timeUpDownStartTime.Size = new System.Drawing.Size(113, 21);
|
||||
this.timeUpDownStartTime.TabIndex = 0;
|
||||
timeCode3.Hours = 0;
|
||||
timeCode3.Milliseconds = 0;
|
||||
@ -5324,13 +5332,20 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
//
|
||||
// numericUpDownDuration
|
||||
//
|
||||
this.numericUpDownDuration.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.numericUpDownDuration.BackColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
||||
this.numericUpDownDuration.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179)))));
|
||||
this.numericUpDownDuration.BorderColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(120)))), ((int)(((byte)(120)))));
|
||||
this.numericUpDownDuration.ButtonForeColor = System.Drawing.SystemColors.ControlText;
|
||||
this.numericUpDownDuration.ButtonForeColorDown = System.Drawing.Color.Orange;
|
||||
this.numericUpDownDuration.ButtonForeColorOver = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
|
||||
this.numericUpDownDuration.DecimalPlaces = 3;
|
||||
this.numericUpDownDuration.Increment = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
65536});
|
||||
this.numericUpDownDuration.Location = new System.Drawing.Point(122, 27);
|
||||
this.numericUpDownDuration.Location = new System.Drawing.Point(122, 26);
|
||||
this.numericUpDownDuration.Maximum = new decimal(new int[] {
|
||||
999999999,
|
||||
0,
|
||||
@ -5342,8 +5357,14 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
0,
|
||||
-2147483648});
|
||||
this.numericUpDownDuration.Name = "numericUpDownDuration";
|
||||
this.numericUpDownDuration.Size = new System.Drawing.Size(56, 20);
|
||||
this.numericUpDownDuration.Size = new System.Drawing.Size(56, 21);
|
||||
this.numericUpDownDuration.TabIndex = 1;
|
||||
this.numericUpDownDuration.ThousandsSeparator = false;
|
||||
this.numericUpDownDuration.Value = new decimal(new int[] {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
196608});
|
||||
this.numericUpDownDuration.ValueChanged += new System.EventHandler(this.NumericUpDownDurationValueChanged);
|
||||
//
|
||||
// buttonPrevious
|
||||
@ -5733,7 +5754,6 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
this.panelBookmark.PerformLayout();
|
||||
this.contextMenuStripTextBoxListView.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxBookmark)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.numericUpDownDuration)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxRecord)).EndInit();
|
||||
this.contextMenuStripTextBoxSourceView.ResumeLayout(false);
|
||||
this.panelVideoPlayer.ResumeLayout(false);
|
||||
@ -5816,14 +5836,14 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private System.Windows.Forms.Button buttonAutoBreak;
|
||||
private System.Windows.Forms.ToolStripMenuItem removeFormattinglToolStripMenuItem;
|
||||
private System.Windows.Forms.Label labelTextLineLengths;
|
||||
private System.Windows.Forms.NumericUpDown numericUpDownDuration;
|
||||
private Nikse.SubtitleEdit.Controls.NikseUpDown numericUpDownDuration;
|
||||
private System.Windows.Forms.Label labelStartTimeWarning;
|
||||
private System.Windows.Forms.Button buttonUnBreak;
|
||||
private System.Windows.Forms.ToolStripMenuItem colorToolStripMenuItem;
|
||||
private System.Windows.Forms.Label labelTextLineTotal;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator10;
|
||||
private Nikse.SubtitleEdit.Controls.TimeUpDown timeUpDownStartTime;
|
||||
private Nikse.SubtitleEdit.Controls.NikseTimeUpDown timeUpDownStartTime;
|
||||
private System.Windows.Forms.ToolStripMenuItem ChangeCasingToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemMergeLines;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSortBy;
|
||||
|
6
src/ui/Forms/Options/Settings.Designer.cs
generated
6
src/ui/Forms/Options/Settings.Designer.cs
generated
@ -4689,9 +4689,9 @@
|
||||
this.groupBoxGraphicsButtons.Controls.Add(this.pictureBoxPreview1);
|
||||
this.groupBoxGraphicsButtons.Controls.Add(this.labelToolbarIconTheme);
|
||||
this.groupBoxGraphicsButtons.Controls.Add(this.comboBoxToolbarIconTheme);
|
||||
this.groupBoxGraphicsButtons.Location = new System.Drawing.Point(383, 310);
|
||||
this.groupBoxGraphicsButtons.Location = new System.Drawing.Point(383, 307);
|
||||
this.groupBoxGraphicsButtons.Name = "groupBoxGraphicsButtons";
|
||||
this.groupBoxGraphicsButtons.Size = new System.Drawing.Size(461, 109);
|
||||
this.groupBoxGraphicsButtons.Size = new System.Drawing.Size(461, 114);
|
||||
this.groupBoxGraphicsButtons.TabIndex = 41;
|
||||
this.groupBoxGraphicsButtons.TabStop = false;
|
||||
this.groupBoxGraphicsButtons.Text = "Graphics buttons";
|
||||
@ -5414,8 +5414,8 @@
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1092, 574);
|
||||
this.Controls.Add(this.labelUpdateFileTypeAssociationsStatus);
|
||||
this.Controls.Add(this.panelVideoPlayer);
|
||||
this.Controls.Add(this.panelFont);
|
||||
this.Controls.Add(this.panelVideoPlayer);
|
||||
this.Controls.Add(this.panelToolBar);
|
||||
this.Controls.Add(this.panelTools);
|
||||
this.Controls.Add(this.panelWaveform);
|
||||
|
@ -3,7 +3,7 @@
|
||||
<General>
|
||||
<Title>Subtitle Edit</Title>
|
||||
<Version>3.6.13</Version>
|
||||
<TranslatedBy>Tradotto da NAMP e bovirus - Data traduzione: 13.07.2023</TranslatedBy>
|
||||
<TranslatedBy>Tradotto da NAMP e bovirus - Data traduzione: 15.07.2023</TranslatedBy>
|
||||
<CultureName>it-IT</CultureName>
|
||||
<HelpFile />
|
||||
<Ok>OK</Ok>
|
||||
@ -2840,7 +2840,7 @@ Vuoi continuare?</RestoreDefaultSettingsMsg>
|
||||
<NumberOfBoldTags>Numero tag grassetto: {0}</NumberOfBoldTags>
|
||||
<NumberOfUnderlineTags>Numero tag sottolineatura: {0}</NumberOfUnderlineTags>
|
||||
<NumberOfFontTags>Numero tag per font: {0}</NumberOfFontTags>
|
||||
<NumberOfAlignmentTags>Numero di tag allineamento: {0}</NumberOfAlignmentTags>
|
||||
<NumberOfAlignmentTags>Numero tag allineamento: {0}</NumberOfAlignmentTags>
|
||||
<LineLengthMinimum>Lunghezza sottotitolo - minima: {0}</LineLengthMinimum>
|
||||
<LineLengthMaximum>Lunghezza sottotitolo - massima: {0}</LineLengthMaximum>
|
||||
<LineLengthAverage>Lunghezza sottotitolo - media: {0}</LineLengthAverage>
|
||||
@ -2848,18 +2848,29 @@ Vuoi continuare?</RestoreDefaultSettingsMsg>
|
||||
<SingleLineLengthMinimum>Lunghezza riga singola - minimo: {0}</SingleLineLengthMinimum>
|
||||
<SingleLineLengthMaximum>Lunghezza riga singola - massima: {0}</SingleLineLengthMaximum>
|
||||
<SingleLineLengthAverage>Lunghezza riga singola - media: {0}</SingleLineLengthAverage>
|
||||
<SingleLineWidthMinimum>Larghezza riga singola - minima: {0} pixels</SingleLineWidthMinimum>
|
||||
<SingleLineWidthMaximum>Larghezza riga singola - massima: {0} pixels</SingleLineWidthMaximum>
|
||||
<SingleLineWidthAverage>Larghezza riga singola - media: {0} pixels</SingleLineWidthAverage>
|
||||
<SingleLineLengthExceedingMaximum>Lunghezza riga singola - superiore al massimo ({0} caratteri): {1} ({2:0.00}%)</SingleLineLengthExceedingMaximum>
|
||||
<SingleLineWidthMinimum>Larghezza riga singola - minima: {0} pixel</SingleLineWidthMinimum>
|
||||
<SingleLineWidthMaximum>Larghezza riga singola - massima: {0} pixel</SingleLineWidthMaximum>
|
||||
<SingleLineWidthExceedingMaximum>Larghezza riga singola - superiore al massimo ({0} pixel): {1} ({2:0.00}%)</SingleLineWidthExceedingMaximum>
|
||||
<SingleLineWidthAverage>Larghezza riga singola - media: {0} pixel</SingleLineWidthAverage>
|
||||
<DurationMinimum>Durata - minima: {0:0.000} secondi</DurationMinimum>
|
||||
<DurationMaximum>Durata - massima: {0:0.000} secondi</DurationMaximum>
|
||||
<DurationAverage>Durata - media: {0:0.000} secondi</DurationAverage>
|
||||
<DurationExceedingMinimum>Durata - inferiore al minimo ({0:0.###} sec): {1} ({2:0.00}%)</DurationExceedingMinimum>
|
||||
<DurationExceedingMaximum>Durata - superiore al massimo ({0:0.###} sec): {1} ({2:0.00}%)</DurationExceedingMaximum>
|
||||
<CharactersPerSecondMinimum>Caratteri/sec - minimuo: {0:0.000}</CharactersPerSecondMinimum>
|
||||
<CharactersPerSecondMaximum>Caratteri/sec - massimo: {0:0.000}</CharactersPerSecondMaximum>
|
||||
<CharactersPerSecondAverage>Caratteri/sec - media: {0:0.000}</CharactersPerSecondAverage>
|
||||
<CharactersPerSecondExceedingOptimal>Caratteri/sec - superiore ad ottimale ({0:0.##} cps): {1} ({2:0.00}%)</CharactersPerSecondExceedingOptimal>
|
||||
<CharactersPerSecondExceedingMaximum>Caratteri/sec - superiore al massimo ({0:0.##} cps): {1} ({2:0.00}%)</CharactersPerSecondExceedingMaximum>
|
||||
<WordsPerMinuteMinimum>Parole/min - minimo: {0:0.000}</WordsPerMinuteMinimum>
|
||||
<WordsPerMinuteMaximum>Parole/min - massimo: {0:0.000}</WordsPerMinuteMaximum>
|
||||
<WordsPerMinuteAverage>Parole/min - media: {0:0.000}</WordsPerMinuteAverage>
|
||||
<WordsPerMinuteExceedingMaximum>Words/min - exceeding maximum ({0} wpm): {1} ({2:0.00}%)</WordsPerMinuteExceedingMaximum>
|
||||
<GapMinimum>Gap - minimo: {0:#,##0} ms</GapMinimum>
|
||||
<GapMaximum>Gap - massimo: {0:#,##0} ms</GapMaximum>
|
||||
<GapAverage>Gap - media: {0:#,##0.##} ms</GapAverage>
|
||||
<GapExceedingMinimum>Gap - inferiore al minimo ({0:#,##0} ms): {1} ({2:0.00}%)</GapExceedingMinimum>
|
||||
<Export>Esporta...</Export>
|
||||
</Statistics>
|
||||
<SubStationAlphaProperties>
|
||||
|
@ -2411,6 +2411,7 @@ FFmpeg를 다운로드하고 사용하시겠습니까?</FfmpegNotFound>
|
||||
<DarkTheme>어두운 테마</DarkTheme>
|
||||
<DarkThemeEnabled>어두운 테마 사용</DarkThemeEnabled>
|
||||
<DarkThemeShowGridViewLines>목록 보기 그리드 선 표시</DarkThemeShowGridViewLines>
|
||||
<GraphicsButtons>그래픽 버튼</GraphicsButtons>
|
||||
<UpdateShortcut>업데이트</UpdateShortcut>
|
||||
<FoucsSetVideoPosition>초점에 비디오 위치 설정</FoucsSetVideoPosition>
|
||||
<ToggleDockUndockOfVideoControls>비디오 컨트롤 연결 | 해제</ToggleDockUndockOfVideoControls>
|
||||
@ -2846,18 +2847,29 @@ FFmpeg를 다운로드하고 사용하시겠습니까?</FfmpegNotFound>
|
||||
<SingleLineLengthMinimum>한 줄의 길이 - 최소: {0}</SingleLineLengthMinimum>
|
||||
<SingleLineLengthMaximum>한 줄의 길이 - 최대: {0}</SingleLineLengthMaximum>
|
||||
<SingleLineLengthAverage>한 줄의 길이 - 평균: {0}</SingleLineLengthAverage>
|
||||
<SingleLineLengthExceedingMaximum>한 줄의 길이 - 최대값 초과 ({0} 문자): {1} ({2:0.00}%)</SingleLineLengthExceedingMaximum>
|
||||
<SingleLineWidthMinimum>한 줄의 너비 - 최소: {0} 픽셀</SingleLineWidthMinimum>
|
||||
<SingleLineWidthMaximum>한 줄의 너비 - 최대: {0} 픽셀</SingleLineWidthMaximum>
|
||||
<SingleLineWidthAverage>한 줄의 너비 - 평균: {0} 픽셀</SingleLineWidthAverage>
|
||||
<SingleLineWidthExceedingMaximum>한 줄의 너비 - 최대값 초과 ({0} 픽셀): {1} ({2:0.00}%)</SingleLineWidthExceedingMaximum>
|
||||
<DurationMinimum>표시시간 - 최소: {0:0.000}초</DurationMinimum>
|
||||
<DurationMaximum>표시시간 - 최대: {0:0.000}초</DurationMaximum>
|
||||
<DurationAverage>표시시간 - 평균: {0:0.000}초</DurationAverage>
|
||||
<DurationExceedingMinimum>표시시간 - 최소값 미만 ({0:0.###} 초): {1} ({2:0.00}%)</DurationExceedingMinimum>
|
||||
<DurationExceedingMaximum>표시시간 - 최대값 초과 ({0:0.###} 초): {1} ({2:0.00}%)</DurationExceedingMaximum>
|
||||
<CharactersPerSecondMinimum>문자/초 - 최소: {0:0.000}</CharactersPerSecondMinimum>
|
||||
<CharactersPerSecondMaximum>문자/초 - 최대: {0:0.000}</CharactersPerSecondMaximum>
|
||||
<CharactersPerSecondAverage>문자/초 - 평균: {0:0.000}</CharactersPerSecondAverage>
|
||||
<CharactersPerSecondExceedingOptimal>문자/초 - 최적값 초과 ({0:0.##} cps): {1} ({2:0.00}%)</CharactersPerSecondExceedingOptimal>
|
||||
<CharactersPerSecondExceedingMaximum>문자/초 - 최대값 초과 ({0:0.##} cps): {1} ({2:0.00}%)</CharactersPerSecondExceedingMaximum>
|
||||
<WordsPerMinuteMinimum>단어/분 - 최소: {0:0.000}</WordsPerMinuteMinimum>
|
||||
<WordsPerMinuteMaximum>단어/분 - 최대: {0:0.000}</WordsPerMinuteMaximum>
|
||||
<WordsPerMinuteAverage>단어/분 - 평균: {0:0.000}</WordsPerMinuteAverage>
|
||||
<WordsPerMinuteExceedingMaximum>단어/분 - 최대값 초과 ({0} wpm): {1} ({2:0.00}%)</WordsPerMinuteExceedingMaximum>
|
||||
<GapMinimum>간격 - 최소: {0:#,##0} 밀리초</GapMinimum>
|
||||
<GapMaximum>간격 - 최대: {0:#,##0} 밀리초</GapMaximum>
|
||||
<GapAverage>간격 - 평균: {0:#,##0.##} 밀리초</GapAverage>
|
||||
<GapExceedingMinimum>간격 - 최소값 미만 ({0:#,##0} ms): {1} ({2:0.00}%)</GapExceedingMinimum>
|
||||
<Export>내보내기</Export>
|
||||
</Statistics>
|
||||
<SubStationAlphaProperties>
|
||||
@ -3219,4 +3231,9 @@ FFmpeg를 다운로드하고 사용하시겠습니까?</FfmpegNotFound>
|
||||
<WebVttStyleManager>
|
||||
<Title>WebVTT 스타일</Title>
|
||||
</WebVttStyleManager>
|
||||
<WhisperAdvanced>
|
||||
<Title>Whisper Advanced - 추가 명령줄 인수</Title>
|
||||
<CommandLineArguments>Whisper 명령줄에 대한 추가 매개변수:</CommandLineArguments>
|
||||
<Info>참고: Whisper 구현에 따라 명령줄 매개 변수는 다릅니다!</Info>
|
||||
</WhisperAdvanced>
|
||||
</Language>
|
@ -11,8 +11,8 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
{
|
||||
public static class DarkTheme
|
||||
{
|
||||
internal static readonly Color BackColor = Configuration.Settings.General.DarkThemeBackColor;
|
||||
internal static readonly Color ForeColor = Configuration.Settings.General.DarkThemeForeColor;
|
||||
public static Color BackColor => Configuration.Settings.General.DarkThemeBackColor;
|
||||
public static Color ForeColor => Configuration.Settings.General.DarkThemeForeColor;
|
||||
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
|
||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
@ -264,11 +264,16 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
c.BackColor = Control.DefaultBackColor;
|
||||
c.ForeColor = Control.DefaultForeColor;
|
||||
|
||||
var newButton = new TextBox();
|
||||
var buttonBackColor = newButton.BackColor;
|
||||
newButton.Dispose();
|
||||
|
||||
if (c is Button b)
|
||||
{
|
||||
b.FlatStyle = FlatStyle.Standard;
|
||||
b.EnabledChanged -= Button_EnabledChanged;
|
||||
b.Paint -= Button_Paint;
|
||||
b.BackColor = buttonBackColor;
|
||||
}
|
||||
|
||||
if (c is CheckBox cb)
|
||||
@ -354,6 +359,21 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
lv.EnabledChanged -= ListView_EnabledChanged;
|
||||
lv.HandleCreated -= ListView_HandleCreated;
|
||||
}
|
||||
else if (c is NikseUpDown)
|
||||
{
|
||||
c.BackColor = buttonBackColor;
|
||||
c.ForeColor = Control.DefaultForeColor;
|
||||
}
|
||||
else if (c is NikseTimeUpDown)
|
||||
{
|
||||
c.BackColor = buttonBackColor;
|
||||
c.ForeColor = Control.DefaultForeColor;
|
||||
}
|
||||
|
||||
if (c is Button bu)
|
||||
{
|
||||
bu.BackColor = buttonBackColor;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixControl(Control c)
|
||||
@ -451,6 +471,20 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
lv.EnabledChanged += ListView_EnabledChanged;
|
||||
lv.HandleCreated += ListView_HandleCreated;
|
||||
}
|
||||
else if (c is NikseUpDown ud)
|
||||
{
|
||||
ud.BackColor = BackColor;
|
||||
ud.ForeColor = ForeColor;
|
||||
ud.ButtonForeColor = ForeColor;
|
||||
ud.BackColorDisabled = BackColor;
|
||||
}
|
||||
else if (c is NikseTimeUpDown tud)
|
||||
{
|
||||
tud.BackColor = BackColor;
|
||||
tud.ForeColor = ForeColor;
|
||||
tud.ButtonForeColor = ForeColor;
|
||||
tud.BackColorDisabled = BackColor;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Button_EnabledChanged(object sender, EventArgs e)
|
||||
|
@ -109,6 +109,12 @@
|
||||
<Compile Include="Controls\CuesPreviewView.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\NikseTimeUpDown.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\NikseUpDown.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Controls\SETextBox.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
|
Loading…
x
Reference in New Issue
Block a user