Browse Source

Backport ICSharpCode.Core.Presentation to SharpDevelop 3.1 - this makes it easier to write WPF-based AddIns.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3820 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
1533f2bbdd
  1. 44
      src/Main/ICSharpCode.Core.Presentation/ConditionalSeparator.cs
  2. 30
      src/Main/ICSharpCode.Core.Presentation/GetBitmapExtension.cs
  3. 94
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  4. 17
      src/Main/ICSharpCode.Core.Presentation/IStatusUpdate.cs
  5. 30
      src/Main/ICSharpCode.Core.Presentation/LocalizeExtension.cs
  6. 54
      src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
  7. 20
      src/Main/ICSharpCode.Core.Presentation/Menu/IMenuItemBuilder.cs
  8. 114
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs
  9. 157
      src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs
  10. 24
      src/Main/ICSharpCode.Core.Presentation/NativeMethods.cs
  11. 174
      src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs
  12. 102
      src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs
  13. 29
      src/Main/ICSharpCode.Core.Presentation/Properties/AssemblyInfo.cs
  14. 95
      src/Main/ICSharpCode.Core.Presentation/SplitButton.cs
  15. 60
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs
  16. 35
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarComboBox.cs
  17. 115
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs
  18. 65
      src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs
  19. 81
      src/Main/ICSharpCode.Core.Presentation/themes/Aero.NormalColor.xaml
  20. 81
      src/Main/ICSharpCode.Core.Presentation/themes/generic.xaml
  21. 3
      src/Setup/Files.wxs
  22. 1
      src/Setup/Setup.wxs
  23. 9
      src/SharpDevelop.sln

44
src/Main/ICSharpCode.Core.Presentation/ConditionalSeparator.cs

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
// <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.Windows;
using System.Windows.Controls;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A Separator that is invisible when it is excluded by a condition.
/// </summary>
sealed class ConditionalSeparator : Separator, IStatusUpdate
{
readonly Codon codon;
readonly object caller;
public ConditionalSeparator(Codon codon, object caller, bool inToolbar)
{
this.codon = codon;
this.caller = caller;
if (inToolbar) {
SetResourceReference(FrameworkElement.StyleProperty, ToolBar.SeparatorStyleKey);
}
}
public void UpdateText()
{
}
public void UpdateStatus()
{
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
}

30
src/Main/ICSharpCode.Core.Presentation/GetBitmapExtension.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// <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.Markup;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Markup extension that gets a BitmapSource object for a ResourceService bitmap.
/// </summary>
public class GetBitmapExtension : MarkupExtension
{
public GetBitmapExtension(string key)
{
this.key = key;
}
protected string key;
public override object ProvideValue(IServiceProvider serviceProvider)
{
return PresentationResourceService.GetBitmapSource(key);
}
}
}

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

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.Core.Presentation</RootNamespace>
<AssemblyName>ICSharpCode.Core.Presentation</AssemblyName>
<TargetFrameworkVersion>v3.0</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<SourceAnalysisOverrideSettingsFile>"C:\Program Files\SharpDevelop\3.0\bin\..\AddIns\AddIns\Misc\SourceAnalysis\Settings.SourceAnalysis"</SourceAnalysisOverrideSettingsFile>
<OutputPath>..\..\..\bin\</OutputPath>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<RunCodeAnalysis>False</RunCodeAnalysis>
<CodeAnalysisRules>-Microsoft.Performance#CA1810</CodeAnalysisRules>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ConditionalSeparator.cs" />
<Compile Include="GetBitmapExtension.cs" />
<Compile Include="IStatusUpdate.cs" />
<Compile Include="LocalizeExtension.cs" />
<Compile Include="Menu\IMenuItemBuilder.cs" />
<Compile Include="Menu\MenuCommand.cs" />
<Compile Include="Menu\MenuService.cs" />
<Compile Include="Menu\CoreMenuItem.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="PixelSnapper.cs" />
<Compile Include="PresentationResourceService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SplitButton.cs" />
<Compile Include="ToolBar\ToolBarButton.cs" />
<Compile Include="ToolBar\ToolBarComboBox.cs" />
<Compile Include="ToolBar\ToolBarService.cs" />
<Compile Include="ToolBar\ToolBarSplitButton.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Project\ICSharpCode.Core.csproj">
<Project>{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}</Project>
<Name>ICSharpCode.Core</Name>
<Private>False</Private>
</ProjectReference>
<Folder Include="Menu" />
<Folder Include="themes" />
<Folder Include="ToolBar" />
<Page Include="themes\Aero.NormalColor.xaml" />
<Page Include="themes\generic.xaml" />
</ItemGroup>
</Project>

