From 1e8ec2492b70a5a794ebb8638edba5c3691aad07 Mon Sep 17 00:00:00 2001 From: kpence Date: Mon, 4 Oct 2021 21:01:46 -0500 Subject: [PATCH 01/21] Add annotations panel and highlighting to PDFViewer; Will include web browser javascript in separate commit --- assets/images/icons/sideBarAnnotation.png | Bin 0 -> 313 bytes .../Models/PDFAnnotationHighlight.cs | 79 +++++ .../Models/PDFCfg.cs | 7 +- .../PDF/PDFAnnotationWebBrowser.cs | 13 + .../PDF/PDFElement.cs | 5 + .../PDF/PDFWindow.xaml | 283 +++++++++++------- .../PDF/PDFWindow.xaml.cs | 158 ++++++++-- .../PDF/Viewer/IPDFViewer.Inputs.cs | 5 + .../PDF/Viewer/IPDFViewer.Selection.cs | 30 +- .../PDF/Viewer/IPDFViewer.SuperMemo.cs | 27 ++ .../PDF/Viewer/IPDFViewer.cs | 1 + .../PDFAnnotationWebBrowserWrapper.cs | 101 +++++++ .../PDFHotKeys.cs | 5 + .../PDFPlugin.cs | 2 +- .../Utils/Web/HtmlBuilder.cs | 8 + .../version.json | 2 +- 16 files changed, 595 insertions(+), 131 deletions(-) create mode 100644 assets/images/icons/sideBarAnnotation.png create mode 100644 src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs create mode 100644 src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs create mode 100644 src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs diff --git a/assets/images/icons/sideBarAnnotation.png b/assets/images/icons/sideBarAnnotation.png new file mode 100644 index 0000000000000000000000000000000000000000..a7911c8207b8305fdf276bb2c90b92bf36e8d148 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^azL!Y!3HGfUF^yPQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtYKT*NBqf{Irtt#G+J&g2c?c61}|C5(N`I zLp{?J_XvA`!kO=qtmkIi6#Bl~yZi!&*WX;;EizdJ*N-r!x2xVM{rG07Wm&=UL~h>Mmo~Jv z`DWgD^u6u+jD-1fmf9KFxc`|h_&T}!cy$-Qf1qQOH20G4qSAIrE#X%Uoi9H8Va@l* z(Jgt-hie7w(qGoy|0JDMy8BD`-ukG|cFV6^7d^zP$D!~}YldqQ(A5l{u6{1-oD!M< DmtA({ literal 0 HcmV?d00001 diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs new file mode 100644 index 0000000..c17fe4f --- /dev/null +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs @@ -0,0 +1,79 @@ +#region License & Metadata + +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// +// Created On: 2018/12/23 17:09 +// Modified On: 2019/02/22 13:43 +// Modified By: Alexis + +#endregion + + + + +using Newtonsoft.Json; +using Patagames.Pdf.Net.Controls.Wpf; + +namespace SuperMemoAssistant.Plugins.PDF.Models +{ + public class PDFAnnotationHighlight : PDFTextExtract + { + #region Properties & Fields - Public + + [JsonProperty(PropertyName = "HTML")] + public string HtmlContent { get; set; } + [JsonProperty(PropertyName = "AnnotationId")] + public int AnnotationId { get; set; } + + #endregion + + + + + #region Methods + public static implicit operator PDFAnnotationHighlight(SelectInfo selInfo) + { + return new PDFAnnotationHighlight + { + StartPage = selInfo.StartPage, + StartIndex = selInfo.StartIndex, + EndPage = selInfo.EndPage, + EndIndex = selInfo.EndIndex, + HtmlContent = "
", + AnnotationId = 0 + }; + } + + public static PDFAnnotationHighlight Create(SelectInfo selInfo, int annotationId) + => new PDFAnnotationHighlight + { + StartPage = selInfo.StartPage, + StartIndex = selInfo.StartIndex, + EndPage = selInfo.EndPage, + EndIndex = selInfo.EndIndex, + HtmlContent = "
", + AnnotationId = annotationId + }; + + #endregion + } +} diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs index 78aaa05..6be23e6 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs @@ -161,6 +161,10 @@ public class PDFCfg : CfgBase, INotifyPropertyChangedEx [Value(Must.MatchPattern, HexREPattern)] [JsonConverter(typeof(ColorToStringJsonConverter))] public Color IgnoreHighlightColor { get; set; } = SMConst.Stylesheet.IgnoreColor; + public Color AnnotationHighlightColor { get; set; } = Color.FromArgb(90, + 100, + 255, + 100); public double WindowTop { get; set; } = 100; public double WindowHeight { get; set; } = 600; @@ -168,7 +172,8 @@ public class PDFCfg : CfgBase, INotifyPropertyChangedEx public double WindowWidth { get; set; } = 800; public WindowState WindowState { get; set; } = WindowState.Normal; - public double SidePanelWidth { get; set; } = 256; + public double SidePanelBookmarksWidth { get; set; } = 256; + public double SidePanelAnnotationsWidth { get; set; } = 256; // Dictionary diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs new file mode 100644 index 0000000..c8155de --- /dev/null +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs @@ -0,0 +1,13 @@ +#region Assembly PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 +// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\PresentationFramework.dll +#endregion + +using System.Windows.Media; +using System.Windows.Controls; + +namespace SuperMemoAssistant.Plugins.PDF.PDF +{ + public class PDFAnnotationWebBrowser : Decorator + { + } +} diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs index c0c12cc..1c06f86 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs @@ -73,11 +73,13 @@ public PDFElement() SMExtracts = new ObservableCollection(); SMImgExtracts = new ObservableCollection(); IgnoreHighlights = new ObservableCollection(); + AnnotationHighlights = new ObservableCollection(); PDFExtracts.CollectionChanged += OnCollectionChanged; SMExtracts.CollectionChanged += OnCollectionChanged; SMImgExtracts.CollectionChanged += OnCollectionChanged; IgnoreHighlights.CollectionChanged += OnCollectionChanged; + AnnotationHighlights.CollectionChanged += OnCollectionChanged; } #endregion @@ -107,6 +109,8 @@ public PDFElement() public ObservableCollection SMImgExtracts { get; } [JsonProperty(PropertyName = "IH")] public ObservableCollection IgnoreHighlights { get; } + [JsonProperty(PropertyName = "AH")] + public ObservableCollection AnnotationHighlights { get; } [JsonProperty(PropertyName = "RPg")] public int ReadPage { get; set; } @@ -501,6 +505,7 @@ private string GetJsonB64() string elementJson = JsonConvert.SerializeObject(this, Formatting.None); + //MessageBox.Show("GetJsonB64: " + elementJson.Replace("HTML", "\nHTML")); // TODO NOCHECKIN return elementJson.ToBase64(); } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml index b19f187..e21d147 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml @@ -11,124 +11,137 @@ xmlns:dictUi="clr-namespace:SuperMemoAssistant.Plugins.Dictionary.Interop.UI;assembly=SuperMemoAssistant.Plugins.Dictionary.Interop" mc:Ignorable="d" Title="SuperMemo Incremental PDF" Height="450" Width="800" - KeyDown="Window_KeyDown"> + KeyDown="Window_KeyDown" + PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"> + - - - - - - - - + + + + + + - + - - - - + - - - + - - + + - - - - - - - + + + + + + + + - - - + - - - + - + + + + + - - - - - - - - - - - + + + + + + + + + - - - - - + + - + - - - - + + - - - - - - + + + + - - - - - - - - + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + - + - - - - + - - + + - - - - + - - - - - + - - + + - - - - - - + + + - \ No newline at end of file + diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs index 3a75bc8..7cb9a1f 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs @@ -31,7 +31,9 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.ComponentModel; using System.Reflection; using System.Threading.Tasks; @@ -43,6 +45,7 @@ using Patagames.Pdf.Net; using SuperMemoAssistant.Extensions; using SuperMemoAssistant.Plugins.PDF.Models; +using SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper; using SuperMemoAssistant.Services; using SuperMemoAssistant.Services.IO.HotKeys; using SuperMemoAssistant.Sys.IO.Devices; @@ -68,9 +71,11 @@ partial class PDFWindow : Window #region Properties & Fields - Non-Public protected readonly DelayedTask _saveConfigDelayed; - protected double _lastSidePanelWidth; + protected double _lastSidePanelBookmarksWidth; + protected double _lastSidePanelAnnotationsWidth; protected PDFCfg Config => PDFState.Instance.Config; + protected PDFAnnotationWebBrowserWrapper AnnotationWebBrowserWrapper { get; set; } #endregion @@ -93,8 +98,10 @@ public PDFWindow() ? WindowState.Maximized : WindowState.Normal; - if (double.IsNaN(Config.SidePanelWidth) == false) - sidePanelColumn.Width = new GridLength(Config.SidePanelWidth); + if (double.IsNaN(Config.SidePanelBookmarksWidth) == false) + sidePanelBookmarksColumn.Width = new GridLength(Config.SidePanelBookmarksWidth); + if (double.IsNaN(Config.SidePanelAnnotationsWidth) == false) + sidePanelAnnotationsColumn.Width = new GridLength(Config.SidePanelAnnotationsWidth); _saveConfigDelayed = new DelayedTask(SaveConfig); } @@ -171,9 +178,24 @@ private void IPDFViewer_OnDocumentLoaded(object sender, Bookmarks.Clear(); + // TODO order the annotationHighlights by text selection position, add the sorting to the javascript, and pass in the text position through argument + // TODO Find out the best location where you can put the document, placeholder will be ~/Documents + // TODO Create the html file here, which will contain all the scripts you need + // TODO Extract that functionality out into a seaprate object which you can use here + // TODO In thsi separate class you can encapsulate the creation of a class that can properly be used for hooking into the onclick/ (will change to just changes likee input) + AnnotationWebBrowserWrapper = new PDFAnnotationWebBrowserWrapper(annotationWebBrowser, IPDFViewer); + IPDFViewer.Document?.Bookmarks.ForEach(b => Bookmarks.Add(b)); } + private void WebBrowserLoadCompletedEventHandler(object sender, + EventArgs e) + { + AnnotationWebBrowserWrapper.RefreshAnnotations(); + IPDFViewer.PDFElement.AnnotationHighlights.CollectionChanged += + AnnotationWebBrowserWrapper.AnnotationHighlights_CollectionChanged; + } + private void IPDFViewer_OnDocumentClosing(object sender, EventArgs e) { @@ -232,7 +254,8 @@ private void SaveConfig() Width, WindowState); - Config.SidePanelWidth = _lastSidePanelWidth; + Config.SidePanelBookmarksWidth = _lastSidePanelBookmarksWidth; + Config.SidePanelAnnotationsWidth = _lastSidePanelAnnotationsWidth; PDFState.Instance.SaveConfigAsync().RunAsync(); } ); @@ -243,6 +266,20 @@ public void CancelSave() IPDFViewer?.CancelSave(); } + private void Window_PreviewMouseLeftButtonDown(object sender, + EventArgs e) + { + if (IPDFViewer == null) + return; + + var currentHighlightAnnotation = IPDFViewer?.CurrentAnnotationHighlight; + + if (currentHighlightAnnotation == null) + return; + + AnnotationWebBrowserWrapper.ScrollToAnnotation(currentHighlightAnnotation); + } + private void Window_KeyDown(object sender, KeyEventArgs e) { @@ -378,18 +415,30 @@ private void TvBookmarks_PreviewKeyDown(object sender, } } - private void BtnExpandAll_Click(object sender, + private void BtnBookmarksExpandAll_Click(object sender, RoutedEventArgs e) { tvBookmarks.ExpandAll(); } - private void BtnCollapseAll_Click(object sender, + private void BtnBookmarksCollapseAll_Click(object sender, RoutedEventArgs e) { tvBookmarks.CollapseAll(); } + private void BtnAnnotationsExpandAll_Click(object sender, + RoutedEventArgs e) + { + // TODO + } + + private void BtnAnnotationsCollapseAll_Click(object sender, + RoutedEventArgs e) + { + // TODO + } + protected KeyModifiers GetKeyboardModifiers() { KeyModifiers mod = KeyModifiers.None; @@ -409,60 +458,121 @@ protected KeyModifiers GetKeyboardModifiers() private void BtnBookmarks_CheckedChanged(object sender, RoutedEventArgs e) { - if (sidePanel == null) + if (sidePanelBookmarks == null) return; bool isVisible = btnBookmarks.IsChecked ?? false; if (isVisible) { - if (sidePanel.Visibility == Visibility.Hidden) - sidePanelColumn.Width = new GridLength(Math.Max(_lastSidePanelWidth, 250)); + if (sidePanelBookmarks.Visibility == Visibility.Hidden) + sidePanelBookmarksColumn.Width = new GridLength(Math.Max(_lastSidePanelBookmarksWidth, 250)); } else { - if (sidePanel.Visibility == Visibility.Visible) + if (sidePanelBookmarks.Visibility == Visibility.Visible) { - _lastSidePanelWidth = sidePanelColumn.ActualWidth; + _lastSidePanelBookmarksWidth = sidePanelBookmarksColumn.ActualWidth; - sidePanelColumn.Width = new GridLength(0); + sidePanelBookmarksColumn.Width = new GridLength(0); } } } - private void SidePanel_SizeChanged(object sender, + private void BtnAnnotations_CheckedChanged(object sender, + RoutedEventArgs e) + { + if (sidePanelAnnotations == null) + return; + + bool isVisible = btnAnnotations.IsChecked ?? false; + + if (isVisible) + { + if (sidePanelAnnotations.Visibility == Visibility.Hidden) + sidePanelAnnotationsColumn.Width = new GridLength(Math.Max(_lastSidePanelAnnotationsWidth, 250)); + } + + else + { + if (sidePanelAnnotations.Visibility == Visibility.Visible) + { + _lastSidePanelAnnotationsWidth = sidePanelAnnotationsColumn.ActualWidth; + + sidePanelAnnotationsColumn.Width = new GridLength(0); + } + } + } + + private void SidePanelBookmarks_SizeChanged(object sender, SizeChangedEventArgs e) { - if (sidePanel.Visibility == Visibility.Visible) + if (sidePanelBookmarks.Visibility == Visibility.Visible) { - if (sidePanel.ActualWidth < 50) + if (sidePanelBookmarks.ActualWidth < 50) { - sidePanel.Visibility = Visibility.Hidden; - sidePanelColumn.Width = new GridLength(0); + sidePanelBookmarks.Visibility = Visibility.Hidden; + sidePanelBookmarksColumn.Width = new GridLength(0); btnBookmarks.IsChecked = false; - _lastSidePanelWidth = 0; + _lastSidePanelBookmarksWidth = 0; } else { - _lastSidePanelWidth = sidePanelColumn.ActualWidth; + _lastSidePanelBookmarksWidth = sidePanelBookmarksColumn.ActualWidth; } } - else if (sidePanel.Visibility == Visibility.Hidden) + else if (sidePanelBookmarks.Visibility == Visibility.Hidden) { - if (sidePanel.ActualWidth >= 50) + if (sidePanelBookmarks.ActualWidth >= 50) { - sidePanel.Visibility = Visibility.Visible; + sidePanelBookmarks.Visibility = Visibility.Visible; btnBookmarks.IsChecked = true; - _lastSidePanelWidth = sidePanelColumn.ActualWidth; + _lastSidePanelBookmarksWidth = sidePanelBookmarksColumn.ActualWidth; + } + + else + { + sidePanelBookmarksColumn.Width = new GridLength(0); + } + } + } + + private void SidePanelAnnotations_SizeChanged(object sender, + SizeChangedEventArgs e) + { + if (sidePanelAnnotations.Visibility == Visibility.Visible) + { + if (sidePanelAnnotations.ActualWidth < 50) + { + sidePanelAnnotations.Visibility = Visibility.Hidden; + sidePanelAnnotationsColumn.Width = new GridLength(0); + btnAnnotations.IsChecked = false; + _lastSidePanelAnnotationsWidth = 0; + } + + else + { + _lastSidePanelAnnotationsWidth = sidePanelAnnotationsColumn.ActualWidth; + } + } + + else if (sidePanelAnnotations.Visibility == Visibility.Hidden) + { + if (sidePanelAnnotations.ActualWidth >= 50) + { + sidePanelAnnotations.Visibility = Visibility.Visible; + btnAnnotations.IsChecked = true; + + _lastSidePanelAnnotationsWidth = sidePanelAnnotationsColumn.ActualWidth; } else { - sidePanelColumn.Width = new GridLength(0); + sidePanelAnnotationsColumn.Width = new GridLength(0); } } } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Inputs.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Inputs.cs index 507d182..3f4e863 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Inputs.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Inputs.cs @@ -106,6 +106,11 @@ protected override void OnKeyDown(KeyEventArgs e) e.Handled = true; break; + case PDFHotKeys.Annotate: + CreateAnnotationHighlight(); + e.Handled = true; + break; + // // PDF features diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs index 63d4f1d..0e7fee9 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs @@ -62,13 +62,12 @@ public partial class IPDFViewer #endregion - + public PDFAnnotationHighlight? CurrentAnnotationHighlight { get; set; } = null; #region Properties & Fields - Non-Public protected SelectionType CurrentSelectionTool { get; set; } = SelectionType.None; - protected PDFPageSelection SelectedPages { get; set; } protected List SelectedImageList { get; } = new List(); @@ -391,6 +390,33 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, invalidate = true; } + if (e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released) + { + var charIndex = GetCharIndexAtPos(pageIndex, pagePoint); + if (CurrentAnnotationHighlight == null) + { + // TODO Check if hovering over any annotationHighlights and then change the color + foreach (PDFAnnotationHighlight annotationHighlight in PDFElement.AnnotationHighlights) + { + if (charIndex > annotationHighlight.StartIndex + && charIndex < annotationHighlight.EndIndex) + { + // TODO add the new highlight + CurrentAnnotationHighlight = annotationHighlight; + } + } + } + else + { + if (charIndex < CurrentAnnotationHighlight.StartIndex + || charIndex > CurrentAnnotationHighlight.EndIndex) + { + CurrentAnnotationHighlight = null; + // TODO change the color + } + } + } + if (invalidate) InvalidateVisual(); diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs index 0a8719d..abee884 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs @@ -356,6 +356,28 @@ protected bool CreateIgnoreHighlight() return true; } + protected bool CreateAnnotationHighlight() + { + if (IsTextSelectionValid(out _) == false) + return false; + + foreach (var selInfo in SelectInfos) + { + var count = 0; + foreach (PDFAnnotationHighlight a in PDFElement.AnnotationHighlights) + { + count = (a.AnnotationId >= count) ? a.AnnotationId + 1 : count; + } + var annotationHighlight = PDFAnnotationHighlight.Create(selInfo, count); + PDFElement.AnnotationHighlights.Add(annotationHighlight); + AddAnnotationHighlight(annotationHighlight); + } + + DeselectText(); + + return true; + } + // // Highlights @@ -419,6 +441,11 @@ protected void AddIgnoreHighlight(PDFTextExtract extract) AddHighlight(extract, Config.IgnoreHighlightColor); } + protected void AddAnnotationHighlight(PDFTextExtract extract) + { + AddHighlight(extract, Config.AnnotationHighlightColor); + } + protected void AddHighlight(PDFTextExtract extract, System.Windows.Media.Color highlightColor) { diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs index 0f93959..b7bf74d 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs @@ -132,6 +132,7 @@ protected override void OnDocumentLoaded(EventArgs ev) PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); + PDFElement.AnnotationHighlights.ForEach(AddAnnotationHighlight); GenerateOutOfExtractHighlights(); diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs new file mode 100644 index 0000000..bd8ab95 --- /dev/null +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -0,0 +1,101 @@ +using SuperMemoAssistant.Extensions; +using SuperMemoAssistant.Plugins.PDF.Models; +using System; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper +{ + public class PDFAnnotationWebBrowserWrapper + { + public string testString => "hello world"; + private IPDFViewer PDFViewer { get; set; } + private WebBrowser AnnotationWebBrowser { get; set; } + public PDFAnnotationWebBrowserWrapper(WebBrowser webBrowser, IPDFViewer pdfViewer) + { + PDFViewer = pdfViewer; + AnnotationWebBrowser = webBrowser; + AnnotationWebBrowser.Source = new Uri(@"file://C:\Users\User\Documents\test.html"); + AnnotationWebBrowser.ObjectForScripting = this; + } + + public void RefreshAnnotations() + { + ClearAnnotations(); + PDFViewer.PDFElement.AnnotationHighlights.ForEach(a => InsertAnnotation(a)); + } + + public void ClearAnnotations() + { + AnnotationWebBrowser.InvokeScript("clearAnnotations"); + } + + public void InsertAnnotation(PDFAnnotationHighlight annotationHighlight) + { + var innerHtml = annotationHighlight.HtmlContent; + var annotationId = annotationHighlight.AnnotationId; + AnnotationWebBrowser.InvokeScript("insertAnnotation", annotationId, innerHtml); + ScrollToAnnotation(annotationHighlight); + } + + public void ScrollToAnnotation(PDFAnnotationHighlight annotationHighlight) + { + AnnotationWebBrowser.InvokeScript("scrollToAnnotation", annotationHighlight.AnnotationId); + } + + public void AnnotationHighlights_CollectionChanged(object sender, + NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (PDFAnnotationHighlight annotation in e.NewItems) + { + InsertAnnotation(annotation); + PDFViewer.PDFElement.IsChanged = true; + PDFViewer.PDFElement.Save(); + } + break; + } + } + + public void Annotation_OnClick(int annotationId) => ScrollToAnnotationWithId(annotationId); + + public void Annotation_OnAfterUpdate() => UpdateAnnotationHighlights(); + + public void UpdateAnnotationHighlights() + { + PDFViewer.PDFElement.IsChanged = true; + foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + { + annotation.HtmlContent = + GetHTMLContentForAnnotationId(annotation.AnnotationId) + ?? annotation.HtmlContent; + } + PDFViewer.PDFElement.Save(); + } + + public void ScrollToAnnotationWithId(int annotationId) + { + foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + { + if (annotation.AnnotationId == annotationId) + { + PDFViewer.ScrollToChar(annotation.StartPage, + annotation.StartIndex); + } + } + } + + public string GetHTMLContentForAnnotationId(int annotationId) + { + var document = (mshtml.HTMLDocument)AnnotationWebBrowser.Document; + var element = document.getElementById("annotation" + annotationId.ToString()); + return element?.innerHTML; + } + } +} diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs b/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs index dee7554..7f4008e 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs @@ -46,6 +46,7 @@ internal static class PDFHotKeys public const string ExtractSM = "ExtractSM"; public const string ExtractSMWithPriority = "ExtractSMWithPriority"; public const string MarkIgnore = "MarkIgnore"; + public const string Annotate = "Annotate"; public const string ShowDictionary = "ShowDictionary"; public const string GoToPage = "GoToPage"; public const string SMLearn = "SMLearn"; @@ -104,6 +105,10 @@ public static void RegisterHotKeys() "Mark text as ignored", new HotKey(Key.I, KeyModifiers.CtrlShift) ) + .RegisterLocal(Annotate, + "Create annotation for selected text", + new HotKey(Key.A, KeyModifiers.CtrlShift) + ) // // PDF features diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs index acbaa7f..a86541b 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs @@ -82,7 +82,7 @@ protected override void OnPluginInitialized() if (!PdfCommon.IsInitialize) // TODO: Specify dll path depending on IsDevelopmentPlugin ? - PdfCommon.Initialize(PDFLicense.LicenseKey); + PdfCommon.Initialize(); base.OnPluginInitialized(); } diff --git a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs index 8d08ee1..b5da26b 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs @@ -521,6 +521,14 @@ private void GenerateExtractSpans() SMConst.Stylesheet.IgnoreColor, pageSpanDict); + foreach (var annotationHighlight in PdfElement.AnnotationHighlights) + SplitExtractByPage(annotationHighlight, + Color.FromArgb(90, + 100, + 255, + 100), + pageSpanDict); + foreach (var pageSpan in pageSpanDict) GenerateExtractSpans(pageSpan.Key, pageSpan.Value diff --git a/src/SuperMemoAssistant.Plugins.PDF/version.json b/src/SuperMemoAssistant.Plugins.PDF/version.json index c62f9b7..634c556 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/version.json +++ b/src/SuperMemoAssistant.Plugins.PDF/version.json @@ -1,3 +1,3 @@ { - "version": "2.1.0-beta" + "version": "2.1.0-alpha" } \ No newline at end of file From ef502b4521b2760297d02170e7497a34f3afe355 Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 19:31:51 -0500 Subject: [PATCH 02/21] Change highlight color upon mouse hovering; Remove unneeded file --- .../Models/PDFCfg.cs | 4 ++++ .../PDF/PDFAnnotationWebBrowser.cs | 13 ----------- .../PDF/PDFWindow.xaml.cs | 2 -- .../PDF/Viewer/IPDFViewer.Selection.cs | 23 +++++++++++++++++-- .../PDF/Viewer/IPDFViewer.SuperMemo.cs | 10 +++++++- 5 files changed, 34 insertions(+), 18 deletions(-) delete mode 100644 src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs index 6be23e6..9bf8016 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs @@ -161,6 +161,10 @@ public class PDFCfg : CfgBase, INotifyPropertyChangedEx [Value(Must.MatchPattern, HexREPattern)] [JsonConverter(typeof(ColorToStringJsonConverter))] public Color IgnoreHighlightColor { get; set; } = SMConst.Stylesheet.IgnoreColor; + public Color FocusedAnnotationHighlightColor { get; set; } = Color.FromArgb(150, + 0, + 255, + 0); public Color AnnotationHighlightColor { get; set; } = Color.FromArgb(90, 100, 255, diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs deleted file mode 100644 index c8155de..0000000 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFAnnotationWebBrowser.cs +++ /dev/null @@ -1,13 +0,0 @@ -#region Assembly PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 -// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\PresentationFramework.dll -#endregion - -using System.Windows.Media; -using System.Windows.Controls; - -namespace SuperMemoAssistant.Plugins.PDF.PDF -{ - public class PDFAnnotationWebBrowser : Decorator - { - } -} diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs index 7cb9a1f..329e4a6 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs @@ -31,9 +31,7 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.ComponentModel; using System.Reflection; using System.Threading.Tasks; diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs index 0e7fee9..11530a8 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs @@ -50,6 +50,7 @@ namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer { + using SuperMemoAssistant.Extensions; using System.Diagnostics.CodeAnalysis; /// @@ -401,7 +402,16 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, if (charIndex > annotationHighlight.StartIndex && charIndex < annotationHighlight.EndIndex) { - // TODO add the new highlight + ExtractHighlights.Clear(); + ImageExtractHighlights.Clear(); + RemoveHighlightFromText(); + + PDFElement.PDFExtracts.ForEach(AddPDFExtractHighlight); + PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); + PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); + PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); + PDFElement.AnnotationHighlights.ForEach(a => AddAnnotationHighlight(a, a == annotationHighlight)); + CurrentAnnotationHighlight = annotationHighlight; } } @@ -411,8 +421,17 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, if (charIndex < CurrentAnnotationHighlight.StartIndex || charIndex > CurrentAnnotationHighlight.EndIndex) { + ExtractHighlights.Clear(); + ImageExtractHighlights.Clear(); + RemoveHighlightFromText(); + + PDFElement.PDFExtracts.ForEach(AddPDFExtractHighlight); + PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); + PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); + PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); + PDFElement.AnnotationHighlights.ForEach(AddAnnotationHighlight); + CurrentAnnotationHighlight = null; - // TODO change the color } } } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs index abee884..fb64aa5 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs @@ -442,8 +442,16 @@ protected void AddIgnoreHighlight(PDFTextExtract extract) } protected void AddAnnotationHighlight(PDFTextExtract extract) + => AddAnnotationHighlight(extract, false); + + protected void AddAnnotationHighlight(PDFTextExtract extract, bool isFocused) { - AddHighlight(extract, Config.AnnotationHighlightColor); + AddHighlight( + extract, + isFocused + ? Config.FocusedAnnotationHighlightColor + : Config.AnnotationHighlightColor + ); } protected void AddHighlight(PDFTextExtract extract, From 6c6c0a4600efb35bf86dba31631cc6658290434a Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 19:32:57 -0500 Subject: [PATCH 03/21] Remove redundant code --- .../WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index bd8ab95..088d172 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -1,18 +1,13 @@ using SuperMemoAssistant.Extensions; using SuperMemoAssistant.Plugins.PDF.Models; using System; -using System.Collections.ObjectModel; using System.Collections.Specialized; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; using System.Windows.Controls; namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper { public class PDFAnnotationWebBrowserWrapper { - public string testString => "hello world"; private IPDFViewer PDFViewer { get; set; } private WebBrowser AnnotationWebBrowser { get; set; } public PDFAnnotationWebBrowserWrapper(WebBrowser webBrowser, IPDFViewer pdfViewer) From fc663d0d2117a24b6643769bbd38d7ca37af0fa5 Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 20:08:01 -0500 Subject: [PATCH 04/21] Add assets used for Annotations feature --- assets/annotationSidePanel.html | 82 +++++++++++++++++++ libs/Patagames.Pdf.Wpf | 2 +- .../PDF/PDFWindow.xaml | 2 +- .../PDFPlugin.cs | 1 + .../SuperMemoAssistant.Plugins.PDF.csproj | 2 + 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 assets/annotationSidePanel.html diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html new file mode 100644 index 0000000..0506bcb --- /dev/null +++ b/assets/annotationSidePanel.html @@ -0,0 +1,82 @@ + + + +
+ + + + diff --git a/libs/Patagames.Pdf.Wpf b/libs/Patagames.Pdf.Wpf index fb9de33..cb9fec0 160000 --- a/libs/Patagames.Pdf.Wpf +++ b/libs/Patagames.Pdf.Wpf @@ -1 +1 @@ -Subproject commit fb9de33775255e12a1d37d3de033e432fc54b193 +Subproject commit cb9fec09a122cece3f24e1671d3fc62db4787bfb diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml index e21d147..96ec252 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml @@ -81,7 +81,7 @@ Unchecked="BtnAnnotations_CheckedChanged" Margin="0 16 0 0" Background="Transparent"> - diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs index a86541b..9ebc4aa 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs @@ -27,6 +27,7 @@ namespace SuperMemoAssistant.Plugins.PDF { + using System.IO; using System.Runtime.Remoting; using Anotar.Serilog; using Dictionary.Interop; diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index 1265db3..eccf2db 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -43,8 +43,10 @@ + + From 4760c78e6c5a5b73d60933512d1977d6c1ab4f1a Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 20:39:08 -0500 Subject: [PATCH 05/21] Install annotation side panel html to config folder --- .../WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs | 4 +++- .../SuperMemoAssistant.Plugins.PDF.csproj | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 088d172..b66face 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -1,4 +1,5 @@ using SuperMemoAssistant.Extensions; +using SuperMemoAssistant.Interop; using SuperMemoAssistant.Plugins.PDF.Models; using System; using System.Collections.Specialized; @@ -14,7 +15,8 @@ public PDFAnnotationWebBrowserWrapper(WebBrowser webBrowser, IPDFViewer pdfViewe { PDFViewer = pdfViewer; AnnotationWebBrowser = webBrowser; - AnnotationWebBrowser.Source = new Uri(@"file://C:\Users\User\Documents\test.html"); + var configDir = SMAFileSystem.ConfigDir.Combine("SuperMemoAssistant.Plugins.PDF"); + AnnotationWebBrowser.Source = new Uri($@"file://{configDir}\annotationSidePanel.html"); AnnotationWebBrowser.ObjectForScripting = this; } diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index eccf2db..819a69b 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -126,7 +126,10 @@ $(PkgPdfium_Net_SDK)\lib\net472\Patagames.Pdf.dll - + + + + From b38bef561a0c10a694f0dd7ac7e0b848890d72d8 Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 20:40:38 -0500 Subject: [PATCH 06/21] Remove unneeded file linking --- .../SuperMemoAssistant.Plugins.PDF.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index 819a69b..1110d19 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -46,7 +46,6 @@ - From a5a83c114f24ec494766b019748f302469aa3ace Mon Sep 17 00:00:00 2001 From: kpence Date: Tue, 5 Oct 2021 20:58:59 -0500 Subject: [PATCH 07/21] Fix annotationSidePanel copy location and uri path in web browser source --- .../Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs | 2 +- .../SuperMemoAssistant.Plugins.PDF.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index b66face..2697029 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -16,7 +16,7 @@ public PDFAnnotationWebBrowserWrapper(WebBrowser webBrowser, IPDFViewer pdfViewe PDFViewer = pdfViewer; AnnotationWebBrowser = webBrowser; var configDir = SMAFileSystem.ConfigDir.Combine("SuperMemoAssistant.Plugins.PDF"); - AnnotationWebBrowser.Source = new Uri($@"file://{configDir}\annotationSidePanel.html"); + AnnotationWebBrowser.Source = new Uri($@"{configDir}/annotationSidePanel.html"); AnnotationWebBrowser.ObjectForScripting = this; } diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index 1110d19..dde1492 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -126,7 +126,7 @@ - + From 46779eac6743a035793547ac372856c9c0be5e4f Mon Sep 17 00:00:00 2001 From: kpence Date: Wed, 6 Oct 2021 18:33:30 -0500 Subject: [PATCH 08/21] Scroll to center of annotation in PDF and change its highlight color --- .../Models/PDFAnnotationHighlight.cs | 2 ++ .../PDF/PDFWindow.xaml.cs | 8 ++--- .../PDF/Viewer/IPDFViewer.Selection.cs | 35 ++++++++----------- .../PDF/Viewer/IPDFViewer.Utils.cs | 25 ++++++++++--- .../PDFAnnotationWebBrowserWrapper.cs | 4 +-- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs index c17fe4f..5a4665a 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs @@ -74,6 +74,8 @@ public static PDFAnnotationHighlight Create(SelectInfo selInfo, int annotationId AnnotationId = annotationId }; + public int GetSortingKey() => StartPage * 10000 + StartIndex; + #endregion } } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs index 329e4a6..e9b8a79 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs @@ -272,10 +272,10 @@ private void Window_PreviewMouseLeftButtonDown(object sender, var currentHighlightAnnotation = IPDFViewer?.CurrentAnnotationHighlight; - if (currentHighlightAnnotation == null) - return; - - AnnotationWebBrowserWrapper.ScrollToAnnotation(currentHighlightAnnotation); + if (currentHighlightAnnotation != null) + { + AnnotationWebBrowserWrapper.ScrollToAnnotation(currentHighlightAnnotation); + } } private void Window_KeyDown(object sender, diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs index 11530a8..eb87724 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs @@ -402,16 +402,7 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, if (charIndex > annotationHighlight.StartIndex && charIndex < annotationHighlight.EndIndex) { - ExtractHighlights.Clear(); - ImageExtractHighlights.Clear(); - RemoveHighlightFromText(); - - PDFElement.PDFExtracts.ForEach(AddPDFExtractHighlight); - PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); - PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); - PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); - PDFElement.AnnotationHighlights.ForEach(a => AddAnnotationHighlight(a, a == annotationHighlight)); - + ChangeColorOfAnnotationHighlight(annotationHighlight); CurrentAnnotationHighlight = annotationHighlight; } } @@ -421,16 +412,7 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, if (charIndex < CurrentAnnotationHighlight.StartIndex || charIndex > CurrentAnnotationHighlight.EndIndex) { - ExtractHighlights.Clear(); - ImageExtractHighlights.Clear(); - RemoveHighlightFromText(); - - PDFElement.PDFExtracts.ForEach(AddPDFExtractHighlight); - PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); - PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); - PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); - PDFElement.AnnotationHighlights.ForEach(AddAnnotationHighlight); - + ChangeColorOfAnnotationHighlight(null); CurrentAnnotationHighlight = null; } } @@ -442,6 +424,19 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, return handled; } + public void ChangeColorOfAnnotationHighlight(PDFAnnotationHighlight? annotation) + { + ExtractHighlights.Clear(); + ImageExtractHighlights.Clear(); + RemoveHighlightFromText(); + + PDFElement.PDFExtracts.ForEach(AddPDFExtractHighlight); + PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); + PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); + PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); + PDFElement.AnnotationHighlights.ForEach(a => AddAnnotationHighlight(a, annotation != null && a == annotation)); + } + protected bool OnMouseUpProcessSelection(MouseButtonEventArgs e, int pageIndex, Point pagePoint) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Utils.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Utils.cs index 1efe811..b316d83 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Utils.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Utils.cs @@ -98,7 +98,7 @@ public void ShowDictionaryPopup() return; */ - var pageIdx = SelectInfo.StartPage; + var pageIdx = SelectInfo.StartPage; var startIdx = SelectInfo.StartIndex; var textInfos = Document.Pages[pageIdx].Text.GetTextInfo(startIdx, text.Length); @@ -133,7 +133,7 @@ public void ShowDictionaryPopup() textInfos.Rects.Last().top)); DictionaryPopup.HorizontalOffset = pagePt.X; - DictionaryPopup.VerticalOffset = pagePt.Y; + DictionaryPopup.VerticalOffset = pagePt.Y; DictionaryPopup.DataContext = new PendingEntryResult(cts, entryResultTask, dict); @@ -141,8 +141,8 @@ public void ShowDictionaryPopup() } public async Task LookupWordEntryAsync(RemoteCancellationToken ct, - string word, - IDictionaryService dict) + string word, + IDictionaryService dict) { var lemmas = await dict.LookupLemma(ct, word, (Config.PDFDictionary ?? dict.DefaultDictionary).GetLanguageId()); @@ -335,7 +335,7 @@ protected bool IsEndOfSelectionInScreen() return ClientRect.Contains(topLeftPt); } - public override void ScrollToPoint(int pageIndex, + public override void ScrollToPoint(int pageIndex, Point pagePoint) { int count = Document?.Pages.Count ?? 0; @@ -352,6 +352,21 @@ public override void ScrollToPoint(int pageIndex, pagePoint); } + public void ScrollToAnnotationHighlight(PDFAnnotationHighlight annotation) + { + var point = GetCharPoint(annotation.StartPage, + annotation.StartIndex); + if (PointInPage(point) == -1) + { + ScrollToChar(annotation.EndPage, + annotation.EndIndex); + + var scrollY = -_viewport.Height / 2 - _autoScrollPosition.Y; + + SetVerticalOffset(scrollY); + } + } + protected void ScrollToEndOfSelection() { ScrollToChar(SelectInfo.EndPage, diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 2697029..8b516f8 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -82,8 +82,8 @@ public void ScrollToAnnotationWithId(int annotationId) { if (annotation.AnnotationId == annotationId) { - PDFViewer.ScrollToChar(annotation.StartPage, - annotation.StartIndex); + PDFViewer.ScrollToAnnotationHighlight(annotation); + PDFViewer.ChangeColorOfAnnotationHighlight(annotation); } } } From 0abc1ebd49013c21a41dd563f499a1f65db59a81 Mon Sep 17 00:00:00 2001 From: kpence Date: Wed, 6 Oct 2021 19:22:15 -0500 Subject: [PATCH 09/21] Make the annotations sorted in the side panel based on where they appear on the PDF --- assets/annotationSidePanel.html | 29 +++++++++++++++---- .../PDFAnnotationWebBrowserWrapper.cs | 3 +- .../SuperMemoAssistant.Plugins.PDF.csproj | 1 + 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html index 0506bcb..6ffe707 100644 --- a/assets/annotationSidePanel.html +++ b/assets/annotationSidePanel.html @@ -61,15 +61,34 @@ e.removeChild(e.firstChild); } } - function insertAnnotation(annotationId, text) { + function insertAnnotation(annotationId, sortingKey, text) { var e = document.getElementById("root"); var onUpdate = "handleKeyPress(event)"; var onClick = "handleClick(event)"; annotationId = "annotation"+annotationId; - e.insertAdjacentHTML( - "beforeend", - "
"+text+"

" - ); + var childHtml = "
"+text+"

"; + if (!e.firstChild) { + e.insertAdjacentHTML( + "beforeend", + childHtml + ); + } else { + for (e = e.firstChild; e != null; e = e.nextSibling) { + var key = parseInt(e.className.replace("key","")); + if (parseInt(sortingKey) < key) { + e.insertAdjacentHTML( + "beforebegin", + childHtml + ); + return; + } + } + e = document.getElementById("root"); + e.insertAdjacentHTML( + "beforeend", + childHtml + ); + } } function scrollToAnnotation(annotationId) { var e = document.getElementById("annotation"+annotationId); diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 8b516f8..193cdc6 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -35,7 +35,8 @@ public void InsertAnnotation(PDFAnnotationHighlight annotationHighlight) { var innerHtml = annotationHighlight.HtmlContent; var annotationId = annotationHighlight.AnnotationId; - AnnotationWebBrowser.InvokeScript("insertAnnotation", annotationId, innerHtml); + var annotationSortingKey = annotationHighlight.GetSortingKey(); + AnnotationWebBrowser.InvokeScript("insertAnnotation", annotationId, annotationSortingKey, innerHtml); ScrollToAnnotation(annotationHighlight); } diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index dde1492..e494be1 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -46,6 +46,7 @@ + From 4595c69ad4163fab130919616e99b2523db7d316 Mon Sep 17 00:00:00 2001 From: kpence Date: Fri, 15 Oct 2021 20:56:45 -0500 Subject: [PATCH 10/21] Add GridSplitter to Bookmark side panel to allow for resizing bookmark panel (Bug fix) --- .../PDF/PDFWindow.xaml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml index 96ec252..fc2f232 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml @@ -51,6 +51,7 @@ + @@ -179,8 +180,17 @@ Background="Transparent" /> + + + @@ -246,7 +256,7 @@ - - + Date: Sat, 13 Nov 2021 11:11:09 -0600 Subject: [PATCH 11/21] Clean up PDF annotation webbrowser script --- assets/annotationSidePanel.html | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html index 6ffe707..c65e0ca 100644 --- a/assets/annotationSidePanel.html +++ b/assets/annotationSidePanel.html @@ -1,6 +1,6 @@ - +
- + From 7c170f9cad4db2b8c646ea27ef0d8b5d07124487 Mon Sep 17 00:00:00 2001 From: kpence Date: Sat, 13 Nov 2021 11:13:59 -0600 Subject: [PATCH 12/21] Replace Windows Control Webbrowser with Windows Forms Webbrowser --- .../PDF/PDFWindow.xaml | 11 +++---- .../PDF/PDFWindow.xaml.cs | 18 ++---------- .../PDFAnnotationWebBrowserWrapper.cs | 29 +++++++++++++------ .../SuperMemoAssistant.Plugins.PDF.csproj | 1 + 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml index fc2f232..f9d6a7d 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml @@ -242,11 +242,12 @@ - - + + + Bookmarks.Add(b)); } - private void WebBrowserLoadCompletedEventHandler(object sender, - EventArgs e) - { - AnnotationWebBrowserWrapper.RefreshAnnotations(); - IPDFViewer.PDFElement.AnnotationHighlights.CollectionChanged += - AnnotationWebBrowserWrapper.AnnotationHighlights_CollectionChanged; - } - private void IPDFViewer_OnDocumentClosing(object sender, EventArgs e) { diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 193cdc6..5ca4d3a 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -3,22 +3,33 @@ using SuperMemoAssistant.Plugins.PDF.Models; using System; using System.Collections.Specialized; -using System.Windows.Controls; namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper { public class PDFAnnotationWebBrowserWrapper { private IPDFViewer PDFViewer { get; set; } - private WebBrowser AnnotationWebBrowser { get; set; } - public PDFAnnotationWebBrowserWrapper(WebBrowser webBrowser, IPDFViewer pdfViewer) + private System.Windows.Forms.WebBrowser AnnotationWebBrowser { get; set; } + public PDFAnnotationWebBrowserWrapper(System.Windows.Forms.Integration.WindowsFormsHost wfHost, IPDFViewer pdfViewer) { PDFViewer = pdfViewer; - AnnotationWebBrowser = webBrowser; + AnnotationWebBrowser = new System.Windows.Forms.WebBrowser(); + wfHost.Child = AnnotationWebBrowser; + AnnotationWebBrowser.DocumentCompleted += WebBrowserLoadCompletedEventHandler; var configDir = SMAFileSystem.ConfigDir.Combine("SuperMemoAssistant.Plugins.PDF"); - AnnotationWebBrowser.Source = new Uri($@"{configDir}/annotationSidePanel.html"); + AnnotationWebBrowser.Url = new Uri($@"{configDir}/annotationSidePanel.html"); + AnnotationWebBrowser.WebBrowserShortcutsEnabled = false; AnnotationWebBrowser.ObjectForScripting = this; } + + private void WebBrowserLoadCompletedEventHandler(object sender, + EventArgs e) + { + RefreshAnnotations(); + PDFViewer.PDFElement.AnnotationHighlights.CollectionChanged += + AnnotationHighlights_CollectionChanged; + } + public void RefreshAnnotations() { @@ -28,7 +39,7 @@ public void RefreshAnnotations() public void ClearAnnotations() { - AnnotationWebBrowser.InvokeScript("clearAnnotations"); + AnnotationWebBrowser.Document.InvokeScript("clearAnnotations"); } public void InsertAnnotation(PDFAnnotationHighlight annotationHighlight) @@ -36,13 +47,13 @@ public void InsertAnnotation(PDFAnnotationHighlight annotationHighlight) var innerHtml = annotationHighlight.HtmlContent; var annotationId = annotationHighlight.AnnotationId; var annotationSortingKey = annotationHighlight.GetSortingKey(); - AnnotationWebBrowser.InvokeScript("insertAnnotation", annotationId, annotationSortingKey, innerHtml); + AnnotationWebBrowser.Document.InvokeScript("insertAnnotation", new object[] {annotationId, annotationSortingKey, innerHtml}); ScrollToAnnotation(annotationHighlight); } public void ScrollToAnnotation(PDFAnnotationHighlight annotationHighlight) { - AnnotationWebBrowser.InvokeScript("scrollToAnnotation", annotationHighlight.AnnotationId); + AnnotationWebBrowser.Document.InvokeScript("scrollToAnnotation", new object[] {annotationHighlight.AnnotationId}); } public void AnnotationHighlights_CollectionChanged(object sender, @@ -91,7 +102,7 @@ public void ScrollToAnnotationWithId(int annotationId) public string GetHTMLContentForAnnotationId(int annotationId) { - var document = (mshtml.HTMLDocument)AnnotationWebBrowser.Document; + var document = (mshtml.HTMLDocument)AnnotationWebBrowser.Document.DomDocument; var element = document.getElementById("annotation" + annotationId.ToString()); return element?.innerHTML; } diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj index e494be1..8399aa7 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj +++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj @@ -39,6 +39,7 @@ + From ff15827d7622e5c138758b9fe47e473fe72ed4da Mon Sep 17 00:00:00 2001 From: kpence Date: Sat, 13 Nov 2021 11:15:26 -0600 Subject: [PATCH 13/21] Configure Windows Registry to make PDF Annotation Web browser utilize the latest version of IE --- .../PDFAnnotationWebBrowserWrapper.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 5ca4d3a..3c7ef59 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -6,6 +6,93 @@ namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper { + public class WebBrowserHelper + { + public static int GetEmbVersion() + { + int ieVer = GetBrowserVersion(); + + if (ieVer > 9) + return ieVer * 1000 + 1; + + if (ieVer > 7) + return ieVer * 1111; + + return 7000; + } // End Function GetEmbVersion + + public static void FixBrowserVersion() + { + FixBrowserVersion("PluginHost"); + } + + public static void FixBrowserVersion(string appName) + { + FixBrowserVersion(appName, GetEmbVersion()); + } // End Sub FixBrowserVersion + + public static void FixBrowserVersion(string appName, int ieVer) + { + FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".exe", ieVer); + FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".exe", ieVer); + FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".vshost.exe", ieVer); + FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".vshost.exe", ieVer); + } // End Sub FixBrowserVersion + + private static void FixBrowserVersion_Internal(string root, string appName, int ieVer) + { + try + { + //For 64 bit Machine + if (Environment.Is64BitOperatingSystem) + { + //MessageBox.Show("is 64"); // TODO NOCHECKIN + Microsoft.Win32.Registry.SetValue(root + @"\Software\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer); + //MessageBox.Show("Success for "+appName + "|"+ieVer.ToString()); // TODO NOCHECKIN + } + else //For 32 bit Machine + Microsoft.Win32.Registry.SetValue(root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer); + + + } + catch (Exception exception) + { + // some config will hit access rights exceptions + // this is why we try with both LOCAL_MACHINE and CURRENT_USER + //TODO NOCHECKIN (remove this) + //MessageBox.Show("calledcalled: "+exception.ToString()); + } + } // End Sub FixBrowserVersion_Internal + + public static int GetBrowserVersion() + { + // string strKeyPath = @"HKLM\SOFTWARE\Microsoft\Internet Explorer"; + string strKeyPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer"; + string[] ls = new string[] { "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" }; + + int maxVer = 0; + for (int i = 0; i < ls.Length; ++i) + { + object objVal = Microsoft.Win32.Registry.GetValue(strKeyPath, ls[i], "0"); + string strVal = System.Convert.ToString(objVal); + if (strVal != null) + { + int iPos = strVal.IndexOf('.'); + if (iPos > 0) + strVal = strVal.Substring(0, iPos); + + int res = 0; + if (int.TryParse(strVal, out res)) + maxVer = Math.Max(maxVer, res); + } // End if (strVal != null) + + } // Next i + + //MessageBox.Show("FixBrowserVersion version is" + maxVer.ToString()); // TODO NOCHECKIN + return maxVer; + } // End Function GetBrowserVersion + } + public class PDFAnnotationWebBrowserWrapper { private IPDFViewer PDFViewer { get; set; } @@ -13,6 +100,7 @@ public class PDFAnnotationWebBrowserWrapper public PDFAnnotationWebBrowserWrapper(System.Windows.Forms.Integration.WindowsFormsHost wfHost, IPDFViewer pdfViewer) { PDFViewer = pdfViewer; + WebBrowserHelper.FixBrowserVersion(); AnnotationWebBrowser = new System.Windows.Forms.WebBrowser(); wfHost.Child = AnnotationWebBrowser; AnnotationWebBrowser.DocumentCompleted += WebBrowserLoadCompletedEventHandler; From 8b2e8cb48bc950bf8250733a00ad563be4da857c Mon Sep 17 00:00:00 2001 From: kpence Date: Sat, 13 Nov 2021 16:53:21 -0600 Subject: [PATCH 14/21] Undo changes to PDFPlugin --- src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs index 9ebc4aa..acbaa7f 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDFPlugin.cs @@ -27,7 +27,6 @@ namespace SuperMemoAssistant.Plugins.PDF { - using System.IO; using System.Runtime.Remoting; using Anotar.Serilog; using Dictionary.Interop; @@ -83,7 +82,7 @@ protected override void OnPluginInitialized() if (!PdfCommon.IsInitialize) // TODO: Specify dll path depending on IsDevelopmentPlugin ? - PdfCommon.Initialize(); + PdfCommon.Initialize(PDFLicense.LicenseKey); base.OnPluginInitialized(); } From 15e63265afe19396d5dca05fe476a69ec8162c1e Mon Sep 17 00:00:00 2001 From: kpence Date: Sat, 13 Nov 2021 16:54:17 -0600 Subject: [PATCH 15/21] Update app manifest to force permission to modify registry --- src/SuperMemoAssistant.Plugins.PDF/app.manifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/app.manifest b/src/SuperMemoAssistant.Plugins.PDF/app.manifest index 9e0851b..80fab65 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/app.manifest +++ b/src/SuperMemoAssistant.Plugins.PDF/app.manifest @@ -16,7 +16,7 @@ Remove this element if your application requires this virtualization for backwards compatibility. --> - + From a276a45c7257fb4eceb169982b301c929667ebdc Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 14 Nov 2021 11:39:49 -0600 Subject: [PATCH 16/21] Add Windows hooks into annotation webbrowser for key input; Add annotation text extraction --- assets/annotationSidePanel.html | 51 ++++-- .../PDF/PDFWindow.xaml.cs | 147 ++++++++++++++++++ .../PDF/Viewer/IPDFViewer.SuperMemo.cs | 68 ++++---- .../PDFAnnotationWebBrowserWrapper.cs | 57 ++++++- 4 files changed, 286 insertions(+), 37 deletions(-) diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html index c65e0ca..d0fa2e3 100644 --- a/assets/annotationSidePanel.html +++ b/assets/annotationSidePanel.html @@ -1,9 +1,17 @@ + + +
- diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs index 0680072..1c5ae40 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs @@ -31,13 +31,17 @@ using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Interop; using System.Windows.Media; using Microsoft.Win32; using Patagames.Pdf.Net; @@ -54,6 +58,60 @@ namespace SuperMemoAssistant.Plugins.PDF.PDF { + public class WindowHandleInfo + { + private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam); + + [DllImport("user32")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam); + + private IntPtr _MainHandle; + + public WindowHandleInfo(IntPtr handle) + { + this._MainHandle = handle; + } + + public List GetAllChildHandles() + { + List childHandles = new List(); + + GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles); + IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList); + + try + { + EnumWindowProc childProc = new EnumWindowProc(EnumWindow); + EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList); + } + finally + { + gcChildhandlesList.Free(); + } + + return childHandles; + } + + private bool EnumWindow(IntPtr hWnd, IntPtr lParam) + { + GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam); + + if (gcChildhandlesList == null || gcChildhandlesList.Target == null) + { + return false; + } + + List childHandles = gcChildhandlesList.Target as List; + childHandles.Add(hWnd); + + return true; + } + } + + + + /// Interaction logic for PDFWindow.xaml partial class PDFWindow : Window { @@ -178,10 +236,16 @@ private void IPDFViewer_OnDocumentLoaded(object sender, Bookmarks.Clear(); AnnotationWebBrowserWrapper = new PDFAnnotationWebBrowserWrapper(wfHost, IPDFViewer); + AnnotationWebBrowserWrapper.AnnotationWebBrowser.DocumentCompleted += AnnotationWebBrowser_DocumentCompleted; IPDFViewer.Document?.Bookmarks.ForEach(b => Bookmarks.Add(b)); } + private void AnnotationWebBrowser_DocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e) + { + InstallHook(); + } + private void IPDFViewer_OnDocumentClosing(object sender, EventArgs e) { @@ -581,5 +645,88 @@ private bool DictionaryControl_OnAfterExtract(bool success) } #endregion + + + [DllImport("user32.dll", SetLastError = true)] + private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, IntPtr windowTitle); + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + public static extern IntPtr SetWindowsHookEx(int idHook, HookHandlerDelegate lpfn, IntPtr hInstance, int threadId); + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam); + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + private static extern short GetKeyState(int keyCode); + + + [DllImport("kernel32.dll")] + public static extern int GetCurrentThreadId(); + + [DllImport("user32.dll")] + static extern bool UnhookWindowsHookEx(IntPtr hInstance); + + public delegate IntPtr HookHandlerDelegate(int nCode, IntPtr wParam, IntPtr lParam); + + //Keyboard API constants + private const int WH_GETMESSAGE = 3; + private const int WM_KEYDOWN = 0x0100; + private const int WM_SYSKEYDOWN = 0x0104; + + + private const uint VK_MENU = 0x12; + private const uint VK_X = 0x58; + + //Remove message constants + private const int PM_NOREMOVE = 0x0000; + + //Variables used in the call to SetWindowsHookEx + private IntPtr hHook = IntPtr.Zero; + + private IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr lParam) + { + if (nCode >= 0 || wParam.ToInt32() == PM_NOREMOVE) + { + MSG msg = (MSG)Marshal.PtrToStructure(lParam, typeof(MSG)); + if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) + { + if ((uint)msg.wParam == VK_X && (GetKeyState((int)VK_MENU) & 0x8000) == 0x8000) + { + if (this.IsLoaded && this.IsActive && AnnotationWebBrowserWrapper.AnnotationWebBrowser.Focused) + { + AnnotationWebBrowserWrapper.Extract(); + } + } + } + } + return CallNextHookEx(hHook, nCode, wParam, lParam); + } + + private HookHandlerDelegate hookHandlerDelegate; + + private void InstallHook() + { + IntPtr wnd = AnnotationWebBrowserWrapper.AnnotationWebBrowser.Handle; + if (wnd != IntPtr.Zero) + { + var allChildWindows = new WindowHandleInfo(wnd).GetAllChildHandles(); + wnd = FindWindowEx(wnd, IntPtr.Zero, "Shell Embedding", IntPtr.Zero); + if (wnd != IntPtr.Zero) + { + wnd = FindWindowEx(wnd, IntPtr.Zero, "Shell DocObject View", IntPtr.Zero); + if (wnd != IntPtr.Zero) + { + wnd = FindWindowEx(wnd, IntPtr.Zero, "Internet Explorer_Server", IntPtr.Zero); + if (wnd != IntPtr.Zero) + { + hookHandlerDelegate = new HookHandlerDelegate(HookCallBack); + hHook = SetWindowsHookEx(WH_GETMESSAGE, hookHandlerDelegate, (IntPtr)0, GetCurrentThreadId()); + } + } + } + } + } } } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs index fb64aa5..916dc63 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs @@ -158,32 +158,7 @@ protected bool CreateSMExtract(double priority) // Generate extract if (contents.Count > 0) { - Save(false); - - var bookmarks = pageIndices.Select(FindBookmark) - .Where(b => b != null) - .Distinct() - .Select(b => $"({b.ToHierarchyString()})"); - var bookmarksStr = StringEx.Join(" ; ", bookmarks); - var parentEl = Svc.SM.Registry.Element[PDFElement.ElementId]; - - var templateId = imgExtracts.Count > 0 ? Config.ImageTemplate : Config.TextTemplate; - var template = Svc.SM.Registry.Template[templateId]; - - ret = Svc.SM.Registry.Element.Add( - out _, - ElemCreationFlags.CreateSubfolders, - new ElementBuilder(ElementType.Topic, - contents.ToArray()) - .WithParent(parentEl) - .WithConcept(parentEl.Concept) - .WithLayout(Config.Layout) - .WithTemplate(template) - .WithPriority(priority) - .WithReference(r => PDFElement.ConfigureSMReferences(r, bookmarks: bookmarksStr)) - .WithTitle(extractTitle) - .DoNotDisplay() - ); + ret = CreateAndAddSMExtract(contents, extractTitle, pageIndices, imgExtracts.Count > 0, priority); Window.GetWindow(this)?.Activate(); @@ -222,6 +197,47 @@ protected bool CreateSMExtract(double priority) return ret; } + public bool CreateAndAddSMExtract( + List contents, + string extractTitle, + HashSet pageIndices, + bool useImageTemplate = false, + double? priority = null) + { + if (priority == null) + { + priority = Config.PDFExtractPriority; + } + Save(false); + + var bookmarks = pageIndices.Select(FindBookmark) + .Where(b => b != null) + .Distinct() + .Select(b => $"({b.ToHierarchyString()})"); + var bookmarksStr = StringEx.Join(" ; ", bookmarks); + var parentEl = Svc.SM.Registry.Element[PDFElement.ElementId]; + + var templateId = useImageTemplate ? Config.ImageTemplate : Config.TextTemplate; + var template = Svc.SM.Registry.Template[templateId]; + + var ret = Svc.SM.Registry.Element.Add( + out _, + ElemCreationFlags.CreateSubfolders, + new ElementBuilder(ElementType.Topic, + contents.ToArray()) + .WithParent(parentEl) + .WithConcept(parentEl.Concept) + .WithLayout(Config.Layout) + .WithTemplate(template) + .WithPriority((double)priority) + .WithReference(r => PDFElement.ConfigureSMReferences(r, bookmarks: bookmarksStr)) + .WithTitle(extractTitle) + .DoNotDisplay() + ); + + return ret; + } + [System.Diagnostics.CodeAnalysis.SuppressMessage("AsyncUsage", "AsyncFixer03:Avoid fire & forget async void methods", Justification = "")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "")] diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 3c7ef59..d17f9a5 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -1,8 +1,13 @@ using SuperMemoAssistant.Extensions; using SuperMemoAssistant.Interop; +using SuperMemoAssistant.Interop.SuperMemo.Content.Contents; using SuperMemoAssistant.Plugins.PDF.Models; +using SuperMemoAssistant.Services; using System; +using System.Collections.Generic; using System.Collections.Specialized; +using System.Linq; +using System.Windows; namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper { @@ -96,11 +101,12 @@ public static int GetBrowserVersion() public class PDFAnnotationWebBrowserWrapper { private IPDFViewer PDFViewer { get; set; } - private System.Windows.Forms.WebBrowser AnnotationWebBrowser { get; set; } + private int? SelectedAnnotationId { get; set; } = null; + public System.Windows.Forms.WebBrowser AnnotationWebBrowser { get; set; } public PDFAnnotationWebBrowserWrapper(System.Windows.Forms.Integration.WindowsFormsHost wfHost, IPDFViewer pdfViewer) { PDFViewer = pdfViewer; - WebBrowserHelper.FixBrowserVersion(); + //WebBrowserHelper.FixBrowserVersion(); AnnotationWebBrowser = new System.Windows.Forms.WebBrowser(); wfHost.Child = AnnotationWebBrowser; AnnotationWebBrowser.DocumentCompleted += WebBrowserLoadCompletedEventHandler; @@ -119,6 +125,11 @@ private void WebBrowserLoadCompletedEventHandler(object sender, } + public void Extract() + { + AnnotationWebBrowser.Document.InvokeScript("handleExtract"); + } + public void RefreshAnnotations() { ClearAnnotations(); @@ -160,10 +171,52 @@ public void AnnotationHighlights_CollectionChanged(object sender, } } + public void Annotation_HandleExtract(string extractHtml) + { + var hasTextSelection = string.IsNullOrWhiteSpace(extractHtml) == false; + + if (!hasTextSelection || SelectedAnnotationId == null) + return; + + var annotationHighlight = GetAnnotationHighlightFromId((int)SelectedAnnotationId); + if (annotationHighlight == null) + return; + + var parentEl = Svc.SM.Registry.Element[PDFViewer.PDFElement.ElementId]; + + var pageIndices = new HashSet(); + for (int p = annotationHighlight.StartPage; p <= annotationHighlight.EndPage; p++) + pageIndices.Add(p); + + var titleString = $"{parentEl.Title} -- Annotation extract:"; + var pageString = "p" + string.Join(", p", pageIndices.Select(p => p + 1)); + var extractTitle = $"{titleString} {extractHtml} from Annotation #{SelectedAnnotationId} from {pageString}"; + var contents = new List(); + contents.Add(new TextContent(true, extractHtml)); + + PDFViewer.CreateAndAddSMExtract(contents, extractTitle, pageIndices); + + Window.GetWindow(PDFViewer)?.Activate(); + } + + public void Annotation_OnFocus(int annotationId) { + SelectedAnnotationId = annotationId; + } + public void Annotation_OnClick(int annotationId) => ScrollToAnnotationWithId(annotationId); public void Annotation_OnAfterUpdate() => UpdateAnnotationHighlights(); + public PDFAnnotationHighlight? GetAnnotationHighlightFromId(int annotationId) + { + foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + { + if (annotation.AnnotationId == annotationId) + return annotation; + } + return null; + } + public void UpdateAnnotationHighlights() { PDFViewer.PDFElement.IsChanged = true; From ef78b99f5e8af31f123d1dcfbc7843c466198fe0 Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 14 Nov 2021 11:42:09 -0600 Subject: [PATCH 17/21] Remove unnecessary IE version registry changing code --- .../PDFAnnotationWebBrowserWrapper.cs | 88 ------------------- .../app.manifest | 2 +- 2 files changed, 1 insertion(+), 89 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index d17f9a5..1c7ad69 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -11,93 +11,6 @@ namespace SuperMemoAssistant.Plugins.PDF.PDF.Viewer.WebBrowserWrapper { - public class WebBrowserHelper - { - public static int GetEmbVersion() - { - int ieVer = GetBrowserVersion(); - - if (ieVer > 9) - return ieVer * 1000 + 1; - - if (ieVer > 7) - return ieVer * 1111; - - return 7000; - } // End Function GetEmbVersion - - public static void FixBrowserVersion() - { - FixBrowserVersion("PluginHost"); - } - - public static void FixBrowserVersion(string appName) - { - FixBrowserVersion(appName, GetEmbVersion()); - } // End Sub FixBrowserVersion - - public static void FixBrowserVersion(string appName, int ieVer) - { - FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".exe", ieVer); - FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".exe", ieVer); - FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".vshost.exe", ieVer); - FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".vshost.exe", ieVer); - } // End Sub FixBrowserVersion - - private static void FixBrowserVersion_Internal(string root, string appName, int ieVer) - { - try - { - //For 64 bit Machine - if (Environment.Is64BitOperatingSystem) - { - //MessageBox.Show("is 64"); // TODO NOCHECKIN - Microsoft.Win32.Registry.SetValue(root + @"\Software\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer); - //MessageBox.Show("Success for "+appName + "|"+ieVer.ToString()); // TODO NOCHECKIN - } - else //For 32 bit Machine - Microsoft.Win32.Registry.SetValue(root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer); - - - } - catch (Exception exception) - { - // some config will hit access rights exceptions - // this is why we try with both LOCAL_MACHINE and CURRENT_USER - //TODO NOCHECKIN (remove this) - //MessageBox.Show("calledcalled: "+exception.ToString()); - } - } // End Sub FixBrowserVersion_Internal - - public static int GetBrowserVersion() - { - // string strKeyPath = @"HKLM\SOFTWARE\Microsoft\Internet Explorer"; - string strKeyPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer"; - string[] ls = new string[] { "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" }; - - int maxVer = 0; - for (int i = 0; i < ls.Length; ++i) - { - object objVal = Microsoft.Win32.Registry.GetValue(strKeyPath, ls[i], "0"); - string strVal = System.Convert.ToString(objVal); - if (strVal != null) - { - int iPos = strVal.IndexOf('.'); - if (iPos > 0) - strVal = strVal.Substring(0, iPos); - - int res = 0; - if (int.TryParse(strVal, out res)) - maxVer = Math.Max(maxVer, res); - } // End if (strVal != null) - - } // Next i - - //MessageBox.Show("FixBrowserVersion version is" + maxVer.ToString()); // TODO NOCHECKIN - return maxVer; - } // End Function GetBrowserVersion - } - public class PDFAnnotationWebBrowserWrapper { private IPDFViewer PDFViewer { get; set; } @@ -106,7 +19,6 @@ public class PDFAnnotationWebBrowserWrapper public PDFAnnotationWebBrowserWrapper(System.Windows.Forms.Integration.WindowsFormsHost wfHost, IPDFViewer pdfViewer) { PDFViewer = pdfViewer; - //WebBrowserHelper.FixBrowserVersion(); AnnotationWebBrowser = new System.Windows.Forms.WebBrowser(); wfHost.Child = AnnotationWebBrowser; AnnotationWebBrowser.DocumentCompleted += WebBrowserLoadCompletedEventHandler; diff --git a/src/SuperMemoAssistant.Plugins.PDF/app.manifest b/src/SuperMemoAssistant.Plugins.PDF/app.manifest index 80fab65..b692f73 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/app.manifest +++ b/src/SuperMemoAssistant.Plugins.PDF/app.manifest @@ -16,7 +16,7 @@ Remove this element if your application requires this virtualization for backwards compatibility. --> - + From 5e75182c597fe7c5a1fa539c21d07e43c4fe7aa5 Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 14 Nov 2021 11:45:22 -0600 Subject: [PATCH 18/21] Change annotation extract highlight color to light blue --- assets/annotationSidePanel.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html index d0fa2e3..c879077 100644 --- a/assets/annotationSidePanel.html +++ b/assets/annotationSidePanel.html @@ -3,7 +3,7 @@ From 720f8793fd99cd0b08ecfd7ae5cfa2b1e5d6f75a Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 14 Nov 2021 11:50:44 -0600 Subject: [PATCH 19/21] Add shortcut to opening annotation side panel --- src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs | 6 ++++++ src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs index 1c5ae40..401eac2 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs @@ -354,6 +354,12 @@ private void Window_KeyDown(object sender, e.Handled = true; break; + case PDFHotKeys.UIToggleAnnotations: + btnAnnotations.IsChecked = !btnAnnotations.IsChecked; + AnnotationWebBrowserWrapper.AnnotationWebBrowser.Focus(); + e.Handled = true; + break; + case PDFHotKeys.UIFocusViewer: IPDFViewer.Focus(); e.Handled = true; diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs b/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs index 7f4008e..04264ff 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDFHotKeys.cs @@ -62,6 +62,7 @@ internal static class PDFHotKeys public const string SMPrevSibling = "SMPrevSibling"; public const string SMNextSibling = "SMNextSibling"; public const string UIShowOptions = "UIShowOptions"; + public const string UIToggleAnnotations = "UIToggleAnnotations"; public const string UIToggleBookmarks = "UIToggleBookmarks"; public const string UIFocusViewer = "UIFocusViewer"; public const string UIFocusBookmarks = "UIFocusBookmarks"; @@ -181,6 +182,10 @@ public static void RegisterHotKeys() "Show options", new HotKey(Key.O, KeyModifiers.Ctrl) ) + .RegisterLocal(UIToggleAnnotations, + "Toggle annotations", + new HotKey(Key.A, KeyModifiers.Ctrl) + ) .RegisterLocal(UIToggleBookmarks, "Toggle bookmarks", new HotKey(Key.B, KeyModifiers.Ctrl) From 4eb00de2cf9b18389e5039a91b012907b2a7bebd Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 12 Dec 2021 18:34:56 -0600 Subject: [PATCH 20/21] Change AnnotationHighlights to using a dictionary that indexes by PDF page --- .../Models/PDFAnnotationHighlight.cs | 7 +++ .../PDF/PDFElement.cs | 57 +++++++++++++----- .../PDF/Viewer/IPDFViewer.Selection.cs | 21 +++++-- .../PDF/Viewer/IPDFViewer.SuperMemo.cs | 9 ++- .../PDF/Viewer/IPDFViewer.cs | 2 +- .../PDFAnnotationWebBrowserWrapper.cs | 59 ++++++++++--------- .../Utils/Web/HtmlBuilder.cs | 15 ++--- .../version.json | 2 +- 8 files changed, 111 insertions(+), 61 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs index 5a4665a..91c1253 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs @@ -32,9 +32,16 @@ using Newtonsoft.Json; using Patagames.Pdf.Net.Controls.Wpf; +using System; +using System.Collections.Generic; namespace SuperMemoAssistant.Plugins.PDF.Models { + public class AnnotationAddedEventArgs : EventArgs + { + public PDFAnnotationHighlight NewItem { get; set; } + } + public class PDFAnnotationHighlight : PDFTextExtract { #region Properties & Fields - Public diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs index 1c06f86..5cd93cf 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs @@ -28,6 +28,7 @@ namespace SuperMemoAssistant.Plugins.PDF.PDF { using System; + using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; @@ -60,26 +61,29 @@ public class PDFElement : INotifyPropertyChanged { #region Constructors + public delegate void AnnotationAdded(object sender, AnnotationAddedEventArgs e); + public event AnnotationAdded OnAnnotationAdded; + public PDFElement() { - BinaryMemberId = -1; - StartPage = -1; - EndPage = -1; - StartIndex = -1; - EndIndex = -1; - ReadPage = 0; - ReadPoint = default; - PDFExtracts = new ObservableCollection(); - SMExtracts = new ObservableCollection(); - SMImgExtracts = new ObservableCollection(); + BinaryMemberId = -1; + StartPage = -1; + EndPage = -1; + StartIndex = -1; + EndIndex = -1; + ReadPage = 0; + ReadPoint = default; + PDFExtracts = new ObservableCollection(); + SMExtracts = new ObservableCollection(); + SMImgExtracts = new ObservableCollection(); IgnoreHighlights = new ObservableCollection(); - AnnotationHighlights = new ObservableCollection(); + AnnotationHighlights = new Dictionary>(); - PDFExtracts.CollectionChanged += OnCollectionChanged; - SMExtracts.CollectionChanged += OnCollectionChanged; - SMImgExtracts.CollectionChanged += OnCollectionChanged; + PDFExtracts.CollectionChanged += OnCollectionChanged; + SMExtracts.CollectionChanged += OnCollectionChanged; + SMImgExtracts.CollectionChanged += OnCollectionChanged; IgnoreHighlights.CollectionChanged += OnCollectionChanged; - AnnotationHighlights.CollectionChanged += OnCollectionChanged; + OnAnnotationAdded += OnAnnotationAddedEffect; } #endregion @@ -110,7 +114,7 @@ public PDFElement() [JsonProperty(PropertyName = "IH")] public ObservableCollection IgnoreHighlights { get; } [JsonProperty(PropertyName = "AH")] - public ObservableCollection AnnotationHighlights { get; } + public Dictionary> AnnotationHighlights { get; } [JsonProperty(PropertyName = "RPg")] public int ReadPage { get; set; } @@ -586,6 +590,27 @@ private void OnCollectionChanged(object sender, IsChanged = true; } + [SuppressPropertyChangedWarnings] + private void OnAnnotationAddedEffect(object sender, + AnnotationAddedEventArgs e) + { + IsChanged = true; + } + + public void AddAnnotationHighlight(PDFAnnotationHighlight annotationHighlight) + { + OnAnnotationAdded(this, new AnnotationAddedEventArgs() { + NewItem = annotationHighlight + }); + + int page = annotationHighlight.StartPage; + if (!AnnotationHighlights.ContainsKey(page)) + { + AnnotationHighlights[page] = new List(); + } + AnnotationHighlights[page].Add(annotationHighlight); + } + #endregion diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs index eb87724..354e228 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.Selection.cs @@ -397,13 +397,18 @@ protected bool OnMouseMoveProcessSelection(MouseEventArgs e, if (CurrentAnnotationHighlight == null) { // TODO Check if hovering over any annotationHighlights and then change the color - foreach (PDFAnnotationHighlight annotationHighlight in PDFElement.AnnotationHighlights) + if (PDFElement.AnnotationHighlights.ContainsKey(pageIndex)) { - if (charIndex > annotationHighlight.StartIndex - && charIndex < annotationHighlight.EndIndex) + var annotationHighlightsAtPageIndex = PDFElement.AnnotationHighlights[pageIndex]; + + foreach (PDFAnnotationHighlight annotationHighlight in annotationHighlightsAtPageIndex) { - ChangeColorOfAnnotationHighlight(annotationHighlight); - CurrentAnnotationHighlight = annotationHighlight; + if (charIndex > annotationHighlight.StartIndex + && charIndex < annotationHighlight.EndIndex) + { + ChangeColorOfAnnotationHighlight(annotationHighlight); + CurrentAnnotationHighlight = annotationHighlight; + } } } } @@ -434,7 +439,11 @@ public void ChangeColorOfAnnotationHighlight(PDFAnnotationHighlight? annotation) PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); - PDFElement.AnnotationHighlights.ForEach(a => AddAnnotationHighlight(a, annotation != null && a == annotation)); + PDFElement.AnnotationHighlights.ForEach( + alist => alist.Value.ForEach( + a => AddAnnotationHighlight(a, annotation != null && a == annotation) + ) + ); } protected bool OnMouseUpProcessSelection(MouseButtonEventArgs e, diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs index 916dc63..bcc0cac 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs @@ -380,12 +380,15 @@ protected bool CreateAnnotationHighlight() foreach (var selInfo in SelectInfos) { var count = 0; - foreach (PDFAnnotationHighlight a in PDFElement.AnnotationHighlights) + foreach (var annotationHighlightsAtPageIndex in PDFElement.AnnotationHighlights) { - count = (a.AnnotationId >= count) ? a.AnnotationId + 1 : count; + foreach (PDFAnnotationHighlight a in annotationHighlightsAtPageIndex.Value) + { + count = (a.AnnotationId >= count) ? a.AnnotationId + 1 : count; + } } var annotationHighlight = PDFAnnotationHighlight.Create(selInfo, count); - PDFElement.AnnotationHighlights.Add(annotationHighlight); + PDFElement.AddAnnotationHighlight(annotationHighlight); AddAnnotationHighlight(annotationHighlight); } diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs index b7bf74d..9317e90 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs @@ -132,7 +132,7 @@ protected override void OnDocumentLoaded(EventArgs ev) PDFElement.SMExtracts.ForEach(AddSMExtractHighlight); PDFElement.SMImgExtracts.ForEach(e => AddImgExtractHighlight(e.PageIndex, e.BoundingBox)); PDFElement.IgnoreHighlights.ForEach(AddIgnoreHighlight); - PDFElement.AnnotationHighlights.ForEach(AddAnnotationHighlight); + PDFElement.AnnotationHighlights.ForEach(e => e.Value.ForEach(AddAnnotationHighlight)); GenerateOutOfExtractHighlights(); diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs index 1c7ad69..ae772e8 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs @@ -32,8 +32,8 @@ private void WebBrowserLoadCompletedEventHandler(object sender, EventArgs e) { RefreshAnnotations(); - PDFViewer.PDFElement.AnnotationHighlights.CollectionChanged += - AnnotationHighlights_CollectionChanged; + PDFViewer.PDFElement.OnAnnotationAdded += + AnnotationHighlights_AnnotationAdded; } @@ -45,7 +45,11 @@ public void Extract() public void RefreshAnnotations() { ClearAnnotations(); - PDFViewer.PDFElement.AnnotationHighlights.ForEach(a => InsertAnnotation(a)); + PDFViewer.PDFElement.AnnotationHighlights.ForEach( + alist => alist.Value.ForEach( + a => InsertAnnotation(a) + ) + ); } public void ClearAnnotations() @@ -67,20 +71,12 @@ public void ScrollToAnnotation(PDFAnnotationHighlight annotationHighlight) AnnotationWebBrowser.Document.InvokeScript("scrollToAnnotation", new object[] {annotationHighlight.AnnotationId}); } - public void AnnotationHighlights_CollectionChanged(object sender, - NotifyCollectionChangedEventArgs e) + public void AnnotationHighlights_AnnotationAdded(object sender, + AnnotationAddedEventArgs e) { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - foreach (PDFAnnotationHighlight annotation in e.NewItems) - { - InsertAnnotation(annotation); - PDFViewer.PDFElement.IsChanged = true; - PDFViewer.PDFElement.Save(); - } - break; - } + InsertAnnotation(e.NewItem); + PDFViewer.PDFElement.IsChanged = true; + PDFViewer.PDFElement.Save(); } public void Annotation_HandleExtract(string extractHtml) @@ -121,10 +117,13 @@ public void Annotation_OnFocus(int annotationId) { public PDFAnnotationHighlight? GetAnnotationHighlightFromId(int annotationId) { - foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + foreach (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights) { - if (annotation.AnnotationId == annotationId) - return annotation; + foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value) + { + if (annotation.AnnotationId == annotationId) + return annotation; + } } return null; } @@ -132,23 +131,29 @@ public void Annotation_OnFocus(int annotationId) { public void UpdateAnnotationHighlights() { PDFViewer.PDFElement.IsChanged = true; - foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + foreach (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights) { - annotation.HtmlContent = - GetHTMLContentForAnnotationId(annotation.AnnotationId) - ?? annotation.HtmlContent; + foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value) + { + annotation.HtmlContent = + GetHTMLContentForAnnotationId(annotation.AnnotationId) + ?? annotation.HtmlContent; + } } PDFViewer.PDFElement.Save(); } public void ScrollToAnnotationWithId(int annotationId) { - foreach (PDFAnnotationHighlight annotation in PDFViewer.PDFElement.AnnotationHighlights) + foreach (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights) { - if (annotation.AnnotationId == annotationId) + foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value) { - PDFViewer.ScrollToAnnotationHighlight(annotation); - PDFViewer.ChangeColorOfAnnotationHighlight(annotation); + if (annotation.AnnotationId == annotationId) + { + PDFViewer.ScrollToAnnotationHighlight(annotation); + PDFViewer.ChangeColorOfAnnotationHighlight(annotation); + } } } } diff --git a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs index b5da26b..9faa9c2 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs @@ -521,13 +521,14 @@ private void GenerateExtractSpans() SMConst.Stylesheet.IgnoreColor, pageSpanDict); - foreach (var annotationHighlight in PdfElement.AnnotationHighlights) - SplitExtractByPage(annotationHighlight, - Color.FromArgb(90, - 100, - 255, - 100), - pageSpanDict); + foreach (var annotationsOnPage in PdfElement.AnnotationHighlights) + foreach (var annotationHighlight in annotationsOnPage.Value) + SplitExtractByPage(annotationHighlight, + Color.FromArgb(90, + 100, + 255, + 100), + pageSpanDict); foreach (var pageSpan in pageSpanDict) GenerateExtractSpans(pageSpan.Key, diff --git a/src/SuperMemoAssistant.Plugins.PDF/version.json b/src/SuperMemoAssistant.Plugins.PDF/version.json index 634c556..4dc71a1 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/version.json +++ b/src/SuperMemoAssistant.Plugins.PDF/version.json @@ -1,3 +1,3 @@ { - "version": "2.1.0-alpha" + "version": "2.1.0" } \ No newline at end of file From b9940857e6b7a7e209e9345c92212feb787fab7f Mon Sep 17 00:00:00 2001 From: kpence Date: Sun, 12 Dec 2021 18:55:16 -0600 Subject: [PATCH 21/21] Make it so the highlighted text is the initial content for the annotation --- .../Models/PDFAnnotationHighlight.cs | 4 ++-- .../PDF/Viewer/IPDFViewer.SuperMemo.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs index 91c1253..6574afa 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs @@ -70,14 +70,14 @@ public static implicit operator PDFAnnotationHighlight(SelectInfo selInfo) }; } - public static PDFAnnotationHighlight Create(SelectInfo selInfo, int annotationId) + public static PDFAnnotationHighlight Create(SelectInfo selInfo, int annotationId, string initialContent) => new PDFAnnotationHighlight { StartPage = selInfo.StartPage, StartIndex = selInfo.StartIndex, EndPage = selInfo.EndPage, EndIndex = selInfo.EndIndex, - HtmlContent = "
", + HtmlContent = "
"+initialContent+"
", AnnotationId = annotationId }; diff --git a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs index bcc0cac..659a655 100644 --- a/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs +++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs @@ -387,7 +387,7 @@ protected bool CreateAnnotationHighlight() count = (a.AnnotationId >= count) ? a.AnnotationId + 1 : count; } } - var annotationHighlight = PDFAnnotationHighlight.Create(selInfo, count); + var annotationHighlight = PDFAnnotationHighlight.Create(selInfo, count, GetSelectedTextAsHtml()); PDFElement.AddAnnotationHighlight(annotationHighlight); AddAnnotationHighlight(annotationHighlight); }