Browse Source

Update enabled status of menu and toolbar items.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0wpf@3384 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
245747804d
  1. 2
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonDockLayout.cs
  2. 6
      src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
  3. 47
      src/Main/ICSharpCode.Core.Presentation/CommandService.cs
  4. 2
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  5. 28
      src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
  6. 98
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs
  7. 166
      src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs
  8. 2
      src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs
  9. 54
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs

2
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonDockLayout.cs

@ -10,6 +10,7 @@ using System.Collections.Generic; @@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using AvalonDock;
@ -44,6 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -44,6 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui
void dockingManager_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "ActiveContent") {
CommandManager.InvalidateRequerySuggested();
if (ActiveContentChanged != null)
ActiveContentChanged(this, e);
}

6
src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs

@ -6,12 +6,13 @@ @@ -6,12 +6,13 @@
// </file>
using System;
using System.Linq;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using System.Windows.Input;
namespace ICSharpCode.SharpDevelop.Project
{
@ -37,6 +38,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -37,6 +38,7 @@ namespace ICSharpCode.SharpDevelop.Project
LoggingService.Info("CurrentProject changed to " + (value == null ? "null" : value.Name));
currentProject = value;
OnCurrentProjectChanged(new ProjectEventArgs(currentProject));
CommandManager.InvalidateRequerySuggested();
}
}
}
@ -249,6 +251,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -249,6 +251,7 @@ namespace ICSharpCode.SharpDevelop.Project
OnSolutionLoading(fileName);
try {
openSolution = Solution.Load(fileName);
CommandManager.InvalidateRequerySuggested();
if (openSolution == null)
return;
} catch (UnauthorizedAccessException ex) {
@ -477,6 +480,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -477,6 +480,7 @@ namespace ICSharpCode.SharpDevelop.Project
openSolution = null;
OnSolutionClosed(EventArgs.Empty);
CommandManager.InvalidateRequerySuggested();
}
}

47
src/Main/ICSharpCode.Core.Presentation/CommandService.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Provides access to the RoutedUICommand objects for commands defined in the addin-tree.
/// </summary>
public static class CommandService
{
static Dictionary<string, RoutedUICommand> dict = new Dictionary<string, RoutedUICommand>();
public static RoutedUICommand GetCommand(string className)
{
if (className == null)
throw new ArgumentNullException("className");
if (className.Length == 0)
throw new ArgumentException("className must not be the empty string");
lock (dict) {
RoutedUICommand cmd;
if (!dict.TryGetValue(className, out cmd)) {
dict[className] = cmd = new RoutedUICommand(className, className, typeof(CommandService));
}
return cmd;
}
}
public static RoutedUICommand GetCommand(Type commandClass)
{
if (commandClass == null)
throw new ArgumentNullException("commandClass");
if (!typeof(ICommand).IsAssignableFrom(commandClass))
throw new ArgumentException("commandClass must implement ICommand", "commandClass");
return GetCommand(commandClass.FullName);
}
}
}

2
src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj

@ -59,6 +59,7 @@ @@ -59,6 +59,7 @@
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CommandService.cs" />
<Compile Include="ConditionalSeparator.cs" />
<Compile Include="GetBitmapExtension.cs" />
<Compile Include="IStatusUpdate.cs" />
@ -67,6 +68,7 @@ @@ -67,6 +68,7 @@
<Compile Include="Menu\MenuCommand.cs" />
<Compile Include="Menu\MenuService.cs" />
<Compile Include="Menu\CoreMenuItem.cs" />
<Compile Include="PixelSnapper.cs" />
<Compile Include="PresentationResourceService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ToolBar\ToolBarButton.cs" />

28
src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs

@ -26,12 +26,13 @@ namespace ICSharpCode.Core.Presentation @@ -26,12 +26,13 @@ namespace ICSharpCode.Core.Presentation
this.codon = codon;
this.caller = caller;
if (codon.Properties.Contains("shortcut")) {
InputGestureText = codon.Properties["shortcut"];
}
if (codon.Properties.Contains("icon")) {
try {
this.Icon = PresentationResourceService.GetImage(codon.Properties["icon"]);
Image image = PresentationResourceService.GetImage(codon.Properties["icon"]);
image.Height = 16;
this.Icon = new PixelSnapper {
Child = image
};
} catch (ResourceNotFoundException) {}
}
this.SubmenuOpened += CoreMenuItem_SubmenuOpened;
@ -52,23 +53,10 @@ namespace ICSharpCode.Core.Presentation @@ -52,23 +53,10 @@ namespace ICSharpCode.Core.Presentation
public virtual void UpdateStatus()
{
this.IsEnabled = this.IsEnabledCore;
if (this.IsEnabled) {
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
} else {
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
protected override bool IsEnabledCore {
get {
ConditionFailedAction failedAction = codon.GetFailedAction(caller);
bool isEnabled = failedAction == ConditionFailedAction.Nothing;
return isEnabled;
}
}
}
}

98
src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs

@ -7,39 +7,36 @@ @@ -7,39 +7,36 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
class MenuCommand : CoreMenuItem
class CommandWrapper : System.Windows.Input.ICommand
{
ICommand menuCommand;
bool commandCreated;
ICommand addInCommand;
readonly Codon codon;
readonly object caller;
public MenuCommand(Codon codon, object caller, bool createCommand) : base(codon, caller)
public CommandWrapper(Codon codon, object caller, bool createCommand)
{
this.codon = codon;
this.caller = caller;
if (createCommand) {
commandCreated = true;
CreateCommand();
}
}
protected override bool IsEnabledCore {
get {
if (!base.IsEnabledCore)
return false;
if (menuCommand != null && menuCommand is IMenuCommand) {
return ((IMenuCommand)menuCommand).IsEnabled;
} else {
return true;
}
}
}
void CreateCommand()
{
commandCreated = true;
try {
string link = codon.Properties["link"];
ICommand menuCommand;
if (link != null && link.Length > 0) {
if (MenuService.LinkCommandCreator == null)
throw new NotSupportedException("MenuCommand.LinkCommandCreator is not set, cannot create LinkCommands.");
@ -50,20 +47,79 @@ namespace ICSharpCode.Core.Presentation @@ -50,20 +47,79 @@ namespace ICSharpCode.Core.Presentation
if (menuCommand != null) {
menuCommand.Owner = caller;
}
addInCommand = menuCommand;
} catch (Exception e) {
MessageService.ShowError(e, "Can't create menu command : " + codon.Id);
}
}
protected override void OnClick()
void CommandManager_RequerySuggested(object sender, EventArgs e)
{
//LoggingService.Debug("Received CommandManager_RequerySuggested ");
if (canExecuteChanged != null)
canExecuteChanged(this, e);
}
// keep a reference to the event handler to prevent it from being gargabe collected
// (CommandManager.RequerySuggested only keeps weak references to the event handlers)
EventHandler requerySuggestedEventHandler;
// only attach to CommandManager.RequerySuggested if someone listens to the CanExecuteChanged event
EventHandler canExecuteChanged;
public event EventHandler CanExecuteChanged {
add {
if (canExecuteChanged == null && value != null) {
//LoggingService.Debug("Attach CommandManager_RequerySuggested " + codon.Id);
if (requerySuggestedEventHandler == null)
requerySuggestedEventHandler = CommandManager_RequerySuggested;
CommandManager.RequerySuggested += requerySuggestedEventHandler;
}
canExecuteChanged += value;
}
remove {
canExecuteChanged -= value;
if (canExecuteChanged == null) {
//LoggingService.Debug("Detach CommandManager_RequerySuggested " + codon.Id);
CommandManager.RequerySuggested -= requerySuggestedEventHandler;
}
}
}
public void Execute(object parameter)
{
base.OnClick();
if (menuCommand == null) {
if (!commandCreated) {
CreateCommand();
}
if (menuCommand != null && IsEnabledCore) {
menuCommand.Run();
LoggingService.Debug("Execute " + codon.Id);
if (CanExecute(parameter)) {
addInCommand.Run();
}
}
public bool CanExecute(object parameter)
{
//LoggingService.Debug("CanExecute " + codon.Id);
if (codon.GetFailedAction(caller) != ConditionFailedAction.Nothing)
return false;
if (!commandCreated)
return true;
if (addInCommand == null)
return false;
IMenuCommand menuCommand = addInCommand as IMenuCommand;
if (menuCommand != null) {
return menuCommand.IsEnabled;
} else {
return true;
}
}
}
class MenuCommand : CoreMenuItem
{
public MenuCommand(Codon codon, object caller, bool createCommand) : base(codon, caller)
{
this.Command = new CommandWrapper(codon, caller, createCommand);
}
}
}

166
src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs

@ -0,0 +1,166 @@ @@ -0,0 +1,166 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A WPF control that aligns its content on pixel boundaries.
/// </summary>
public class PixelSnapper : UIElement
{
public PixelSnapper()
{
LayoutUpdated += new EventHandler(OnLayoutUpdated);
}
UIElement _visualChild;
/// <summary>
/// Gets/sets the visual child.
/// </summary>
public UIElement Child {
get { return _visualChild; }
set {
RemoveVisualChild(_visualChild);
_visualChild = value;
AddVisualChild(_visualChild);
InvalidateMeasure();
}
}
/// <summary>
/// Gets the visual child.
/// </summary>
protected override Visual GetVisualChild(int index)
{
if (index == 0 && _visualChild != null)
return _visualChild;
else
throw new ArgumentOutOfRangeException("index");
}
/// <summary>
/// Gets the number of visual children.
/// </summary>
protected override int VisualChildrenCount {
get { return _visualChild != null ? 1 : 0; }
}
/// <summary>
/// Measure the visual child.
/// </summary>
protected override Size MeasureCore(Size availableSize)
{
if (_visualChild != null) {
_visualChild.Measure(availableSize);
return _visualChild.DesiredSize;
} else {
return base.MeasureCore(availableSize);
}
}
protected override void ArrangeCore(Rect finalRect)
{
base.ArrangeCore(finalRect);
if (_visualChild != null) {
_pixelOffset = GetPixelOffset();
//LoggingService.Debug("Arrange, Pixel Offset=" + _pixelOffset);
_visualChild.Arrange(new Rect(new Point(_pixelOffset.X, _pixelOffset.Y), finalRect.Size));
}
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
// This event just means that layout happened somewhere. However, this is
// what we need since layout anywhere could affect our pixel positioning.
Point pixelOffset = GetPixelOffset();
if (!AreClose(pixelOffset, _pixelOffset)) {
InvalidateArrange();
}
}
// Gets the matrix that will convert a point from "above" the
// coordinate space of a visual into the the coordinate space
// "below" the visual.
private Matrix GetVisualTransform(Visual v)
{
if (v != null) {
Matrix m = Matrix.Identity;
Transform transform = VisualTreeHelper.GetTransform(v);
if (transform != null) {
m *= transform.Value;
}
Vector offset = VisualTreeHelper.GetOffset(v);
m.Translate(offset.X, offset.Y);
return m;
}
return Matrix.Identity;
}
private Point ApplyVisualTransform(Point point, Visual v, bool inverse)
{
if (v != null) {
Matrix visualTransform = GetVisualTransform(v);
if (inverse)
visualTransform.Invert();
point = visualTransform.Transform(point);
}
return point;
}
private Point GetPixelOffset()
{
Point pixelOffset = new Point();
PresentationSource ps = PresentationSource.FromVisual(this);
if (ps != null) {
Visual rootVisual = ps.RootVisual;
// Transform (0,0) from this element up to pixels.
pixelOffset = this.TransformToAncestor(rootVisual).Transform(pixelOffset);
pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, false);
pixelOffset = ps.CompositionTarget.TransformToDevice.Transform(pixelOffset);
// Round the origin to the nearest whole pixel.
pixelOffset.X = Math.Round(pixelOffset.X);
pixelOffset.Y = Math.Round(pixelOffset.Y);
// Transform the whole-pixel back to this element.
pixelOffset = ps.CompositionTarget.TransformFromDevice.Transform(pixelOffset);
pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, true);
pixelOffset = rootVisual.TransformToDescendant(this).Transform(pixelOffset);
}
return pixelOffset;
}
private bool AreClose(Point point1, Point point2)
{
return AreClose(point1.X, point2.X) && AreClose(point1.Y, point2.Y);
}
private bool AreClose(double value1, double value2)
{
if (value1 == value2)
{
return true;
}
double delta = value1 - value2;
return ((delta < 1.53E-06) && (delta > -1.53E-06));
}
private Point _pixelOffset;
}
}