17
src/Main/ICSharpCode.Core.Presentation/IStatusUpdate.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.Core.Presentation
{
public interface IStatusUpdate
{
void UpdateText();
void UpdateStatus();
}
}

30
src/Main/ICSharpCode.Core.Presentation/LocalizeExtension.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// <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.Markup;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Markup extension that retrieves localized resource strings.
/// </summary>
public class LocalizeExtension : MarkupExtension
{
public LocalizeExtension(string key)
{
this.key = key;
}
protected string key;
public override object ProvideValue(IServiceProvider serviceProvider)
{
return ResourceService.GetString(key);
}
}
}

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

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// <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;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A menu item representing an AddIn-Tree element.
/// </summary>
class CoreMenuItem : MenuItem, IStatusUpdate
{
protected readonly Codon codon;
protected readonly object caller;
public CoreMenuItem(Codon codon, object caller)
{
this.codon = codon;
this.caller = caller;
if (codon.Properties.Contains("icon")) {
try {
var image = PresentationResourceService.GetImage(codon.Properties["icon"]);
image.Height = 16;
this.Icon = new PixelSnapper(image);
} catch (ResourceNotFoundException) {}
}
UpdateText();
}
public void UpdateText()
{
if (codon != null) {
Header = MenuService.ConvertLabel(StringParser.Parse(codon.Properties["label"]));
}
}
public virtual void UpdateStatus()
{
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
}

20
src/Main/ICSharpCode.Core.Presentation/Menu/IMenuItemBuilder.cs

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
// <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;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Used to include a dynamically built list of menu items.
/// </summary>
public interface IMenuItemBuilder
{
ICollection BuildItems(Codon codon, object owner);
}
}

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

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// <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;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
class CommandWrapper : System.Windows.Input.ICommand
{
bool commandCreated;
ICommand addInCommand;
readonly Codon codon;
readonly object caller;
public CommandWrapper(Codon codon, object caller, bool createCommand)
{
this.codon = codon;
this.caller = caller;
if (createCommand) {
commandCreated = true;
CreateCommand();
}
}
public CommandWrapper(Codon codon, object caller, ICommand command)
{
this.codon = codon;
this.caller = caller;
this.addInCommand = command;
commandCreated = true;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="We're displaying the message to the user.")]
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.");
menuCommand = MenuService.LinkCommandCreator(codon.Properties["link"]);
} else {
menuCommand = (ICommand)codon.AddIn.CreateObject(codon.Properties["class"]);
}
if (menuCommand != null) {
menuCommand.Owner = caller;
}
addInCommand = menuCommand;
} catch (Exception e) {
MessageService.ShowError(e, "Can't create menu command : " + codon.Id);
}
}
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
if (!commandCreated) {
CreateCommand();
}
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(UIElement inputBindingOwner, Codon codon, object caller, bool createCommand) : base(codon, caller)
{
this.Command = new CommandWrapper(codon, caller, createCommand);
if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) {
KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]);
inputBindingOwner.InputBindings.Add(
new InputBinding(this.Command, kg)
);
this.InputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture);
}
}
}
}

157
src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs

