diff --git a/JL.Core/Anki/JLField.cs b/JL.Core/Anki/JLField.cs index e60ab8f7..46e6c589 100644 --- a/JL.Core/Anki/JLField.cs +++ b/JL.Core/Anki/JLField.cs @@ -9,6 +9,7 @@ public enum JLField [Description("Primary Spelling")] PrimarySpelling, Readings, Definitions, + [Description("Selected Definitions")] SelectedDefinitions, [Description("Dictionary Name")] DictionaryName, Audio, Image, diff --git a/JL.Core/Anki/JLFieldUtils.cs b/JL.Core/Anki/JLFieldUtils.cs index c3204fa1..0ef01492 100644 --- a/JL.Core/Anki/JLFieldUtils.cs +++ b/JL.Core/Anki/JLFieldUtils.cs @@ -11,6 +11,7 @@ public static class JLFieldUtils JLField.Readings, JLField.ReadingsWithOrthographyInfo, JLField.Definitions, + JLField.SelectedDefinitions, JLField.DictionaryName, JLField.Audio, JLField.Image, @@ -37,6 +38,7 @@ public static class JLFieldUtils JLField.KanjiGrade, JLField.KanjiComposition, JLField.Definitions, + JLField.SelectedDefinitions, JLField.DictionaryName, JLField.Audio, JLField.Image, @@ -54,6 +56,7 @@ public static class JLFieldUtils JLField.Readings, JLField.AlternativeSpellings, JLField.Definitions, + JLField.SelectedDefinitions, JLField.DictionaryName, JLField.Audio, JLField.Image, diff --git a/JL.Windows/GUI/PopupWindow.xaml.cs b/JL.Windows/GUI/PopupWindow.xaml.cs index ef6b7104..9b2b1240 100644 --- a/JL.Windows/GUI/PopupWindow.xaml.cs +++ b/JL.Windows/GUI/PopupWindow.xaml.cs @@ -30,9 +30,9 @@ internal sealed partial class PopupWindow : Window private TextBox? _lastInteractedTextBox; - private int _listBoxIndex = 0; + private int _listViewItemIndex = 0; - private int _firstVisibleListBoxIndex = 0; + private int _firstVisibleListViewItemIndex = 0; private int _currentCharPosition; @@ -125,7 +125,7 @@ private void ShowAddWordWindow() { string text = _lastInteractedTextBox?.SelectionLength > 0 ? _lastInteractedTextBox.SelectedText - : LastLookupResults[_listBoxIndex].PrimarySpelling; + : LastLookupResults[_listViewItemIndex].PrimarySpelling; WindowsUtils.ShowAddWordWindow(text); } @@ -139,7 +139,7 @@ private void SearchWithBrowser() { string text = _lastInteractedTextBox?.SelectionLength > 0 ? _lastInteractedTextBox.SelectedText - : LastLookupResults[_listBoxIndex].PrimarySpelling; + : LastLookupResults[_listViewItemIndex].PrimarySpelling; WindowsUtils.SearchWithBrowser(text); } @@ -219,8 +219,8 @@ public async Task LookupOnCharPosition(TextBox tb, int charPosition, bool enable Show(); - _firstVisibleListBoxIndex = GetFirstVisibleListBoxItemIndex(); - _listBoxIndex = _firstVisibleListBoxIndex; + _firstVisibleListViewItemIndex = GetFirstVisibleListViewItemIndex(); + _listViewItemIndex = _firstVisibleListViewItemIndex; if (ConfigManager.FixedPopupPositioning && Owner == MainWindow.Instance) { @@ -302,8 +302,8 @@ public async Task LookupOnSelect(TextBox tb) Show(); - _firstVisibleListBoxIndex = GetFirstVisibleListBoxItemIndex(); - _listBoxIndex = _firstVisibleListBoxIndex; + _firstVisibleListViewItemIndex = GetFirstVisibleListViewItemIndex(); + _listViewItemIndex = _firstVisibleListViewItemIndex; if (ConfigManager.FixedPopupPositioning && Owner == MainWindow.Instance) { @@ -1132,30 +1132,30 @@ public StackPanel MakeResultStackPanel(LookupResult result, int index, int resul Children = { top, bottom } }; - stackPanel.MouseEnter += ListBoxItem_MouseEnter; + stackPanel.MouseEnter += ListViewItem_MouseEnter; return stackPanel; } - private static int GetIndexOfListBoxItemFromStackPanel(StackPanel stackPanel) + private static int GetIndexOfListViewItemFromStackPanel(StackPanel stackPanel) { return (int)((WrapPanel)stackPanel.Children[0]).Tag; } - private int GetFirstVisibleListBoxItemIndex() + private int GetFirstVisibleListViewItemIndex() { StackPanel? firstVisibleStackPanel = PopupListView.Items.Cast() .FirstOrDefault(static stackPanel => stackPanel.Visibility is Visibility.Visible); return firstVisibleStackPanel is not null - ? GetIndexOfListBoxItemFromStackPanel(firstVisibleStackPanel) + ? GetIndexOfListViewItemFromStackPanel(firstVisibleStackPanel) : 0; } - private void ListBoxItem_MouseEnter(object sender, MouseEventArgs e) + private void ListViewItem_MouseEnter(object sender, MouseEventArgs e) { - _listBoxIndex = GetIndexOfListBoxItemFromStackPanel((StackPanel)sender); - LastSelectedText = LastLookupResults[_listBoxIndex].PrimarySpelling; + _listViewItemIndex = GetIndexOfListViewItemFromStackPanel((StackPanel)sender); + LastSelectedText = LastLookupResults[_listViewItemIndex].PrimarySpelling; } private static void Unselect(object sender, RoutedEventArgs e) @@ -1226,7 +1226,7 @@ private async void PrimarySpelling_PreviewMouseUp(object sender, MouseButtonEven HidePopup(); - await PopupWindowUtils.Mine(LastLookupResults[_listBoxIndex], _currentText, _currentCharPosition).ConfigureAwait(false); + await PopupWindowUtils.Mine(LastLookupResults[_listViewItemIndex], _currentText, GetSelectedDefinitions(_listViewItemIndex), _currentCharPosition).ConfigureAwait(false); } private void ShowAddNameWindow() @@ -1246,9 +1246,9 @@ private void ShowAddNameWindow() } else { - text = LastLookupResults[_listBoxIndex].PrimarySpelling; + text = LastLookupResults[_listViewItemIndex].PrimarySpelling; - string[]? readings = LastLookupResults[_listBoxIndex].Readings; + string[]? readings = LastLookupResults[_listViewItemIndex].Readings; reading = readings?.Length is 1 ? readings[0] : ""; @@ -1576,7 +1576,7 @@ public async Task HandleHotKey(KeyGesture keyGesture) { string text = _lastInteractedTextBox?.SelectionLength > 0 ? _lastInteractedTextBox.SelectedText - : LastLookupResults[_listBoxIndex].PrimarySpelling; + : LastLookupResults[_listViewItemIndex].PrimarySpelling; await SpeechSynthesisUtils.TextToSpeech(SpeechSynthesisUtils.InstalledVoiceWithHighestPriority, text, CoreConfig.AudioVolume).ConfigureAwait(false); } @@ -1604,8 +1604,8 @@ public async Task HandleHotKey(KeyGesture keyGesture) { HidePopup(); - int index = GetIndexOfListBoxItemFromStackPanel((StackPanel)PopupListView.SelectedItem); - await PopupWindowUtils.Mine(LastLookupResults[index], _currentText, _currentCharPosition).ConfigureAwait(false); + int index = GetIndexOfListViewItemFromStackPanel((StackPanel)PopupListView.SelectedItem); + await PopupWindowUtils.Mine(LastLookupResults[index], _currentText, GetSelectedDefinitions(index), _currentCharPosition).ConfigureAwait(false); } } } @@ -1629,7 +1629,7 @@ private async Task PlayAudio() return; } - LookupResult lastLookupResult = LastLookupResults[_listBoxIndex]; + LookupResult lastLookupResult = LastLookupResults[_listViewItemIndex]; string primarySpelling = lastLookupResult.PrimarySpelling; string? reading = lastLookupResult.Readings?[0]; @@ -1782,9 +1782,9 @@ private void ButtonAllOnClick(object sender, RoutedEventArgs e) button.Background = Brushes.DodgerBlue; PopupListView.Items.Filter = NoAllDictFilter; - _firstVisibleListBoxIndex = GetFirstVisibleListBoxItemIndex(); - _listBoxIndex = _firstVisibleListBoxIndex; - LastSelectedText = LastLookupResults[_listBoxIndex].PrimarySpelling; + _firstVisibleListViewItemIndex = GetFirstVisibleListViewItemIndex(); + _listViewItemIndex = _firstVisibleListViewItemIndex; + LastSelectedText = LastLookupResults[_listViewItemIndex].PrimarySpelling; WindowsUtils.Unselect(_lastInteractedTextBox); _lastInteractedTextBox = null; @@ -1804,9 +1804,9 @@ private void DictTypeButtonOnClick(object sender, RoutedEventArgs e) _filteredDict = (Dict)button.Tag; PopupListView.Items.Filter = DictFilter; - _firstVisibleListBoxIndex = GetFirstVisibleListBoxItemIndex(); - _listBoxIndex = _firstVisibleListBoxIndex; - LastSelectedText = LastLookupResults[_listBoxIndex].PrimarySpelling; + _firstVisibleListViewItemIndex = GetFirstVisibleListViewItemIndex(); + _listViewItemIndex = _firstVisibleListViewItemIndex; + LastSelectedText = LastLookupResults[_listViewItemIndex].PrimarySpelling; WindowsUtils.Unselect(_lastInteractedTextBox); _lastInteractedTextBox = null; @@ -1895,8 +1895,8 @@ public void HidePopup() PopupListView.ItemsSource = null; LastText = ""; - _listBoxIndex = 0; - _firstVisibleListBoxIndex = 0; + _listViewItemIndex = 0; + _firstVisibleListViewItemIndex = 0; _lastInteractedTextBox = null; PopupAutoHideTimer.Stop(); @@ -1943,7 +1943,24 @@ private void Window_ContextMenuOpening(object sender, ContextMenuEventArgs e) private void PopupListView_MouseLeave(object sender, MouseEventArgs e) { - _listBoxIndex = _firstVisibleListBoxIndex; - LastSelectedText = LastLookupResults[_listBoxIndex].PrimarySpelling; + _listViewItemIndex = _firstVisibleListViewItemIndex; + LastSelectedText = LastLookupResults[_listViewItemIndex].PrimarySpelling; + } + + private TextBox? GetDefinitionTextBox(int listViewIndex) + { + return ((StackPanel)((StackPanel)PopupListView.Items[listViewIndex]).Children[1]).GetChildByName(nameof(LookupResult.FormattedDefinitions)); + } + + private string? GetSelectedDefinitions(int listViewIndex) + { + TextBox? definitionTextBox = GetDefinitionTextBox(listViewIndex); + string? selectedDefinitions = null; + if (definitionTextBox?.SelectionLength > 0) + { + selectedDefinitions = definitionTextBox.SelectedText; + } + + return selectedDefinitions; } } diff --git a/JL.Windows/GUI/PreferencesWindow.xaml.cs b/JL.Windows/GUI/PreferencesWindow.xaml.cs index 0eade19d..9857276a 100644 --- a/JL.Windows/GUI/PreferencesWindow.xaml.cs +++ b/JL.Windows/GUI/PreferencesWindow.xaml.cs @@ -52,6 +52,7 @@ public static bool IsItVisible() • Alternative Spellings: Alternative spellings of the mined word, e.g., if you look up "わかりました", its alternative spellings will be "解る, 判る, 分る". • Alternative Spellings with Orthography Info: Alternative spellings of the mined word with their orthography info, e.g., if you look up "嫁" its "Alternative Spellings with Orthography Info" will be "娵 (rK), 婦 (rK), 媳 (rK)". • Definitions: Definitions of the mined word. + • Selected Definitions: The selected text on definition text box. If no text is selected, it will have the same value as "Definitions" field. • Dictionary Name: Name of the dictionary, e.g., JMDict. • Audio: Audio for the first reading of the mined word. • Source Text: Whole text in which the mined word appears in. @@ -76,6 +77,7 @@ public static bool IsItVisible() • Kanji Grade: The kanji grade level. • Kanji Composition: Kanji composition info, e.g., "⿰女未" for "妹". • Definitions: Definitions of the mined kanji. + • Selected Definitions: The selected text on definition text box. If no text is selected, it will have the same value as "Definitions" field. • Dictionary Name: Name of the dictionary, e.g., "Kanjidic". • Source Text: Whole text in which the mined kanji appears in. • Sentence: Sentence in which the mined kanji appears in. @@ -90,6 +92,7 @@ public static bool IsItVisible() • Readings: Readings of the name. • Alternative Spellings: Alternative spellings of the mined name. • Definitions: Translations of the name. + • Selected Definitions: The selected text on definition text box. If no text is selected, it will have the same value as "Definitions" field. • Dictionary Name: Name of the dictionary, e.g., "JMnedict". • Source Text: Whole text in which the mined name appears in. • Sentence: Sentence in which the mined name appears in. diff --git a/JL.Windows/Utilities/ExtensionMethods.cs b/JL.Windows/Utilities/ExtensionMethods.cs index 5c75986f..fd956025 100644 --- a/JL.Windows/Utilities/ExtensionMethods.cs +++ b/JL.Windows/Utilities/ExtensionMethods.cs @@ -30,4 +30,33 @@ internal static class ExtensionMethods return null; } + + public static T? GetChildByName(this DependencyObject parent, string childName) where T : DependencyObject + { + int childrenCount = VisualTreeHelper.GetChildrenCount(parent); + for (int i = 0; i < childrenCount; i++) + { + DependencyObject child = VisualTreeHelper.GetChild(parent, i); + if (child is T t) + { + if (child is FrameworkElement frameworkElement) + { + if (frameworkElement.Name == childName) + { + return t; + } + } + } + else + { + T? tChild = GetChildByName(child, childName); + if (tChild is not null) + { + return tChild; + } + } + } + + return null; + } } diff --git a/JL.Windows/Utilities/PopupWindowUtils.cs b/JL.Windows/Utilities/PopupWindowUtils.cs index ed54b453..738d1345 100644 --- a/JL.Windows/Utilities/PopupWindowUtils.cs +++ b/JL.Windows/Utilities/PopupWindowUtils.cs @@ -281,7 +281,7 @@ public static void ShowMiningModeResults(PopupWindow popupWindow) } } - public static async Task Mine(LookupResult lookupResult, string currentText, int currentCharPosition) + public static async Task Mine(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition) { Dictionary miningParams = new() { @@ -331,8 +331,18 @@ public static async Task Mine(LookupResult lookupResult, string currentText, int if (lookupResult.FormattedDefinitions is not null) { - miningParams[JLField.Definitions] = lookupResult.FormattedDefinitions - .Replace("\n", "
", StringComparison.Ordinal); + string formattedDefinitions = lookupResult.FormattedDefinitions.Replace("\n", "
", StringComparison.Ordinal); + miningParams[JLField.Definitions] = formattedDefinitions; + + if (selectedDefinitions is null) + { + miningParams[JLField.SelectedDefinitions] = formattedDefinitions; + } + } + + if (selectedDefinitions is not null) + { + miningParams[JLField.SelectedDefinitions] = selectedDefinitions.Replace("\n", "
", StringComparison.Ordinal); } if (lookupResult.EdictId > 0)