2
src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs

@ -54,7 +54,7 @@ namespace ICSharpCode.Core.Presentation @@ -54,7 +54,7 @@ namespace ICSharpCode.Core.Presentation
BitmapSource bs;
if (bitmapCache.TryGetValue(name, out bs))
return bs;
Bitmap bmp = (Bitmap)ResourceService.GetImageResource(name);
System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)ResourceService.GetImageResource(name);
if (bmp == null) {
throw new ResourceNotFoundException(name);
}

54
src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs

@ -8,17 +8,17 @@ @@ -8,17 +8,17 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
///
/// A tool bar button based on the AddIn-tree.
/// </summary>
sealed class ToolBarButton : Button, IStatusUpdate
{
readonly Codon codon;
readonly object caller;
ICommand menuCommand;
public ToolBarButton(Codon codon, object caller, bool createCommand)
{
@ -26,41 +26,21 @@ namespace ICSharpCode.Core.Presentation @@ -26,41 +26,21 @@ namespace ICSharpCode.Core.Presentation
this.codon = codon;
this.caller = caller;
if (createCommand) {
CreateCommand();
}
this.Command = new CommandWrapper(codon, caller, createCommand);
if (codon.Properties.Contains("icon")) {
Image image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
image.Height = 16;
image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
this.Content = image;
this.Content = new PixelSnapper {
Child = image
};
}
UpdateText();
SetResourceReference(FrameworkElement.StyleProperty, ToolBar.ButtonStyleKey);
}
protected override void OnClick()
{
base.OnClick();
if (menuCommand == null) {
CreateCommand();
}
if (menuCommand != null) {
menuCommand.Run();
}
}
void CreateCommand()
{
menuCommand = (ICommand)codon.AddIn.CreateObject(codon.Properties["class"]);
if (menuCommand != null) {
menuCommand.Owner = caller;
}
}
public void UpdateText()
{
if (codon.Properties.Contains("label")){
@ -73,26 +53,10 @@ namespace ICSharpCode.Core.Presentation @@ -73,26 +53,10 @@ namespace ICSharpCode.Core.Presentation
public void UpdateStatus()
{
this.IsEnabled = this.IsEnabledCore;
if (this.IsEnabled) {
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
} else {
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
protected override bool IsEnabledCore {
get {
ConditionFailedAction failedAction = codon.GetFailedAction(caller);
bool isEnabled = failedAction == ConditionFailedAction.Nothing;
if (isEnabled && menuCommand != null && menuCommand is IMenuCommand) {
isEnabled = ((IMenuCommand)menuCommand).IsEnabled;
}
return isEnabled;
}
}
}
}

Loading…
Cancel
Save