@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
// <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;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Creates WPF menu controls from the AddIn Tree.
/// </summary>
public static class MenuService
{
public static void UpdateStatus(IEnumerable menuItems)
{
if (menuItems == null)
return;
foreach (object o in menuItems) {
IStatusUpdate cmi = o as IStatusUpdate;
if (cmi != null)
cmi.UpdateStatus();
}
}
public static ContextMenu CreateContextMenu(object owner, string addInTreePath)
{
ContextMenu menu = new ContextMenu();
menu.ItemsSource = CreateMenuItems(menu, owner, addInTreePath);
return menu;
}
internal static ContextMenu CreateContextMenu(IList subItems)
{
var contextMenu = new ContextMenu() {
ItemsSource = new object[1]
};
contextMenu.Opened += (sender, args) => {
contextMenu.ItemsSource = ExpandMenuBuilders(subItems);
args.Handled = true;
};
return contextMenu;
}
public static IList CreateMenuItems(UIElement inputBindingOwner, object owner, string addInTreePath)
{
return CreateMenuItems(inputBindingOwner, AddInTree.BuildItems<MenuItemDescriptor>(addInTreePath, owner, false));
}
sealed class MenuItemBuilderPlaceholder
{
readonly IMenuItemBuilder builder;
readonly Codon codon;
readonly object caller;
public MenuItemBuilderPlaceholder(IMenuItemBuilder builder, Codon codon, object caller)
{
this.builder = builder;
this.codon = codon;
this.caller = caller;
}
public ICollection BuildItems()
{
return builder.BuildItems(codon, caller);
}
}
internal static IList CreateMenuItems(UIElement inputBindingOwner, IEnumerable descriptors)
{
ArrayList result = new ArrayList();
foreach (MenuItemDescriptor descriptor in descriptors) {
result.Add(CreateMenuItemFromDescriptor(inputBindingOwner, descriptor));
}
return result;
}
internal static IList ExpandMenuBuilders(ICollection input)
{
ArrayList result = new ArrayList(input.Count);
foreach (object o in input) {
MenuItemBuilderPlaceholder p = o as MenuItemBuilderPlaceholder;
if (p != null) {
ICollection c = p.BuildItems();
if (c != null)
result.AddRange(c);
} else {
result.Add(o);
IStatusUpdate statusUpdate = o as IStatusUpdate;
if (statusUpdate != null) {
statusUpdate.UpdateStatus();
statusUpdate.UpdateText();
}
}
}
return result;
}
static object CreateMenuItemFromDescriptor(UIElement inputBindingOwner, MenuItemDescriptor descriptor)
{
Codon codon = descriptor.Codon;
string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Command";
bool createCommand = codon.Properties["loadclasslazy"] == "false";
switch (type) {
case "Separator":
return new ConditionalSeparator(codon, descriptor.Caller, false);
case "CheckBox":
return "CheckBox";
//return new MenuCheckBox(codon, descriptor.Caller);
case "Item":
case "Command":
return new MenuCommand(inputBindingOwner, codon, descriptor.Caller, createCommand);
case "Menu":
var item = new CoreMenuItem(codon, descriptor.Caller) {
ItemsSource = new object[1]
};
var subItems = CreateMenuItems(inputBindingOwner, descriptor.SubItems);
item.SubmenuOpened += (sender, args) => {
item.ItemsSource = ExpandMenuBuilders(subItems);
args.Handled = true;
};
return item;
case "Builder":
IMenuItemBuilder builder = codon.AddIn.CreateObject(codon.Properties["class"]) as IMenuItemBuilder;
if (builder == null)
throw new NotSupportedException("Menu item builder " + codon.Properties["class"] + " does not implement IMenuItemBuilder");
return new MenuItemBuilderPlaceholder(builder, descriptor.Codon, descriptor.Caller);
default:
throw new System.NotSupportedException("unsupported menu item type : " + type);
}
}
public static string ConvertLabel(string label)
{
return label.Replace("_", "__").Replace("&", "_");
}
// HACK: find a better way to allow the host app to process link commands
public static Converter<string, ICommand> LinkCommandCreator;
/// <summary>
/// Creates an KeyGesture for a shortcut.
/// </summary>
public static KeyGesture ParseShortcut(string text)
{
return (KeyGesture)new KeyGestureConverter().ConvertFromInvariantString(text.Replace(',', '+').Replace('|', '+'));
}
}
}

