20 changed files with 558 additions and 115 deletions
@ -0,0 +1,72 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.Build.Tasks; |
||||||
|
using ICSharpCode.SharpDevelop.Project.Converter; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Project.PortableLibrary |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Project behavior attached to all non-portable C# and VB projects.
|
||||||
|
/// </summary>
|
||||||
|
public class ConvertToPortableLibraryProjectBehavior : ProjectBehavior |
||||||
|
{ |
||||||
|
public override IEnumerable<TargetFramework> GetAvailableTargetFrameworks() |
||||||
|
{ |
||||||
|
return base.GetAvailableTargetFrameworks().Concat(new [] { new PickPortableTargetFramework() }); |
||||||
|
} |
||||||
|
|
||||||
|
public override void UpgradeProject(CompilerVersion newVersion, TargetFramework newFramework) |
||||||
|
{ |
||||||
|
PortableTargetFramework newFx = newFramework as PortableTargetFramework; |
||||||
|
if (newFx != null) { |
||||||
|
// Convert to portable library
|
||||||
|
Core.AnalyticsMonitorService.TrackFeature(GetType(), "ConvertToPortableLibrary"); |
||||||
|
var project = (CompilableProject)Project; |
||||||
|
lock (project.SyncRoot) { |
||||||
|
if (newVersion != null && GetAvailableCompilerVersions().Contains(newVersion)) { |
||||||
|
project.SetToolsVersion(newVersion.MSBuildVersion.Major + "." + newVersion.MSBuildVersion.Minor); |
||||||
|
} |
||||||
|
project.SetProperty(null, null, "TargetFrameworkProfile", newFx.TargetFrameworkProfile, PropertyStorageLocations.Base, true); |
||||||
|
project.SetProperty(null, null, "TargetFrameworkVersion", newFx.TargetFrameworkVersion, PropertyStorageLocations.Base, true); |
||||||
|
// Convert <Imports>
|
||||||
|
project.PerformUpdateOnProjectFile( |
||||||
|
delegate { |
||||||
|
foreach (var import in project.MSBuildProjectFile.Imports) { |
||||||
|
if (import.Project.EndsWith(PortableLibraryProjectBehavior.NormalCSharpTargets, StringComparison.OrdinalIgnoreCase)) { |
||||||
|
import.Project = PortableLibraryProjectBehavior.PortableTargetsPath + PortableLibraryProjectBehavior.PortableCSharpTargets; |
||||||
|
break; |
||||||
|
} else if (import.Project.EndsWith(PortableLibraryProjectBehavior.NormalVBTargets, StringComparison.OrdinalIgnoreCase)) { |
||||||
|
import.Project = PortableLibraryProjectBehavior.PortableTargetsPath + PortableLibraryProjectBehavior.PortableVBTargets; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
// Remove references
|
||||||
|
foreach (var referenceItem in project.GetItemsOfType(ItemType.Reference).ToArray()) { |
||||||
|
// get short assembly name:
|
||||||
|
string assemblyName = referenceItem.Include; |
||||||
|
if (assemblyName.IndexOf(',') >= 0) |
||||||
|
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(',')); |
||||||
|
assemblyName += ","; |
||||||
|
if (KnownFrameworkAssemblies.FullAssemblyNames.Any(fullName => fullName.StartsWith(assemblyName, StringComparison.OrdinalIgnoreCase))) { |
||||||
|
// If it's a framework assembly, remove the reference
|
||||||
|
// (portable libraries automatically reference all available framework assemblies)
|
||||||
|
ProjectService.RemoveProjectItem(project, referenceItem); |
||||||
|
} |
||||||
|
} |
||||||
|
project.AddProjectType(ProjectTypeGuids.PortableLibrary); |
||||||
|
project.Save(); |
||||||
|
ProjectBrowserPad.RefreshViewAsync(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
base.UpgradeProject(newVersion, newFramework); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,57 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.SharpDevelop.Gui; |
||||||
|
using ICSharpCode.SharpDevelop.Project.Converter; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Project.PortableLibrary |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Dummy TargetFramework that displays the SelectProfileDialog.
|
||||||
|
/// </summary>
|
||||||
|
sealed class PickPortableTargetFramework : TargetFramework |
||||||
|
{ |
||||||
|
public PickPortableTargetFramework() |
||||||
|
: base("PickPortableTargetFramework", ".NET Portable Subset (choose target frameworks)") |
||||||
|
{ |
||||||
|
this.MinimumMSBuildVersion = new Version(4, 0); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object obj) |
||||||
|
{ |
||||||
|
return obj is PickPortableTargetFramework; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public override TargetFramework PickFramework(IEnumerable<IUpgradableProject> selectedProjects) |
||||||
|
{ |
||||||
|
if (ProfileList.IsPortableLibraryInstalled()) { |
||||||
|
SelectProfileDialog dlg = new SelectProfileDialog(ProfileList.Instance); |
||||||
|
dlg.Owner = WorkbenchSingleton.MainWindow; |
||||||
|
if (selectedProjects != null) { |
||||||
|
var project = selectedProjects.FirstOrDefault() as CompilableProject; |
||||||
|
if (project != null) { |
||||||
|
Profile profile = Profile.LoadProfile(project.TargetFrameworkVersion, project.TargetFrameworkProfile); |
||||||
|
if (profile != null) |
||||||
|
dlg.SelectedProfile = profile; |
||||||
|
} |
||||||
|
} |
||||||
|
if (dlg.ShowDialog() == true && dlg.SelectedProfile != null) { |
||||||
|
return new PortableTargetFramework(dlg.SelectedProfile); |
||||||
|
} |
||||||
|
} else { |
||||||
|
new CheckPortableLibraryInstalled().Run(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,65 @@ |
|||||||
|
<Window x:Class="ICSharpCode.SharpDevelop.Project.PortableLibrary.SelectProfileDialog" x:ClassModifier="internal" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:local="clr-namespace:ICSharpCode.SharpDevelop.Project.PortableLibrary" |
||||||
|
xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" |
||||||
|
Title="Select Portable Library Profile" MinWidth="300" MinHeight="200" Height="350" Width="400" WindowStartupLocation="CenterOwner" |
||||||
|
Style="{x:Static core:GlobalStyles.DialogWindowStyle}"> |
||||||
|
<Grid> |
||||||
|
<Grid.Resources> |
||||||
|
<widgets:BoolToVisibilityConverter x:Key="showWhenTrue" TrueValue="Visible" FalseValue="Collapsed" /> |
||||||
|
<widgets:BoolToVisibilityConverter x:Key="showWhenFalse" TrueValue="Collapsed" FalseValue="Visible" /> |
||||||
|
</Grid.Resources> |
||||||
|
<Grid.RowDefinitions> |
||||||
|
<RowDefinition |
||||||
|
Height="1*" /> |
||||||
|
<RowDefinition |
||||||
|
Height="Auto" MinHeight="50" /> |
||||||
|
<RowDefinition |
||||||
|
Height="Auto" /> |
||||||
|
</Grid.RowDefinitions> |
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> |
||||||
|
<ItemsControl ItemsSource="{Binding SupportedFrameworkGroups}" Margin="8"> |
||||||
|
<ItemsControl.ItemsPanel> |
||||||
|
<ItemsPanelTemplate> |
||||||
|
<widgets:StackPanelWithSpacing Orientation="Vertical" SpaceBetweenItems="10"/> |
||||||
|
</ItemsPanelTemplate> |
||||||
|
</ItemsControl.ItemsPanel> |
||||||
|
<ItemsControl.ItemTemplate> |
||||||
|
<DataTemplate DataType="{x:Type local:SupportedFrameworkGroup}"> |
||||||
|
<StackPanel Orientation="Vertical"> |
||||||
|
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding DisplayName}" FontWeight="Bold" /> |
||||||
|
<ComboBox Name="comboBox" ItemsSource="{Binding AvailableVersions}" SelectedItem="{Binding SelectedVersion}" |
||||||
|
Margin="20,0,0,0" IsEnabled="{Binding IsChecked}" /> |
||||||
|
</StackPanel> |
||||||
|
<DataTemplate.Triggers> |
||||||
|
<DataTrigger Binding="{Binding AvailableVersions.Count}" Value="1"> |
||||||
|
<DataTrigger.Setters> |
||||||
|
<Setter TargetName="comboBox" Property="Visibility" Value="Collapsed" /> |
||||||
|
</DataTrigger.Setters> |
||||||
|
</DataTrigger> |
||||||
|
</DataTemplate.Triggers> |
||||||
|
</DataTemplate> |
||||||
|
</ItemsControl.ItemTemplate> |
||||||
|
</ItemsControl> |
||||||
|
</ScrollViewer> |
||||||
|
<TextBlock Grid.Row="1" TextWrapping="WrapWithOverflow" Visibility="{Binding HasTwoOrMoreFrameworksSelected, Converter={StaticResource showWhenTrue}}"> |
||||||
|
<Bold>Selected profile:</Bold> <Run Text="{Binding SelectedProfile.DisplayName, Mode=OneWay}"/> |
||||||
|
</TextBlock> |
||||||
|
<TextBlock Grid.Row="1" TextWrapping="WrapWithOverflow" Visibility="{Binding HasTwoOrMoreFrameworksSelected, Converter={StaticResource showWhenFalse}}"> |
||||||
|
<Bold>Two or more frameworks must be selected.</Bold> |
||||||
|
</TextBlock> |
||||||
|
<widgets:UniformGridWithSpacing Columns="2" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right" Margin="0,4,12,12"> |
||||||
|
<Button |
||||||
|
Content="{core:Localize Global.OKButtonText}" |
||||||
|
IsDefault="True" |
||||||
|
Click="okButton_Click" |
||||||
|
IsEnabled="{Binding HasTwoOrMoreFrameworksSelected}" |
||||||
|
Style="{x:Static core:GlobalStyles.ButtonStyle}" /> |
||||||
|
<Button |
||||||
|
Content="{core:Localize Global.CancelButtonText}" |
||||||
|
IsCancel="True" |
||||||
|
Style="{x:Static core:GlobalStyles.ButtonStyle}" /> |
||||||
|
</widgets:UniformGridWithSpacing> |
||||||
|
</Grid> |
||||||
|
</Window> |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Documents; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Project.PortableLibrary |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SelectProfileDialog.xaml
|
||||||
|
/// </summary>
|
||||||
|
internal partial class SelectProfileDialog : Window, INotifyPropertyChanged |
||||||
|
{ |
||||||
|
readonly ProfileList profileList; |
||||||
|
readonly List<SupportedFrameworkGroup> viewModels; |
||||||
|
|
||||||
|
public IEnumerable<SupportedFrameworkGroup> SupportedFrameworkGroups { |
||||||
|
get { return viewModels; } |
||||||
|
} |
||||||
|
|
||||||
|
public SelectProfileDialog(ProfileList profileList) |
||||||
|
{ |
||||||
|
if (profileList == null) |
||||||
|
throw new ArgumentNullException("profileList"); |
||||||
|
InitializeComponent(); |
||||||
|
this.profileList = profileList; |
||||||
|
Debug.WriteLine(string.Join(Environment.NewLine, profileList.AllProfiles.Select(p => p.DisplayName))); |
||||||
|
viewModels = profileList.AllFrameworks.GroupBy(fx => fx.DisplayName, (key, group) => new SupportedFrameworkGroup(group)).ToList(); |
||||||
|
this.DataContext = this; |
||||||
|
foreach (var vm in viewModels) { |
||||||
|
vm.PropertyChanged += delegate { UpdateSelectedProfile(); }; |
||||||
|
} |
||||||
|
UpdateSelectedProfile(); |
||||||
|
} |
||||||
|
|
||||||
|
void okButton_Click(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
this.DialogResult = true; |
||||||
|
Close(); |
||||||
|
} |
||||||
|
|
||||||
|
Profile selectedProfile; |
||||||
|
bool isSettingProfile; |
||||||
|
|
||||||
|
public Profile SelectedProfile { |
||||||
|
get { return selectedProfile; } |
||||||
|
set { |
||||||
|
selectedProfile = value; |
||||||
|
isSettingProfile = true; |
||||||
|
foreach (var g in viewModels) { |
||||||
|
if (value == null) { |
||||||
|
g.IsChecked = false; |
||||||
|
} else { |
||||||
|
SupportedFramework version = g.AvailableVersions.Intersect(value.SupportedFrameworks).FirstOrDefault(); |
||||||
|
if (version != null) { |
||||||
|
g.IsChecked = true; |
||||||
|
g.SelectedVersion = version; |
||||||
|
} else { |
||||||
|
g.IsChecked = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
isSettingProfile = false; |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("SelectedProfile")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public bool HasTwoOrMoreFrameworksSelected { |
||||||
|
get { return viewModels.Count(vm => vm.IsChecked) >= 2; } |
||||||
|
} |
||||||
|
|
||||||
|
void UpdateSelectedProfile() |
||||||
|
{ |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("HasTwoOrMoreFrameworksSelected")); |
||||||
|
if (isSettingProfile) |
||||||
|
return; |
||||||
|
var requestedFrameworks = (from g in viewModels where g.IsChecked select g.SelectedVersion).ToList(); |
||||||
|
var bestProfile = profileList.GetBestProfile(requestedFrameworks); |
||||||
|
if (bestProfile != selectedProfile) { |
||||||
|
selectedProfile = bestProfile; |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("SelectedProfile")); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged = delegate {}; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View model used in SelectProfileDialog
|
||||||
|
/// </summary>
|
||||||
|
sealed class SupportedFrameworkGroup : INotifyPropertyChanged |
||||||
|
{ |
||||||
|
readonly IList<SupportedFramework> availableVersions; |
||||||
|
bool isChecked; |
||||||
|
SupportedFramework selectedVersion; |
||||||
|
|
||||||
|
public SupportedFrameworkGroup(IEnumerable<SupportedFramework> availableVersions) |
||||||
|
{ |
||||||
|
this.availableVersions = availableVersions.OrderBy(v => v.MinimumVersion).ToList(); |
||||||
|
this.isChecked = true; |
||||||
|
this.selectedVersion = this.availableVersions.First(); |
||||||
|
} |
||||||
|
|
||||||
|
public IList<SupportedFramework> AvailableVersions { |
||||||
|
get { return availableVersions; } |
||||||
|
} |
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged; |
||||||
|
|
||||||
|
private void OnPropertyChanged(string propertyName) |
||||||
|
{ |
||||||
|
if (PropertyChanged != null) { |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public string DisplayName { |
||||||
|
get { return availableVersions[0].DisplayName; } |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsChecked { |
||||||
|
get { return isChecked; } |
||||||
|
set { |
||||||
|
if (isChecked != value) { |
||||||
|
isChecked = value; |
||||||
|
OnPropertyChanged("IsChecked"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public SupportedFramework SelectedVersion { |
||||||
|
get { return selectedVersion; } |
||||||
|
set { |
||||||
|
if (selectedVersion != value) { |
||||||
|
selectedVersion = value; |
||||||
|
OnPropertyChanged("SelectedVersion"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Globalization; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Data; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Widgets |
||||||
|
{ |
||||||
|
[ValueConversion(typeof(bool), typeof(Visibility))] |
||||||
|
public class BoolToVisibilityConverter : IValueConverter |
||||||
|
{ |
||||||
|
public Visibility TrueValue { get; set; } |
||||||
|
public Visibility FalseValue { get; set; } |
||||||
|
|
||||||
|
public BoolToVisibilityConverter() |
||||||
|
{ |
||||||
|
this.TrueValue = Visibility.Visible; |
||||||
|
this.FalseValue = Visibility.Collapsed; |
||||||
|
} |
||||||
|
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
if ((value as bool?) == true) |
||||||
|
return TrueValue; |
||||||
|
else |
||||||
|
return FalseValue; |
||||||
|
} |
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
return value is Visibility && (Visibility)value == TrueValue; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue