Skip to content

Commit

Permalink
Auto position FindReplaceDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandreu committed Jul 7, 2019
1 parent 6a65b89 commit 095a5fe
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 9 deletions.
2 changes: 1 addition & 1 deletion OfficeRibbonXEditor/Controls/ClickSelectTextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private static void SelectivelyIgnoreMouseButton(object sender,
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focussed, give it the focus and
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
Expand Down
3 changes: 3 additions & 0 deletions OfficeRibbonXEditor/Controls/DialogControl.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using OfficeRibbonXEditor.Views;

namespace OfficeRibbonXEditor.Controls
{
Expand Down Expand Up @@ -85,5 +86,7 @@ public double InactiveOpacity
get => (double) this.GetValue(InactiveOpacityProperty);
set => this.SetValue(InactiveOpacityProperty, value);
}

public DialogHostBase Host { get; set; }
}
}
25 changes: 22 additions & 3 deletions OfficeRibbonXEditor/Controls/EditableComboBox.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Windows;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
Expand All @@ -7,12 +8,30 @@ namespace OfficeRibbonXEditor.Controls
{
public class EditableComboBox : ComboBox
{
public EditableComboBox()
{
this.IsEditable = true;
}

private TextBox textBox;

public TextBox TextBox
{
get
{
if (this.textBox != null)
{
return this.textBox;
}

this.ApplyTemplate();
return this.Template.FindName("PART_EditableTextBox", this) as TextBox;
this.textBox = this.Template.FindName("PART_EditableTextBox", this) as TextBox;
if (this.textBox == null)
{
throw new InvalidOperationException($"Make sure IsEditable is set to true when using an {nameof(EditableComboBox)}");
}

return this.textBox;
}
}

Expand Down Expand Up @@ -41,7 +60,7 @@ private static void SelectivelyIgnoreMouseButton(object sender,
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focussed, give it the focus and
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
Expand Down
25 changes: 23 additions & 2 deletions OfficeRibbonXEditor/ViewModels/FindReplaceDialogViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Drawing;
using System.Text.RegularExpressions;
using GalaSoft.MvvmLight.Command;
using OfficeRibbonXEditor.Controls.Forms;
using OfficeRibbonXEditor.Interfaces;
using OfficeRibbonXEditor.Models;
using ScintillaNET;
using CharacterRange = OfficeRibbonXEditor.Models.CharacterRange;

namespace OfficeRibbonXEditor.ViewModels
{
Expand All @@ -22,6 +24,8 @@ public FindReplaceDialogViewModel()
this.ClearCommand = new RelayCommand(this.ExecuteClearCommand);
}

public event EventHandler<DataEventArgs<Point>> MoveDialogAway;

public RecentListViewModel<string> RecentFinds { get; } = new RecentListViewModel<string>();

public RecentListViewModel<string> RecentReplaces { get; } = new RecentListViewModel<string>();
Expand Down Expand Up @@ -72,6 +76,14 @@ public Scintilla Scintilla

public RelayCommand ClearCommand { get; }

private bool autoPosition = true;

public bool AutoPosition
{
get => this.autoPosition;
set => this.Set(ref this.autoPosition, value);
}

private bool isFindTabSelected = true;

public bool IsFindTabSelected
Expand Down Expand Up @@ -636,8 +648,17 @@ public bool OnLoaded((Scintilla, FindReplaceAction) payload)

public virtual void MoveDialogAwayFromSelection()
{
// TODO: This might be tricky to implement in MVVM
// Most sensible solution would be moving the code to the view, and invoke it via an event
if (!this.AutoPosition)
{
return;
}

var pos = this.Scintilla.CurrentPosition;
var x = this.Scintilla.PointXFromPosition(pos);
var y = this.Scintilla.PointYFromPosition(pos);

var cursorPoint = this.Scintilla.PointToScreen(new Point(x, y));
this.MoveDialogAway?.Invoke(this, new DataEventArgs<Point> { Data = cursorPoint });
}
}
}
1 change: 1 addition & 0 deletions OfficeRibbonXEditor/Views/DialogHostBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ private static void OnModelChanged(DependencyObject sender, DependencyPropertyCh
var view = GenerateControl(e.NewValue.GetType());
view.DataContext = e.NewValue;
host.View = view;
view.Host = host;
host.Content = view;
host.SizeToContent = SizeToContent.Manual;
// TODO: This does not work as expected in WPF (as opposed to Windows Forms), so disabled for now
Expand Down
56 changes: 53 additions & 3 deletions OfficeRibbonXEditor/Views/FindReplaceDialog.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System;
using System.Windows;
using Autofac;
using OfficeRibbonXEditor.Controls;
using OfficeRibbonXEditor.Models;
using OfficeRibbonXEditor.ViewModels;
Expand All @@ -26,6 +26,8 @@ protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
return;
}

vm.MoveDialogAway += this.OnMoveDialogAway;

EditableComboBox target;
if (vm.IsFindTabSelected)
{
Expand All @@ -39,5 +41,53 @@ protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
target.TextBox?.Focus();
target.TextBox?.SelectAll();
}

private void OnMoveDialogAway(object sender, DataEventArgs<System.Drawing.Point> e)
{
const int triggerMargin = 64;

// First, we check if the current position is hiding the selection or not
var current = new System.Drawing.Rectangle(
(int) this.Host.Left - triggerMargin,
(int) this.Host.Top - triggerMargin,
(int) this.Host.Width + 2 * triggerMargin,
(int) this.Host.Height + 2 * triggerMargin);

if (!current.Contains(e.Data))
{
return;
}

// We simply try to put the dialog in one of the four corners of the main window, until we find one
// which does not hide the selection

const int margin = 32;
var owner = this.Host.Owner;

for (var i = 0; i < 2; ++i)
{
for (var j = 0; j < 2; ++j)
{
var left = j == 0 ? owner.Left + margin : owner.Left + owner.Width - this.Host.Width - margin;
var top = i == 0 ? owner.Top + margin : owner.Top + owner.Height - this.Host.Height - margin;

var r = new System.Drawing.Rectangle(
(int) left,
(int) top,
(int) this.Host.Width,
(int) this.Host.Height);

if (r.Contains(e.Data))
{
continue;
}

this.Host.Left = left;
this.Host.Top = top;

return;
}
}
}
}
}

0 comments on commit 095a5fe

Please sign in to comment.