24
src/Main/ICSharpCode.Core.Presentation/NativeMethods.cs

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
// <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.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
namespace ICSharpCode.Core.Presentation
{
static class NativeMethods
{
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject(IntPtr hObject);
}
}

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

@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
// <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.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A WPF control that aligns its content on pixel boundaries.
/// </summary>
public class PixelSnapper : UIElement
{
public PixelSnapper()
{
}
public PixelSnapper(UIElement visualChild)
: this()
{
this.Child = visualChild;
}
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));
// check again after the whole layout pass has finished, maybe we need to move
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new ThreadStart(CheckLayout));
}
}
private void CheckLayout()
{
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.
static 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;
}
static 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;
}
static bool AreClose(Point point1, Point point2)
{
return AreClose(point1.X, point2.X) && AreClose(point1.Y, point2.Y);
}
static 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;
}
}

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

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// <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.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Creates WPF BitmapSource objects from images in the ResourceService.
/// </summary>
public static class PresentationResourceService
{
static readonly Dictionary<string, BitmapSource> bitmapCache = new Dictionary<string, BitmapSource>();
static PresentationResourceService()
{
ResourceService.ClearCaches += ResourceService_ClearCaches;
}
static void ResourceService_ClearCaches(object sender, EventArgs e)
{
lock (bitmapCache) {
bitmapCache.Clear();
}
}
/// <summary>
/// Creates a new System.Windows.Controls.Image object containing the image with the
/// specified resource name.
/// </summary>
/// <param name="name">
/// The name of the requested bitmap.
/// </param>
/// <exception cref="ResourceNotFoundException">
/// Is thrown when the GlobalResource manager can't find a requested resource.
/// </exception>
public static System.Windows.Controls.Image GetImage(string name)
{
return new System.Windows.Controls.Image {
Source = GetBitmapSource(name)
};
}
/// <summary>
/// Creates a new PixelSnapper object containing the image with the
/// specified resource name.
/// </summary>
/// <param name="name">
/// The name of the requested bitmap.
/// </param>
/// <exception cref="ResourceNotFoundException">
/// Is thrown when the GlobalResource manager can't find a requested resource.
/// </exception>
public static PixelSnapper GetPixelSnappedImage(string name)
{
return new PixelSnapper(GetImage(name));
}
/// <summary>
/// Returns a BitmapSource from the resource database, it handles localization
/// transparent for the user.
/// </summary>
/// <param name="name">
/// The name of the requested bitmap.
/// </param>
/// <exception cref="ResourceNotFoundException">
/// Is thrown when the GlobalResource manager can't find a requested resource.
/// </exception>
public static BitmapSource GetBitmapSource(string name)
{
lock (bitmapCache) {
BitmapSource bs;
if (bitmapCache.TryGetValue(name, out bs))
return bs;
System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)ResourceService.GetImageResource(name);
if (bmp == null) {
throw new ResourceNotFoundException(name);
}
IntPtr hBitmap = bmp.GetHbitmap();
try {
bs = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero,
Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
bs.Freeze();
bitmapCache[name] = bs;
} finally {
NativeMethods.DeleteObject(hBitmap);
}
return bs;
}
}
}
}

29
src/Main/ICSharpCode.Core.Presentation/Properties/AssemblyInfo.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
// <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.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Markup;
[assembly: CLSCompliant(true)]
[assembly: StringFreezing()]
[assembly: AssemblyTitle("ICSharpCode.Core.Presentation")]
[assembly: AssemblyDescription("ICSharpCode.Core, Windows Presentation Foundation implementation")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ThemeInfo(
ResourceDictionaryLocation.SourceAssembly, //where theme specific resource dictionaries are located
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
)]
[assembly: XmlnsPrefix("http://icsharpcode.net/sharpdevelop/core", "core")]
[assembly: XmlnsDefinition("http://icsharpcode.net/sharpdevelop/core", "ICSharpCode.Core.Presentation")]

