Skip to content

Commit

Permalink
add support for drag and drop images to note windows;
Browse files Browse the repository at this point in the history
other minor optimizations;
bump version;
  • Loading branch information
changbowen committed Nov 4, 2022
1 parent 7121491 commit ce7e631
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 38 deletions.
135 changes: 134 additions & 1 deletion Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
using System.Threading;
using System.Windows;
using System.Windows.Documents;
using System.Xml.Linq;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using Size = System.Drawing.Size;
using System.Windows.Controls;

namespace DesktopNote
{
Expand Down Expand Up @@ -185,7 +188,137 @@ internal static string SaveNote(MainWindow win)
return exMsg;
}

internal static BitmapSource GetImageSource(Stream stream, Size decodeSize = default)
{
try {
stream.Position = 0;
var frame = BitmapFrame.Create(stream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
var pixelSize = new Size(frame.PixelWidth, frame.PixelHeight);
ushort orien = 0;
if ((frame.Metadata as BitmapMetadata)?.GetQuery("/app1/ifd/{ushort=274}") is ushort u)
orien = u;
frame = null;

//calculate decode size
if (decodeSize.Width + decodeSize.Height > 0) {
//use pixelSize if decodeSize is too big
//DecodePixelWidth / Height is set to PixelWidth / Height anyway in reference source
if (decodeSize.Width > pixelSize.Width) decodeSize.Width = pixelSize.Width;
if (decodeSize.Height > pixelSize.Height) decodeSize.Height = pixelSize.Height;

//flip decodeSize according to orientation
if (orien > 4 && orien < 9)
decodeSize = new Size(decodeSize.Height, decodeSize.Width);
}

//init bitmapimage
stream.Position = 0;
var bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
if (pixelSize.Width > 0 && pixelSize.Height > 0) {
//setting both DecodePixelWidth and Height will break the aspect ratio
var imgRatio = (double)pixelSize.Width / pixelSize.Height;
if (decodeSize.Width > 0 && decodeSize.Height > 0) {
if (imgRatio > (double)decodeSize.Width / decodeSize.Height)
bi.DecodePixelHeight = decodeSize.Height;
else
bi.DecodePixelWidth = decodeSize.Width;
}
else if (decodeSize.Width == 0 && decodeSize.Height > 0)
bi.DecodePixelHeight = decodeSize.Height;
else if (decodeSize.Height == 0 && decodeSize.Width > 0)
bi.DecodePixelWidth = decodeSize.Width;
}
bi.StreamSource = stream;
bi.EndInit();
bi.Freeze();

if (orien < 2) return bi;
//apply orientation based on metadata
var tb = new TransformedBitmap();
tb.BeginInit();
tb.Source = bi;
switch (orien) {
case 2:
tb.Transform = new ScaleTransform(-1d, 1d);
break;
case 3:
tb.Transform = new RotateTransform(180d);
break;
case 4:
tb.Transform = new ScaleTransform(1d, -1d);
break;
case 5: {
var tg = new TransformGroup();
tg.Children.Add(new RotateTransform(90d));
tg.Children.Add(new ScaleTransform(-1d, 1d));
tb.Transform = tg;
break;
}
case 6:
tb.Transform = new RotateTransform(90d);
break;
case 7: {
var tg = new TransformGroup();
tg.Children.Add(new RotateTransform(90d));
tg.Children.Add(new ScaleTransform(1d, -1d));
tb.Transform = tg;
break;
}
case 8:
tb.Transform = new RotateTransform(270d);
break;
}
tb.EndInit();
tb.Freeze();
return tb;
}
catch {
return null;
}
}

internal static Image GetImageElement(this TextPointer pointer)
{
var ele = pointer?.GetAdjacentElement(LogicalDirection.Forward);
switch (ele) {
case BlockUIContainer ele1:
return ele1.Child as Image;
case InlineUIContainer ele2:
return ele2.Child as Image;
case Image ele3:
return ele3;
default: return null;
}
}

/// <summary>
/// Get visual or logical parent of an element depending on the type of <paramref name="self"/>.
/// </summary>
/// <param name="includeSelf">Also check the type of the initial object passed in.</param>
/// <returns>The parent element or null.</returns>
internal static T GetParent<T>(DependencyObject self, bool includeSelf = false)
{
switch (self) {
case T s when includeSelf:
return s;
case FrameworkElement s:
self = s.Parent;
break;
case FrameworkContentElement s:
self = s.Parent;
break;
case Visual s:
self = VisualTreeHelper.GetParent(s);
break;
default:
return default;
}
if (self == null) return default;
if (self is T t) return t;
return GetParent<T>(self, false);
}
}

public static class StreamReaderExtensions
Expand Down
3 changes: 2 additions & 1 deletion MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
</Rectangle>
<RichTextBox x:Name="RTB_Main" Margin="20" Background="{x:Null}" BorderBrush="{x:Null}" AcceptsTab="True" BorderThickness="0" IsInactiveSelectionHighlightEnabled="True"
TextChanged="RTB_Main_TextChanged" PreviewKeyDown="RTB_Main_PreviewKeyDown" PreviewMouseWheel="RTB_Main_PreviewMouseWheel"
GotKeyboardFocus="RTB_Main_GotKeyboardFocus"
GotKeyboardFocus="RTB_Main_GotKeyboardFocus" AllowDrop="True"
PreviewDragEnter="RTB_Main_PreviewDrag" PreviewDragOver="RTB_Main_PreviewDrag" PreviewDrop="RTB_Main_PreviewDrop"
ContextMenuOpening="RTB_Main_ContextMenuOpening" PreviewMouseDown="RTB_Main_PreviewMouseDown">
<!--<wtk:RichTextBoxFormatBarManager.FormatBar>
<wtk:RichTextBoxFormatBar/>
Expand Down
29 changes: 29 additions & 0 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -12,6 +13,7 @@
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace DesktopNote
Expand Down Expand Up @@ -355,6 +357,33 @@ private void RTB_Main_PreviewMouseDown(object sender, MouseButtonEventArgs e)
App.FormatWindow.FadeOut();
}
}

private void RTB_Main_PreviewDrag(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Copy;
e.Handled = true;
}

private void RTB_Main_PreviewDrop(object sender, DragEventArgs e)
{
var paths = (string[])e.Data.GetData(DataFormats.FileDrop);
if (paths == null || paths.Length == 0) return;

foreach (var path in paths) {
BitmapSource bs;
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read)) {
bs = Helpers.GetImageSource(fs);
}
if (bs == null) continue;

var ele = RTB_Main.CaretPosition.GetAdjacentElement(LogicalDirection.Forward);
Helpers.GetParent<Paragraph>(ele, true)?.Inlines.Add(new Image() {
Source = bs,
VerticalAlignment = VerticalAlignment.Bottom,
HorizontalAlignment = HorizontalAlignment.Left,
});
}
}
#endregion

#region Rect Events
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.2.0")]
[assembly: AssemblyFileVersion("1.5.2.0")]
[assembly: AssemblyVersion("1.6.0.0")]
[assembly: AssemblyFileVersion("1.6.0.0")]
1 change: 1 addition & 0 deletions RoundedWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ public void FadeIn(double left = double.NaN, double top = double.NaN)
if (left.Equals(double.NaN) || top.Equals(double.NaN))//nan==nan returns false.
{
//get the physical pixel-based position.
//this doesn't work when mouse is outside of mainwindow(?)
newpos = PointToScreen(Mouse.GetPosition(this));
//convert to the actual position considering the DPI settings etc.
realpos = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice.Transform(newpos);
Expand Down
48 changes: 14 additions & 34 deletions Win_Format.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,23 +148,14 @@ internal void IncreaseSize(object sender, RoutedEventArgs e)
if (RTB_Main.Selection.IsEmpty)
RTB_Main.FontSize += 1;
else {
var ele = RTB_Main.Selection.Start.GetNextContextPosition(LogicalDirection.Forward)?.GetAdjacentElement(LogicalDirection.Forward);
if (ele == null) return;
Image img = null;
switch (ele.GetType().Name) {
case "BlockUIContainer":
img = ((BlockUIContainer)ele).Child as Image;
break;
case "InlineUIContainer":
img = ((InlineUIContainer)ele).Child as Image;
break;
case "Image":
img = (Image)ele;
break;
}
var img = RTB_Main.Selection.Start.GetNextContextPosition(LogicalDirection.Forward)?.GetImageElement();
if (img != null) {
img.Width += 2;
img.Height += 2;
var startW = double.IsNaN(img.Width) ? img.ActualWidth : img.Width;
var startH = double.IsNaN(img.Height) ? img.ActualHeight : img.Height;
img.VerticalAlignment = VerticalAlignment.Bottom;
img.HorizontalAlignment = HorizontalAlignment.Left;
img.Width = startW * 1.1;
img.Height = startH * 1.1;
}
else
EditingCommands.IncreaseFontSize.Execute(null, RTB_Main);
Expand All @@ -177,25 +168,14 @@ internal void DecreaseSize(object sender, RoutedEventArgs e)
if (RTB_Main.FontSize > 1) RTB_Main.FontSize -= 1;
}
else {
var ele = RTB_Main.Selection.Start.GetNextContextPosition(LogicalDirection.Forward)?.GetAdjacentElement(LogicalDirection.Forward);
if (ele == null) return;
Image img = null;
switch (ele.GetType().Name) {
case "BlockUIContainer":
img = ((BlockUIContainer)ele).Child as Image;
break;
case "InlineUIContainer":
img = ((InlineUIContainer)ele).Child as Image;
break;
case "Image":
img = (Image)ele;
break;
}
var img = RTB_Main.Selection.Start.GetNextContextPosition(LogicalDirection.Forward)?.GetImageElement();
if (img != null) {
if (img.Width > 2 && img.Height > 2) {
img.Width -= 2;
img.Height -= 2;
}
var startW = double.IsNaN(img.Width) ? img.ActualWidth : img.Width;
var startH = double.IsNaN(img.Height) ? img.ActualHeight : img.Height;
img.VerticalAlignment = VerticalAlignment.Bottom;
img.HorizontalAlignment = HorizontalAlignment.Left;
img.Width = startW * 0.9;
img.Height = startH * 0.9;
}
else
EditingCommands.DecreaseFontSize.Execute(null, RTB_Main);
Expand Down

0 comments on commit ce7e631

Please sign in to comment.