diff --git a/assets/annotationSidePanel.html b/assets/annotationSidePanel.html
new file mode 100644
index 0000000..c879077
--- /dev/null
+++ b/assets/annotationSidePanel.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/icons/sideBarAnnotation.png b/assets/images/icons/sideBarAnnotation.png
new file mode 100644
index 0000000..a7911c8
Binary files /dev/null and b/assets/images/icons/sideBarAnnotation.png differ
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/Models/PDFAnnotationHighlight.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs
new file mode 100644
index 0000000..6574afa
--- /dev/null
+++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFAnnotationHighlight.cs
@@ -0,0 +1,88 @@
+#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;
+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
+
+ [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, string initialContent)
+ => new PDFAnnotationHighlight
+ {
+ StartPage = selInfo.StartPage,
+ StartIndex = selInfo.StartIndex,
+ EndPage = selInfo.EndPage,
+ EndIndex = selInfo.EndIndex,
+ HtmlContent = ""+initialContent+"
",
+ AnnotationId = annotationId
+ };
+
+ public int GetSortingKey() => StartPage * 10000 + StartIndex;
+
+ #endregion
+ }
+}
diff --git a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs
index 78aaa05..9bf8016 100644
--- a/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs
+++ b/src/SuperMemoAssistant.Plugins.PDF/Models/PDFCfg.cs
@@ -161,6 +161,14 @@ 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,
+ 100);
public double WindowTop { get; set; } = 100;
public double WindowHeight { get; set; } = 600;
@@ -168,7 +176,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/PDFElement.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFElement.cs
index c0c12cc..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,24 +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 Dictionary>();
- PDFExtracts.CollectionChanged += OnCollectionChanged;
- SMExtracts.CollectionChanged += OnCollectionChanged;
- SMImgExtracts.CollectionChanged += OnCollectionChanged;
+ PDFExtracts.CollectionChanged += OnCollectionChanged;
+ SMExtracts.CollectionChanged += OnCollectionChanged;
+ SMImgExtracts.CollectionChanged += OnCollectionChanged;
IgnoreHighlights.CollectionChanged += OnCollectionChanged;
+ OnAnnotationAdded += OnAnnotationAddedEffect;
}
#endregion
@@ -107,6 +113,8 @@ public PDFElement()
public ObservableCollection SMImgExtracts { get; }
[JsonProperty(PropertyName = "IH")]
public ObservableCollection IgnoreHighlights { get; }
+ [JsonProperty(PropertyName = "AH")]
+ public Dictionary> AnnotationHighlights { get; }
[JsonProperty(PropertyName = "RPg")]
public int ReadPage { get; set; }
@@ -501,6 +509,7 @@ private string GetJsonB64()
string elementJson = JsonConvert.SerializeObject(this,
Formatting.None);
+ //MessageBox.Show("GetJsonB64: " + elementJson.Replace("HTML", "\nHTML")); // TODO NOCHECKIN
return elementJson.ToBase64();
}
@@ -581,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/PDFWindow.xaml b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml
index b19f187..f9d6a7d 100644
--- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml
+++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml
@@ -11,124 +11,138 @@
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..401eac2 100644
--- a/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs
+++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/PDFWindow.xaml.cs
@@ -31,18 +31,23 @@
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;
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;
@@ -53,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
{
@@ -68,9 +127,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 +154,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);
}
@@ -146,7 +209,8 @@ protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
if (Equals(e.NewFocus,
tvBookmarks)
- || e.NewFocus is TreeViewItem)
+ || e.NewFocus is TreeViewItem
+ || e.NewFocus is WebBrowser)
return;
IPDFViewer.Focus();
@@ -171,9 +235,17 @@ 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)
{
@@ -232,7 +304,8 @@ private void SaveConfig()
Width,
WindowState);
- Config.SidePanelWidth = _lastSidePanelWidth;
+ Config.SidePanelBookmarksWidth = _lastSidePanelBookmarksWidth;
+ Config.SidePanelAnnotationsWidth = _lastSidePanelAnnotationsWidth;
PDFState.Instance.SaveConfigAsync().RunAsync();
}
);
@@ -243,6 +316,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)
+ {
+ AnnotationWebBrowserWrapper.ScrollToAnnotation(currentHighlightAnnotation);
+ }
+ }
+
private void Window_KeyDown(object sender,
KeyEventArgs e)
{
@@ -267,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;
@@ -378,18 +471,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 +514,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 (sidePanelBookmarks.Visibility == Visibility.Visible)
+ {
+ _lastSidePanelBookmarksWidth = sidePanelBookmarksColumn.ActualWidth;
+
+ sidePanelBookmarksColumn.Width = new GridLength(0);
+ }
+ }
+ }
+
+ 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 (sidePanel.Visibility == Visibility.Visible)
+ if (sidePanelAnnotations.Visibility == Visibility.Visible)
{
- _lastSidePanelWidth = sidePanelColumn.ActualWidth;
+ _lastSidePanelAnnotationsWidth = sidePanelAnnotationsColumn.ActualWidth;
- sidePanelColumn.Width = new GridLength(0);
+ sidePanelAnnotationsColumn.Width = new GridLength(0);
}
}
}
- private void SidePanel_SizeChanged(object sender,
+ 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);
}
}
}
@@ -485,5 +651,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.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..354e228 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;
///
@@ -62,13 +63,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,12 +391,61 @@ 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
+ if (PDFElement.AnnotationHighlights.ContainsKey(pageIndex))
+ {
+ var annotationHighlightsAtPageIndex = PDFElement.AnnotationHighlights[pageIndex];
+
+ foreach (PDFAnnotationHighlight annotationHighlight in annotationHighlightsAtPageIndex)
+ {
+ if (charIndex > annotationHighlight.StartIndex
+ && charIndex < annotationHighlight.EndIndex)
+ {
+ ChangeColorOfAnnotationHighlight(annotationHighlight);
+ CurrentAnnotationHighlight = annotationHighlight;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (charIndex < CurrentAnnotationHighlight.StartIndex
+ || charIndex > CurrentAnnotationHighlight.EndIndex)
+ {
+ ChangeColorOfAnnotationHighlight(null);
+ CurrentAnnotationHighlight = null;
+ }
+ }
+ }
+
if (invalidate)
InvalidateVisual();
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(
+ alist => alist.Value.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.SuperMemo.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.SuperMemo.cs
index 0a8719d..659a655 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 = "")]
@@ -356,6 +372,31 @@ protected bool CreateIgnoreHighlight()
return true;
}
+ protected bool CreateAnnotationHighlight()
+ {
+ if (IsTextSelectionValid(out _) == false)
+ return false;
+
+ foreach (var selInfo in SelectInfos)
+ {
+ var count = 0;
+ foreach (var annotationHighlightsAtPageIndex in PDFElement.AnnotationHighlights)
+ {
+ foreach (PDFAnnotationHighlight a in annotationHighlightsAtPageIndex.Value)
+ {
+ count = (a.AnnotationId >= count) ? a.AnnotationId + 1 : count;
+ }
+ }
+ var annotationHighlight = PDFAnnotationHighlight.Create(selInfo, count, GetSelectedTextAsHtml());
+ PDFElement.AddAnnotationHighlight(annotationHighlight);
+ AddAnnotationHighlight(annotationHighlight);
+ }
+
+ DeselectText();
+
+ return true;
+ }
+
//
// Highlights
@@ -419,6 +460,19 @@ protected void AddIgnoreHighlight(PDFTextExtract extract)
AddHighlight(extract, Config.IgnoreHighlightColor);
}
+ protected void AddAnnotationHighlight(PDFTextExtract extract)
+ => AddAnnotationHighlight(extract, false);
+
+ protected void AddAnnotationHighlight(PDFTextExtract extract, bool isFocused)
+ {
+ AddHighlight(
+ extract,
+ isFocused
+ ? Config.FocusedAnnotationHighlightColor
+ : Config.AnnotationHighlightColor
+ );
+ }
+
protected void AddHighlight(PDFTextExtract extract,
System.Windows.Media.Color highlightColor)
{
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/IPDFViewer.cs b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/IPDFViewer.cs
index 0f93959..9317e90 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(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
new file mode 100644
index 0000000..ae772e8
--- /dev/null
+++ b/src/SuperMemoAssistant.Plugins.PDF/PDF/Viewer/WebBrowserWrapper/PDFAnnotationWebBrowserWrapper.cs
@@ -0,0 +1,168 @@
+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
+{
+ public class PDFAnnotationWebBrowserWrapper
+ {
+ private IPDFViewer PDFViewer { 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;
+ AnnotationWebBrowser = new System.Windows.Forms.WebBrowser();
+ wfHost.Child = AnnotationWebBrowser;
+ AnnotationWebBrowser.DocumentCompleted += WebBrowserLoadCompletedEventHandler;
+ var configDir = SMAFileSystem.ConfigDir.Combine("SuperMemoAssistant.Plugins.PDF");
+ AnnotationWebBrowser.Url = new Uri($@"{configDir}/annotationSidePanel.html");
+ AnnotationWebBrowser.WebBrowserShortcutsEnabled = false;
+ AnnotationWebBrowser.ObjectForScripting = this;
+ }
+
+ private void WebBrowserLoadCompletedEventHandler(object sender,
+ EventArgs e)
+ {
+ RefreshAnnotations();
+ PDFViewer.PDFElement.OnAnnotationAdded +=
+ AnnotationHighlights_AnnotationAdded;
+ }
+
+
+ public void Extract()
+ {
+ AnnotationWebBrowser.Document.InvokeScript("handleExtract");
+ }
+
+ public void RefreshAnnotations()
+ {
+ ClearAnnotations();
+ PDFViewer.PDFElement.AnnotationHighlights.ForEach(
+ alist => alist.Value.ForEach(
+ a => InsertAnnotation(a)
+ )
+ );
+ }
+
+ public void ClearAnnotations()
+ {
+ AnnotationWebBrowser.Document.InvokeScript("clearAnnotations");
+ }
+
+ public void InsertAnnotation(PDFAnnotationHighlight annotationHighlight)
+ {
+ var innerHtml = annotationHighlight.HtmlContent;
+ var annotationId = annotationHighlight.AnnotationId;
+ var annotationSortingKey = annotationHighlight.GetSortingKey();
+ AnnotationWebBrowser.Document.InvokeScript("insertAnnotation", new object[] {annotationId, annotationSortingKey, innerHtml});
+ ScrollToAnnotation(annotationHighlight);
+ }
+
+ public void ScrollToAnnotation(PDFAnnotationHighlight annotationHighlight)
+ {
+ AnnotationWebBrowser.Document.InvokeScript("scrollToAnnotation", new object[] {annotationHighlight.AnnotationId});
+ }
+
+ public void AnnotationHighlights_AnnotationAdded(object sender,
+ AnnotationAddedEventArgs e)
+ {
+ InsertAnnotation(e.NewItem);
+ PDFViewer.PDFElement.IsChanged = true;
+ PDFViewer.PDFElement.Save();
+ }
+
+ 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 (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights)
+ {
+ foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value)
+ {
+ if (annotation.AnnotationId == annotationId)
+ return annotation;
+ }
+ }
+ return null;
+ }
+
+ public void UpdateAnnotationHighlights()
+ {
+ PDFViewer.PDFElement.IsChanged = true;
+ foreach (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights)
+ {
+ foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value)
+ {
+ annotation.HtmlContent =
+ GetHTMLContentForAnnotationId(annotation.AnnotationId)
+ ?? annotation.HtmlContent;
+ }
+ }
+ PDFViewer.PDFElement.Save();
+ }
+
+ public void ScrollToAnnotationWithId(int annotationId)
+ {
+ foreach (var annotationsOnPage in PDFViewer.PDFElement.AnnotationHighlights)
+ {
+ foreach (PDFAnnotationHighlight annotation in annotationsOnPage.Value)
+ {
+ if (annotation.AnnotationId == annotationId)
+ {
+ PDFViewer.ScrollToAnnotationHighlight(annotation);
+ PDFViewer.ChangeColorOfAnnotationHighlight(annotation);
+ }
+ }
+ }
+ }
+
+ public string GetHTMLContentForAnnotationId(int annotationId)
+ {
+ var document = (mshtml.HTMLDocument)AnnotationWebBrowser.Document.DomDocument;
+ 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..04264ff 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";
@@ -61,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";
@@ -104,6 +106,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
@@ -176,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)
diff --git a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj
index 1265db3..8399aa7 100644
--- a/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj
+++ b/src/SuperMemoAssistant.Plugins.PDF/SuperMemoAssistant.Plugins.PDF.csproj
@@ -39,12 +39,15 @@
+
+
+
@@ -124,7 +127,10 @@
$(PkgPdfium_Net_SDK)\lib\net472\Patagames.Pdf.dll
-
+
+
+
+
diff --git a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs
index 8d08ee1..9faa9c2 100644
--- a/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs
+++ b/src/SuperMemoAssistant.Plugins.PDF/Utils/Web/HtmlBuilder.cs
@@ -521,6 +521,15 @@ private void GenerateExtractSpans()
SMConst.Stylesheet.IgnoreColor,
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,
pageSpan.Value
diff --git a/src/SuperMemoAssistant.Plugins.PDF/app.manifest b/src/SuperMemoAssistant.Plugins.PDF/app.manifest
index 9e0851b..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.
-->
-
+
diff --git a/src/SuperMemoAssistant.Plugins.PDF/version.json b/src/SuperMemoAssistant.Plugins.PDF/version.json
index c62f9b7..4dc71a1 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"
}
\ No newline at end of file