95
src/Main/ICSharpCode.Core.Presentation/SplitButton.cs

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
// <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.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A button with drop-down menu.
/// </summary>
public class SplitButton : ButtonBase
{
public static readonly DependencyProperty DropDownMenuProperty
= DependencyProperty.Register("DropDownMenu", typeof(ContextMenu),
typeof(SplitButton), new FrameworkPropertyMetadata(null));
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
protected static readonly DependencyPropertyKey IsDropDownMenuOpenPropertyKey
= DependencyProperty.RegisterReadOnly("IsDropDownMenuOpen", typeof(bool),
typeof(SplitButton), new FrameworkPropertyMetadata(false));
public static readonly DependencyProperty IsDropDownMenuOpenProperty = IsDropDownMenuOpenPropertyKey.DependencyProperty;
static SplitButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SplitButton), new FrameworkPropertyMetadata(typeof(SplitButton)));
}
public ContextMenu DropDownMenu {
get { return (ContextMenu)GetValue(DropDownMenuProperty); }
set { SetValue(DropDownMenuProperty, value); }
}
public bool IsDropDownMenuOpen {
get { return (bool)GetValue(IsDropDownMenuOpenProperty); }
protected set { SetValue(IsDropDownMenuOpenPropertyKey, value); }
}
FrameworkElement dropDownButton;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
dropDownButton = (FrameworkElement)Template.FindName("PART_DropDownButton", this);
}
bool IsOverDropDownButton(MouseEventArgs e)
{
if (dropDownButton == null)
return false;
return e.GetPosition(dropDownButton).X >= 0;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (IsOverDropDownButton(e)) {
e.Handled = true;
if (DropDownMenu != null) {
DropDownMenu.Placement = PlacementMode.Bottom;
DropDownMenu.PlacementTarget = this;
DropDownMenu.IsOpen = true;
DropDownMenu.Closed += DropDownMenu_Closed;
this.IsDropDownMenuOpen = true;
}
} else {
base.OnMouseLeftButtonDown(e);
}
}
void DropDownMenu_Closed(object sender, RoutedEventArgs e)
{
((ContextMenu)sender).Closed -= DropDownMenu_Closed;
this.IsDropDownMenuOpen = false;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
if (!IsMouseCaptured && IsOverDropDownButton(e)) {
e.Handled = true;
} else {
base.OnMouseLeftButtonUp(e);
}
}
}
}

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

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// <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.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;
public ToolBarButton(Codon codon, object caller, bool createCommand)
{
ToolTipService.SetShowOnDisabled(this, true);
this.codon = codon;
this.caller = caller;
this.Command = new CommandWrapper(codon, caller, createCommand);
if (codon.Properties.Contains("icon")) {
var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
image.Height = 16;
image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
this.Content = new PixelSnapper(image);
}
UpdateText();
SetResourceReference(FrameworkElement.StyleProperty, ToolBar.ButtonStyleKey);
}
public void UpdateText()
{
if (codon.Properties.Contains("label")){
this.Content = StringParser.Parse(codon.Properties["label"]);
}
if (codon.Properties.Contains("tooltip")) {
this.ToolTip = StringParser.Parse(codon.Properties["tooltip"]);
}
}
public void UpdateStatus()
{
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
}

35
src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarComboBox.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// <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.Windows;
using System.Windows.Controls;
namespace ICSharpCode.Core.Presentation
{
sealed class ToolBarComboBox : ComboBox
{
IComboBoxCommand menuCommand;
public ToolBarComboBox(Codon codon, object caller)
{
if (codon == null)
throw new ArgumentNullException("codon");
this.IsEditable = false;
menuCommand = (IComboBoxCommand)codon.AddIn.CreateObject(codon.Properties["class"]);
menuCommand.Owner = this;
SetResourceReference(FrameworkElement.StyleProperty, ToolBar.ComboBoxStyleKey);
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
menuCommand.Run();
}
}
}

