|
|
|
@ -16,6 +16,8 @@ |
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
|
|
|
using System.ComponentModel; |
|
|
|
using System.Composition; |
|
|
|
using System.Composition; |
|
|
|
using System.Linq; |
|
|
|
using System.Linq; |
|
|
|
using System.Windows; |
|
|
|
using System.Windows; |
|
|
|
@ -23,9 +25,11 @@ using System.Windows.Controls; |
|
|
|
using System.Windows.Controls.Primitives; |
|
|
|
using System.Windows.Controls.Primitives; |
|
|
|
using System.Windows.Data; |
|
|
|
using System.Windows.Data; |
|
|
|
using System.Windows.Input; |
|
|
|
using System.Windows.Input; |
|
|
|
|
|
|
|
using System.Windows.Media; |
|
|
|
using System.Windows.Threading; |
|
|
|
using System.Windows.Threading; |
|
|
|
|
|
|
|
|
|
|
|
using ICSharpCode.ILSpy.Themes; |
|
|
|
using ICSharpCode.ILSpy.Themes; |
|
|
|
|
|
|
|
using ICSharpCode.ILSpyX.TreeView; |
|
|
|
|
|
|
|
|
|
|
|
using TomsToolbox.Composition; |
|
|
|
using TomsToolbox.Composition; |
|
|
|
|
|
|
|
|
|
|
|
@ -85,7 +89,8 @@ namespace ICSharpCode.ILSpy.Controls |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static Button CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> commandExport) |
|
|
|
|
|
|
|
|
|
|
|
static UIElement CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> commandExport) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var command = commandExport.Value; |
|
|
|
var command = commandExport.Value; |
|
|
|
|
|
|
|
|
|
|
|
@ -108,9 +113,106 @@ namespace ICSharpCode.ILSpy.Controls |
|
|
|
parameterBinding.ParameterBinding); |
|
|
|
parameterBinding.ParameterBinding); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (command is IProvideParameterList parameterList) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
toolbarItem.Margin = new Thickness(2, 0, 0, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dropDownPanel = new StackPanel { Orientation = Orientation.Horizontal }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dropDownToggle = new ToggleButton { |
|
|
|
|
|
|
|
Style = ThemeManager.Current.CreateToolBarToggleButtonStyle(), |
|
|
|
|
|
|
|
Content = "▾", |
|
|
|
|
|
|
|
Padding = new Thickness(0), |
|
|
|
|
|
|
|
MinWidth = 0, |
|
|
|
|
|
|
|
Margin = new Thickness(0, 0, 2, 0) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var contextMenu = new ContextMenu { |
|
|
|
|
|
|
|
PlacementTarget = dropDownPanel, |
|
|
|
|
|
|
|
Tag = command |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ContextMenuService.SetPlacement(toolbarItem, PlacementMode.Bottom); |
|
|
|
|
|
|
|
toolbarItem.ContextMenu = contextMenu; |
|
|
|
|
|
|
|
toolbarItem.ContextMenuOpening += (_, _) => |
|
|
|
|
|
|
|
PrepareParameterList(contextMenu); |
|
|
|
|
|
|
|
dropDownToggle.Checked += (_, _) => { |
|
|
|
|
|
|
|
PrepareParameterList(contextMenu); |
|
|
|
|
|
|
|
contextMenu.Placement = PlacementMode.Bottom; |
|
|
|
|
|
|
|
contextMenu.SetCurrentValue(ContextMenu.IsOpenProperty, true); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BindingOperations.SetBinding(dropDownToggle, ToggleButton.IsCheckedProperty, |
|
|
|
|
|
|
|
new Binding(nameof(contextMenu.IsOpen)) { Source = contextMenu }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BindingOperations.SetBinding(dropDownToggle, IsEnabledProperty, |
|
|
|
|
|
|
|
new Binding(nameof(IsEnabled)) { Source = toolbarItem }); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// When the toggle button is checked, clicking it to uncheck will dismiss the menu first
|
|
|
|
|
|
|
|
// which unchecks the toggle button via binding above and the click is used to open it again.
|
|
|
|
|
|
|
|
// This is a workaround to ignore the click to uncheck the already unchecked toggle button.
|
|
|
|
|
|
|
|
// We have to ensure the dismissing click is on the toggle button, otherwise the flag
|
|
|
|
|
|
|
|
// will not get cleared and menu will not open next time.
|
|
|
|
|
|
|
|
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(contextMenu, (_, e) => { |
|
|
|
|
|
|
|
var point = e.GetPosition(dropDownToggle); |
|
|
|
|
|
|
|
dropDownToggle.Tag = dropDownToggle.InputHitTest(point); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
dropDownToggle.PreviewMouseLeftButtonDown += (_, e) => { |
|
|
|
|
|
|
|
e.Handled = dropDownToggle.Tag != null; |
|
|
|
|
|
|
|
dropDownToggle.Tag = null; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dropDownPanel.Children.Add(toolbarItem); |
|
|
|
|
|
|
|
dropDownPanel.Children.Add(dropDownToggle); |
|
|
|
|
|
|
|
return dropDownPanel; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return toolbarItem; |
|
|
|
return toolbarItem; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void PrepareParameterList(ContextMenu menu) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const int maximumParameterListCount = 20; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var command = (ICommand)menu.Tag; |
|
|
|
|
|
|
|
var parameterList = (IProvideParameterList)command; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
menu.Items.Clear(); |
|
|
|
|
|
|
|
foreach (var parameter in parameterList.ParameterList) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MenuItem parameterItem = new MenuItem(); |
|
|
|
|
|
|
|
parameterItem.Command = CommandWrapper.Unwrap(command); |
|
|
|
|
|
|
|
parameterItem.CommandParameter = parameter; |
|
|
|
|
|
|
|
parameterItem.CommandTarget = menu.PlacementTarget; |
|
|
|
|
|
|
|
parameterItem.InputGestureText = " "; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var headerPresenter = new ContentPresenter { RecognizesAccessKey = false }; |
|
|
|
|
|
|
|
parameterItem.Header = headerPresenter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var header = parameterList.GetParameterText(parameter); |
|
|
|
|
|
|
|
switch (header) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case SharpTreeNode node: |
|
|
|
|
|
|
|
headerPresenter.Content = node.NavigationText; |
|
|
|
|
|
|
|
if (node.Icon is ImageSource icon) |
|
|
|
|
|
|
|
parameterItem.Icon = new Image { |
|
|
|
|
|
|
|
Width = 16, |
|
|
|
|
|
|
|
Height = 16, |
|
|
|
|
|
|
|
Source = icon |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
headerPresenter.Content = header; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(parameterItem); |
|
|
|
|
|
|
|
if (menu.Items.Count >= maximumParameterListCount) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void MainWindow_KeyDown(object sender, KeyEventArgs e) |
|
|
|
void MainWindow_KeyDown(object sender, KeyEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (e.Handled || e.KeyboardDevice.Modifiers != ModifierKeys.Alt || e.Key != Key.System) |
|
|
|
if (e.Handled || e.KeyboardDevice.Modifiers != ModifierKeys.Alt || e.Key != Key.System) |
|
|
|
|