115
src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarService.cs

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
// <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;
using System.Collections.Generic;
using System.Windows.Controls;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Creates WPF toolbars from the AddIn Tree.
/// </summary>
public static class ToolBarService
{
/// <summary>
/// Style key used for toolbar images.
/// </summary>
public static readonly object ImageStyleKey = new object();
public static void UpdateStatus(IEnumerable toolBarItems)
{
MenuService.UpdateStatus(toolBarItems);
}
public static IList CreateToolBarItems(object owner, string addInTreePath)
{
return CreateToolBarItems(AddInTree.BuildItems<ToolbarItemDescriptor>(addInTreePath, owner, false));
}
static IList CreateToolBarItems(IEnumerable descriptors)
{
ArrayList result = new ArrayList();
foreach (ToolbarItemDescriptor descriptor in descriptors) {
object item = CreateToolBarItemFromDescriptor(descriptor);
if (item is IMenuItemBuilder) {
IMenuItemBuilder submenuBuilder = (IMenuItemBuilder)item;
result.AddRange(submenuBuilder.BuildItems(descriptor.Codon, descriptor.Caller));
} else {
result.Add(item);
}
}
return result;
}
static object CreateToolBarItemFromDescriptor(ToolbarItemDescriptor descriptor)
{
Codon codon = descriptor.Codon;
object caller = descriptor.Caller;
string type = codon.Properties.Contains("type") ? codon.Properties["type"] : "Item";
bool createCommand = codon.Properties["loadclasslazy"] == "false";
switch (type) {
case "Separator":
return new ConditionalSeparator(codon, caller, true);
case "CheckBox":
return "CheckBox";
//return new ToolBarCheckBox(codon, caller);
case "Item":
return new ToolBarButton(codon, caller, createCommand);
case "ComboBox":
return new ToolBarComboBox(codon, caller);
case "TextBox":
return "TextBox";
//return new ToolBarTextBox(codon, caller);
case "Label":
return "Label";
//return new ToolBarLabel(codon, caller);
case "DropDownButton":
return "DropDownButton";
//return new ToolBarDropDownButton(codon, caller, MenuService.CreateMenuItems(descriptor.SubItems));
case "SplitButton":
return new ToolBarSplitButton(codon, caller, MenuService.CreateMenuItems(null, descriptor.SubItems));
case "Builder":
return codon.AddIn.CreateObject(codon.Properties["class"]);
default:
throw new System.NotSupportedException("unsupported menu item type : " + type);
}
}
static ToolBar CreateToolBar(object owner, AddInTreeNode treeNode)
{
ToolBar tb = new ToolBar();
tb.ItemsSource = CreateToolBarItems(treeNode.BuildChildItems<ToolbarItemDescriptor>(owner));
UpdateStatus(tb.ItemsSource); // setting Visible is only possible after the items have been added
//new LanguageChangeWatcher(toolStrip);
return tb;
}
public static ToolBar CreateToolBar(object owner, string addInTreePath)
{
return CreateToolBar(owner, AddInTree.GetTreeNode(addInTreePath));
}
public static ToolBar[] CreateToolBars(object owner, string addInTreePath)
{
AddInTreeNode treeNode;
try {
treeNode = AddInTree.GetTreeNode(addInTreePath);
} catch (TreePathNotFoundException) {
return null;
}
List<ToolBar> toolBars = new List<ToolBar>();
foreach (AddInTreeNode childNode in treeNode.ChildNodes.Values) {
toolBars.Add(CreateToolBar(owner, childNode));
}
return toolBars.ToArray();
}
}
}

65
src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
// <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;
using System.Windows;
using System.Windows.Controls;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// A tool bar button based on the AddIn-tree.
/// </summary>
sealed class ToolBarSplitButton : SplitButton, IStatusUpdate
{
ICommand menuCommand;
object caller;
Codon codon;
public ToolBarSplitButton(Codon codon, object caller, IList submenu)
{
ToolTipService.SetShowOnDisabled(this, true);
this.codon = codon;
this.caller = caller;
if (codon.Properties.Contains("icon")) {
var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
image.Height = 16;
image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
this.Content = new PixelSnapper(image);
}
menuCommand = (ICommand)codon.AddIn.CreateObject(codon.Properties["class"]);
menuCommand.Owner = this;
this.Command = new CommandWrapper(codon, caller, menuCommand);
this.DropDownMenu = MenuService.CreateContextMenu(submenu);
UpdateText();
}
public void UpdateText()
{
if (codon.Properties.Contains("label")){
this.Content = StringParser.Parse(codon.Properties["label"]);
}
if (codon.Properties.Contains("tooltip")) {
this.ToolTip = StringParser.Parse(codon.Properties["tooltip"]);
}
}
public void UpdateStatus()
{
if (codon.GetFailedAction(caller) == ConditionFailedAction.Exclude)
this.Visibility = Visibility.Collapsed;
else
this.Visibility = Visibility.Visible;
}
}
}

81
src/Main/ICSharpCode.Core.Presentation/themes/Aero.NormalColor.xaml

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.Core.Presentation"
>
<Style TargetType="{x:Type local:SplitButton}">
<Setter Property="TextElement.Foreground" Value = "{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Control.Padding" Value="2,2,2,2"/>
<Setter Property="Border.BorderThickness" Value="1,1,1,1"/>
<Setter Property="Panel.Background" Value="Transparent"/>
<Setter Property="Border.BorderBrush" Value="Transparent"/>
<Setter Property="FrameworkElement.HorizontalAlignment" Value="Center"/>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
<Setter Property="Control.VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SplitButton"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="OuterBorder"
SnapsToDevicePixels="True"
>
<StackPanel Orientation="Horizontal">
<ContentPresenter
Margin="{TemplateBinding Control.Padding}"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
<Border
Name="PART_DropDownButton"
BorderThickness="1,0,0,0"
BorderBrush="{Binding ElementName=OuterBorder, Path=BorderBrush}"
SnapsToDevicePixels="True"
>
<Path Margin="2"
Data = "M0,0 L1,0 0.5,1 z"
Fill = "{TemplateBinding TextElement.Foreground}"
Width = "7"
Height = "3.5"
Stretch = "Fill"/>
</Border>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF3399FF" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FFC2E0FF"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="#FFC2E0FF"/>
</Trigger>
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF3399FF"/>
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FFC2E0FF"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="#FFC2E0FF"/>
</Trigger>
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF3399FF"/>
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FF99CCFF"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="local:SplitButton.IsDropDownMenuOpen" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
<Setter Property="Border.BorderBrush" TargetName="PART_DropDownButton" Value="Transparent" />
<Setter Property="Border.BorderThickness" TargetName="OuterBorder" Value="1,1,1,0" />
<Setter Property="Border.Padding" TargetName="OuterBorder" Value="0,0,0,1" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="Transparent"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

81
src/Main/ICSharpCode.Core.Presentation/themes/generic.xaml

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.Core.Presentation"
>
<Style TargetType="{x:Type local:SplitButton}">
<Setter Property="TextElement.Foreground" Value = "{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Control.Padding" Value="2,2,2,2"/>
<Setter Property="Border.BorderThickness" Value="1,1,1,1"/>
<Setter Property="Panel.Background" Value="Transparent"/>
<Setter Property="Border.BorderBrush" Value="Transparent"/>
<Setter Property="FrameworkElement.HorizontalAlignment" Value="Center"/>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
<Setter Property="Control.VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SplitButton"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="OuterBorder"
SnapsToDevicePixels="True"
>
<StackPanel Orientation="Horizontal">
<ContentPresenter
Margin="{TemplateBinding Control.Padding}"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
<Border
Name="PART_DropDownButton"
BorderThickness="1,0,0,0"
BorderBrush="{Binding ElementName=OuterBorder, Path=BorderBrush}"
SnapsToDevicePixels="True"
>
<Path Margin="2"
Data = "M0,0 L1,0 0.5,1 z"
Fill = "{TemplateBinding TextElement.Foreground}"
Width = "7"
Height = "3.5"
Stretch = "Fill"/>
</Border>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF0A246A" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FFB6BDD2"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="#FFB6BDD2"/>
</Trigger>
<Trigger Property="UIElement.IsKeyboardFocused" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF0A246A"/>
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FFB6BDD2"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="#FFB6BDD2"/>
</Trigger>
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="#FF0A246A"/>
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="#FF8592B5"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="local:SplitButton.IsDropDownMenuOpen" Value="True">
<Setter Property="Border.BorderBrush" TargetName="OuterBorder" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
<Setter Property="Border.BorderBrush" TargetName="PART_DropDownButton" Value="Transparent" />
<Setter Property="Border.BorderThickness" TargetName="OuterBorder" Value="1,1,1,0" />
<Setter Property="Border.Padding" TargetName="OuterBorder" Value="0,0,0,1" />
<Setter Property="Panel.Background" TargetName="OuterBorder" Value="Transparent"/>
<Setter Property="Panel.Background" TargetName="PART_DropDownButton" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

3
src/Setup/Files.wxs

@ -709,6 +709,9 @@ @@ -709,6 +709,9 @@
<Component Guid="2EC34D8A-CF14-4E1F-A512-9A596A1C256D" Id="ICSharpCodeCoreWinFormsDll" DiskId="1">
<File Source="..\..\bin\ICSharpCode.Core.WinForms.dll" Name="ICSharpCode.Core.WinForms.dll" Id="ICSharpCode.Core.WinForms.dll" KeyPath="yes" />
</Component>
<Component Guid="A567716C-7776-4A03-87EB-68818CB36D14" Id="ICSharpCodeCorePresentationDll" DiskId="1">
<File Source="..\..\bin\ICSharpCode.Core.Presentation.dll" Name="ICSharpCode.Core.Presentation.dll" Id="ICSharpCode.Core.Presentation.dll" KeyPath="yes" />
</Component>
</Directory>
<Directory Id="DocFolder" Name="doc">
<Component Guid="9DCED5AC-B771-4A4F-B4FE-69867BF2EBDE" Id="SharpDevelopDocFiles" DiskId="1">

1
src/Setup/Setup.wxs

@ -170,6 +170,7 @@ @@ -170,6 +170,7 @@
<ComponentRef Id="BuildWorkerFiles"/>
<ComponentRef Id="ICSharpCodeCoreDll"/>
<ComponentRef Id="ICSharpCodeCoreWinFormsDll"/>
<ComponentRef Id="ICSharpCodeCorePresentationDll"/>
<ComponentRef Id="ICSharpCodeNRefactoryDll"/>
<ComponentRef Id="ICSharpCodeSharpDevelopDll"/>
<ComponentRef Id="ICSharpCodeSharpDevelopDomdll"/>

9
src/SharpDevelop.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
# SharpDevelop 3.0.0.3638
# SharpDevelop 3.1.0.3801
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}"
ProjectSection(SolutionItems) = postProject
EndProjectSection
@ -158,6 +158,8 @@ Project("{00000000-0000-0000-0000-000000000000}") = "Tools", "Tools\Tools.build" @@ -158,6 +158,8 @@ Project("{00000000-0000-0000-0000-000000000000}") = "Tools", "Tools\Tools.build"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.BuildWorker", "Main\ICSharpCode.SharpDevelop.BuildWorker\ICSharpCode.SharpDevelop.BuildWorker.csproj", "{C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.Presentation", "Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj", "{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -388,6 +390,10 @@ Global @@ -388,6 +390,10 @@ Global
{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.Build.0 = Release|Any CPU
{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.Build.0 = Release|Any CPU
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5}
@ -445,6 +451,7 @@ Global @@ -445,6 +451,7 @@ Global
{D3C782BA-178E-4235-A3BA-8C11DEBB6BEE} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C}
{4139CCF6-FB49-4A9D-B2CF-331E9EA3198D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C}
{E73BB233-D88B-44A7-A98F-D71EE158381D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C}
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486}
{C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486}
B13EFF7F-7EA4-4B68-A375-D112105E9182 = {5A3EBEBA-0560-41C1-966B-23F7D03A5486}
{1152B71B-3C05-4598-B20D-823B5D40559E} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486}

Loading…
Cancel
Save