Browse Source

Local palettes working

flabbet 3 years ago
parent
commit
092a74ea7c

+ 1 - 1
PixiEditor/Helpers/Extensions/DirectoryExtensions.cs

@@ -13,7 +13,7 @@ namespace PixiEditor.Helpers.Extensions
         /// <returns>List of file paths found.</returns>
         /// <returns>List of file paths found.</returns>
         public static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
         public static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
         {
         {
-            return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray();
+            return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, $"*{filter}", searchOption)).ToArray();
         }
         }
     }
     }
 }
 }

+ 3 - 0
PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs

@@ -1,6 +1,7 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers.Shortcuts;
 using PixiEditor.Models.Controllers.Shortcuts;
+using PixiEditor.Models.DataProviders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO.JascPalFile;
 using PixiEditor.Models.IO.JascPalFile;
 using PixiEditor.Models.Services;
 using PixiEditor.Models.Services;
@@ -56,6 +57,8 @@ namespace PixiEditor.Helpers.Extensions
                 .AddSingleton<Tool, ZoomTool>()
                 .AddSingleton<Tool, ZoomTool>()
                 // Palette Parsers
                 // Palette Parsers
                 .AddSingleton<PaletteFileParser, JascFileParser>()
                 .AddSingleton<PaletteFileParser, JascFileParser>()
+                // Palette data sources
+                .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>()
                 // Other
                 // Other
                 .AddSingleton<DocumentProvider>();
                 .AddSingleton<DocumentProvider>();
     }
     }

+ 1 - 0
PixiEditor/Helpers/RelayCommand.cs

@@ -37,6 +37,7 @@ namespace PixiEditor.Helpers
 
 
         public bool CanExecute(object parameter)
         public bool CanExecute(object parameter)
         {
         {
+            if (canExecute == null) return true;
             if(parameter != null && parameter is not T)
             if(parameter != null && parameter is not T)
             {
             {
                 throw new ArgumentException("Provided parameter type does not match RelayCommand parameter type");
                 throw new ArgumentException("Provided parameter type does not match RelayCommand parameter type");

+ 5 - 4
PixiEditor/Models/DataHolders/Palettes/Palette.cs

@@ -1,15 +1,16 @@
-using System.Collections.ObjectModel;
+using PixiEditor.Helpers;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
 
 
 namespace PixiEditor.Models.DataHolders.Palettes
 namespace PixiEditor.Models.DataHolders.Palettes
 {
 {
     public class Palette
     public class Palette
     {
     {
         public string Title { get; set; }
         public string Title { get; set; }
-        public WpfObservableRangeCollection<string> Colors { get; set; }
+        public List<string> Colors { get; set; }
         public string[] Tags { get; set; }
         public string[] Tags { get; set; }
 
 
-        public Palette() { }
-        public Palette(string title, WpfObservableRangeCollection<string> colors, string[] tags)
+        public Palette(string title, List<string> colors, string[] tags)
         {
         {
             Title = title;
             Title = title;
             Colors = colors;
             Colors = colors;

+ 5 - 3
PixiEditor/Models/DataHolders/Palettes/PaletteList.cs

@@ -1,8 +1,10 @@
-namespace PixiEditor.Models.DataHolders.Palettes
+using PixiEditor.Helpers;
+
+namespace PixiEditor.Models.DataHolders.Palettes
 {
 {
     public class PaletteList
     public class PaletteList
     {
     {
-        public bool FetchedCorrectly { get; set; }
-        public WpfObservableRangeCollection<Palette> Palettes { get; set; }
+        public bool FetchedCorrectly { get; set; } = false;
+        public WpfObservableRangeCollection<Palette> Palettes { get; set; } = new WpfObservableRangeCollection<Palette>();
     }
     }
 }
 }

+ 14 - 5
PixiEditor/Models/DataProviders/LocalPalettesFetcher.cs

@@ -17,14 +17,15 @@ namespace PixiEditor.Models.DataProviders
             Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
             Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
             "PixiEditor", "Palettes");
             "PixiEditor", "Palettes");
 
 
-        public IEnumerable<PaletteFileParser> AvailableParsers { get; private set; }
-
         public override async Task<PaletteList> FetchPaletteList()
         public override async Task<PaletteList> FetchPaletteList()
         {
         {
             string[] files = DirectoryExtensions.GetFiles(PathToPalettesFolder, string.Join("|", AvailableParsers.SelectMany(x => x.SupportedFileExtensions)), SearchOption.TopDirectoryOnly);
             string[] files = DirectoryExtensions.GetFiles(PathToPalettesFolder, string.Join("|", AvailableParsers.SelectMany(x => x.SupportedFileExtensions)), SearchOption.TopDirectoryOnly);
 
 
-            PaletteList result = new PaletteList();
-            result.Palettes = new WpfObservableRangeCollection<Palette>();
+            PaletteList result = new PaletteList
+            {
+                Palettes = new WpfObservableRangeCollection<Palette>()
+            };
+
             for (int i = 0; i < files.Length; i++)
             for (int i = 0; i < files.Length; i++)
             {
             {
                 string filePath = files[i];
                 string filePath = files[i];
@@ -33,12 +34,20 @@ namespace PixiEditor.Models.DataProviders
                 if (foundParser != null)
                 if (foundParser != null)
                 {
                 {
                     PaletteFileData fileData = await foundParser.Parse(filePath);
                     PaletteFileData fileData = await foundParser.Parse(filePath);
-                    result.Palettes.Add(new Palette(fileData.Title, new WpfObservableRangeCollection<string>(fileData.GetHexColors()), fileData.Tags));
+                    result.Palettes.Add(new Palette(fileData.Title, new List<string>(fileData.GetHexColors()), fileData.Tags));
                 }
                 }
             }
             }
 
 
             result.FetchedCorrectly = true;
             result.FetchedCorrectly = true;
             return result;
             return result;
         }
         }
+
+        public override void Initialize()
+        {
+            if(!Directory.Exists(PathToPalettesFolder))
+            {
+                Directory.CreateDirectory(PathToPalettesFolder);
+            }
+        }
     }
     }
 }
 }

+ 5 - 0
PixiEditor/Models/DataProviders/PaletteListDataSource.cs

@@ -1,10 +1,15 @@
 using PixiEditor.Models.DataHolders.Palettes;
 using PixiEditor.Models.DataHolders.Palettes;
+using PixiEditor.Models.IO;
+using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace PixiEditor.Models.DataProviders
 namespace PixiEditor.Models.DataProviders
 {
 {
     public abstract class PaletteListDataSource
     public abstract class PaletteListDataSource
     {
     {
+        public virtual void Initialize() { }
         public abstract Task<PaletteList> FetchPaletteList();
         public abstract Task<PaletteList> FetchPaletteList();
+        public List<PaletteFileParser> AvailableParsers { get; set; }
+
     }
     }
 }
 }

+ 2 - 1
PixiEditor/Models/ExternalServices/LospecPaletteFetcher.cs

@@ -2,6 +2,7 @@
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders.Palettes;
 using PixiEditor.Models.DataHolders.Palettes;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
+using System.Collections.Generic;
 using System.Net;
 using System.Net;
 using System.Net.Http;
 using System.Net.Http;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -57,7 +58,7 @@ namespace PixiEditor.Models.ExternalServices
             return null;
             return null;
         }
         }
 
 
-        private static void ReadjustColors(WpfObservableRangeCollection<string> colors)
+        private static void ReadjustColors(List<string> colors)
         {
         {
             for (int i = 0; i < colors.Count; i++)
             for (int i = 0; i < colors.Count; i++)
             {
             {

+ 2 - 0
PixiEditor/Models/IO/PaletteFileData.cs

@@ -13,6 +13,8 @@ namespace PixiEditor.Models.IO
         public PaletteFileData(SKColor[] colors)
         public PaletteFileData(SKColor[] colors)
         {
         {
             Colors = colors;
             Colors = colors;
+            Title = "";
+            Tags = Array.Empty<string>();
         }
         }
 
 
         public PaletteFileData(string title, SKColor[] colors, string[] tags)
         public PaletteFileData(string title, SKColor[] colors, string[] tags)

+ 15 - 6
PixiEditor/ViewModels/SubViewModels/Main/ColorsViewModel.cs

@@ -1,6 +1,7 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.DataProviders;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
@@ -21,12 +22,12 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public RelayCommand RemoveSwatchCommand { get; set; }
         public RelayCommand RemoveSwatchCommand { get; set; }
 
 
-        public RelayCommand<WpfObservableRangeCollection<string>> ImportPaletteCommand { get; set; }
-
+        public RelayCommand<List<string>> ImportPaletteCommand { get; set; }
 
 
         public RelayCommand<int> SelectPaletteColorCommand { get; set; }
         public RelayCommand<int> SelectPaletteColorCommand { get; set; }
 
 
-        public IEnumerable<PaletteFileParser> PaletteParsers { get; private set; }
+        public WpfObservableRangeCollection<PaletteFileParser> PaletteParsers { get; private set; }
+        public WpfObservableRangeCollection<PaletteListDataSource> PaletteDataSources { get; private set; }
 
 
         private SKColor primaryColor = SKColors.Black;
         private SKColor primaryColor = SKColors.Black;
 
 
@@ -67,10 +68,10 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             RemoveSwatchCommand = new RelayCommand(RemoveSwatch);
             RemoveSwatchCommand = new RelayCommand(RemoveSwatch);
             SwapColorsCommand = new RelayCommand(SwapColors);
             SwapColorsCommand = new RelayCommand(SwapColors);
             SelectPaletteColorCommand = new RelayCommand<int>(SelectPaletteColor);
             SelectPaletteColorCommand = new RelayCommand<int>(SelectPaletteColor);
-            ImportPaletteCommand = new RelayCommand<WpfObservableRangeCollection<string>>(ImportPalette);
+            ImportPaletteCommand = new RelayCommand<List<string>>(ImportPalette);
         }
         }
 
 
-        public void ImportPalette(WpfObservableRangeCollection<string> palette)
+        public void ImportPalette(List<string> palette)
         {
         {
             var doc = Owner.BitmapManager.ActiveDocument;
             var doc = Owner.BitmapManager.ActiveDocument;
             if (doc == null) return;
             if (doc == null) return;
@@ -131,7 +132,15 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public void SetupPaletteParsers(IServiceProvider services)
         public void SetupPaletteParsers(IServiceProvider services)
         {
         {
-            PaletteParsers = services.GetServices<PaletteFileParser>();
+            PaletteParsers = new WpfObservableRangeCollection<PaletteFileParser>(services.GetServices<PaletteFileParser>());
+            PaletteDataSources = new WpfObservableRangeCollection<PaletteListDataSource>(services.GetServices<PaletteListDataSource>());
+            var parsers = PaletteParsers.ToList();
+
+            foreach (var dataSource in PaletteDataSources)
+            {
+                dataSource.AvailableParsers = parsers;
+                dataSource.Initialize();
+            }
         }
         }
     }
     }
 }
 }

+ 1 - 2
PixiEditor/Views/Dialogs/PalettesBrowser.xaml

@@ -68,7 +68,7 @@
                     <ItemsControl.ItemTemplate>
                     <ItemsControl.ItemTemplate>
                         <DataTemplate>
                         <DataTemplate>
                             <local:PaletteItem Palette="{Binding}" 
                             <local:PaletteItem Palette="{Binding}" 
-                                                     ImportPaletteCommand="{Binding ImportPaletteCommand, ElementName=lospecPalettesBrowser}"/>
+                                               ImportPaletteCommand="{Binding ImportPaletteCommand, ElementName=lospecPalettesBrowser}"/>
                         </DataTemplate>
                         </DataTemplate>
                     </ItemsControl.ItemTemplate>
                     </ItemsControl.ItemTemplate>
                 </ItemsControl>
                 </ItemsControl>
@@ -77,6 +77,5 @@
                    Visibility="{Binding ElementName=lospecPalettesBrowser, Path=IsFetching, Converter={StaticResource BoolToVisibilityConverter}}"
                    Visibility="{Binding ElementName=lospecPalettesBrowser, Path=IsFetching, Converter={StaticResource BoolToVisibilityConverter}}"
                    Height="50" gif:ImageBehavior.AnimationSpeedRatio="1.5"/>
                    Height="50" gif:ImageBehavior.AnimationSpeedRatio="1.5"/>
         </Grid>
         </Grid>
-        <TextBlock Grid.Row="3" HorizontalAlignment="Right" Margin="0 0 5 0" Text="Palettes fetched from lospec.com/palette-list" Foreground="White"/>
     </Grid>
     </Grid>
 </Window>
 </Window>

+ 39 - 28
PixiEditor/Views/Dialogs/PalettesBrowser.xaml.cs

@@ -1,22 +1,14 @@
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders.Palettes;
 using PixiEditor.Models.DataHolders.Palettes;
+using PixiEditor.Models.DataProviders;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Events;
 using PixiEditor.Models.Events;
-using PixiEditor.Models.ExternalServices;
 using System;
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
-using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
 
 
 namespace PixiEditor.Views.Dialogs
 namespace PixiEditor.Views.Dialogs
 {
 {
@@ -68,9 +60,20 @@ namespace PixiEditor.Views.Dialogs
 
 
         // Using a DependencyProperty as the backing store for ColorsNumber.  This enables animation, styling, binding, etc...
         // Using a DependencyProperty as the backing store for ColorsNumber.  This enables animation, styling, binding, etc...
         public static readonly DependencyProperty ColorsNumberProperty =
         public static readonly DependencyProperty ColorsNumberProperty =
-            DependencyProperty.Register("ColorsNumber", typeof(int), typeof(PalettesBrowser), 
+            DependencyProperty.Register("ColorsNumber", typeof(int), typeof(PalettesBrowser),
                 new PropertyMetadata(8, ColorsNumberChanged));
                 new PropertyMetadata(8, ColorsNumberChanged));
 
 
+        public WpfObservableRangeCollection<PaletteListDataSource> PaletteListDataSources
+        {
+            get { return (WpfObservableRangeCollection<PaletteListDataSource>)GetValue(PaletteListDataSourcesProperty); }
+            set { SetValue(PaletteListDataSourcesProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for PaletteListDataSources.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty PaletteListDataSourcesProperty =
+            DependencyProperty.Register("PaletteListDataSources", typeof(WpfObservableRangeCollection<PaletteListDataSource>), typeof(PalettesBrowser), new PropertyMetadata(new WpfObservableRangeCollection<PaletteListDataSource>()));
+
+
         public string SortingType { get; set; } = "Default";
         public string SortingType { get; set; } = "Default";
         public ColorsNumberMode ColorsNumberMode { get; set; } = ColorsNumberMode.Any;
         public ColorsNumberMode ColorsNumberMode { get; set; } = ColorsNumberMode.Any;
         public string[] Tags { get; set; } = Array.Empty<string>();
         public string[] Tags { get; set; } = Array.Empty<string>();
@@ -104,7 +107,15 @@ namespace PixiEditor.Views.Dialogs
             IsFetching = true;
             IsFetching = true;
             if (PaletteList == null || refetch)
             if (PaletteList == null || refetch)
             {
             {
-                PaletteList = await LospecPaletteFetcher.FetchPage(0, SortingType.ToLower(), Tags, ColorsNumberMode, ColorsNumber);
+                //PaletteList.Palettes.Clear();
+                for (int i = 0; i < PaletteListDataSources.Count; i++)
+                {
+                    var src = await PaletteListDataSources[i].FetchPaletteList();
+                    if (!src.FetchedCorrectly) continue;
+                    //PaletteList.Palettes.AddRange(src.Palettes); //WHY TF IT DOESN'T UPDATE IN VIEW
+                    PaletteList = src; // So yeah, since we don't have more than 1 palette data source right now, then temp solution
+                }
+
                 OnListFetched.Invoke(PaletteList);
                 OnListFetched.Invoke(PaletteList);
             }
             }
 
 
@@ -113,23 +124,23 @@ namespace PixiEditor.Views.Dialogs
 
 
         private async void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
         private async void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
         {
         {
-            if (PaletteList == null || PaletteList.Palettes == null) return;
-            var scrollViewer = (ScrollViewer)sender;
-            if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
-            {
-                IsFetching = true;
-                _currentPage++;
-                var newPalettes = await LospecPaletteFetcher.FetchPage(_currentPage);
-                if(newPalettes == null || !newPalettes.FetchedCorrectly || newPalettes.Palettes == null)
-                {
-                    IsFetching = false;
-                    return;
-                }
-
-                PaletteList.Palettes.AddRange(newPalettes.Palettes);
-                OnListFetched.Invoke(PaletteList);
-                IsFetching = false;
-            }
+            //if (PaletteList == null || PaletteList.Palettes == null) return;
+            //var scrollViewer = (ScrollViewer)sender;
+            //if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
+            //{
+            //    IsFetching = true;
+            //    _currentPage++;
+            //    var newPalettes = await LospecPaletteFetcher.FetchPage(_currentPage);
+            //    if(newPalettes == null || !newPalettes.FetchedCorrectly || newPalettes.Palettes == null)
+            //    {
+            //        IsFetching = false;
+            //        return;
+            //    }
+
+            //    PaletteList.Palettes.AddRange(newPalettes.Palettes);
+            //    OnListFetched.Invoke(PaletteList);
+            //    IsFetching = false;
+            //}
         }
         }
 
 
         private async void SortingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         private async void SortingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

+ 2 - 0
PixiEditor/Views/MainWindow.xaml

@@ -346,6 +346,8 @@
                                         <palettes:PaletteViewer IsEnabled="{Binding DocumentSubViewModel.Owner.BitmapManager.ActiveDocument,
                                         <palettes:PaletteViewer IsEnabled="{Binding DocumentSubViewModel.Owner.BitmapManager.ActiveDocument,
                                         Converter={converters:NotNullToBoolConverter}}" Colors="{Binding BitmapManager.ActiveDocument.Palette}"
                                         Converter={converters:NotNullToBoolConverter}}" Colors="{Binding BitmapManager.ActiveDocument.Palette}"
                                                               SelectColorCommand="{Binding ColorsSubViewModel.SelectColorCommand}"
                                                               SelectColorCommand="{Binding ColorsSubViewModel.SelectColorCommand}"
+                                                                DataSources="{Binding ColorsSubViewModel.PaletteDataSources}"
+                                                                FileParsers="{Binding ColorsSubViewModel.PaletteParsers}"
                                                                     ImportPaletteCommand="{Binding ColorsSubViewModel.ImportPaletteCommand}"/>
                                                                     ImportPaletteCommand="{Binding ColorsSubViewModel.ImportPaletteCommand}"/>
                                     </avalondock:LayoutAnchorable>
                                     </avalondock:LayoutAnchorable>
                                     <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"
                                     <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"

+ 2 - 2
PixiEditor/Views/UserControls/Palettes/PaletteItem.xaml

@@ -21,7 +21,7 @@
             <Separator Background="{StaticResource MainColor}"/>
             <Separator Background="{StaticResource MainColor}"/>
             <TextBlock Text="{Binding Palette.Title, ElementName=paletteItem}" Foreground="White" FontSize="20"/>
             <TextBlock Text="{Binding Palette.Title, ElementName=paletteItem}" Foreground="White" FontSize="20"/>
             <TextBlock Margin="0 5 0 0">
             <TextBlock Margin="0 5 0 0">
-            <controls:PrependTextBlock PrependColor="Gray" Prepend="Author: " Text="{Binding Palette.User.Name, ElementName=paletteItem}" Foreground="White"/>
+            <!--<controls:PrependTextBlock PrependColor="Gray" Prepend="Author: " Text="{Binding Palette.User.Name, ElementName=paletteItem}" Foreground="White"/>-->
             </TextBlock>
             </TextBlock>
         </StackPanel>
         </StackPanel>
         <ItemsControl Margin="0 0 0 0" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding ElementName=paletteItem, Path=Palette.Colors}">
         <ItemsControl Margin="0 0 0 0" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding ElementName=paletteItem, Path=Palette.Colors}">
@@ -47,7 +47,7 @@
         </Button>
         </Button>
         <StackPanel Grid.Row="2" Margin="0 10 0 0" Orientation="Horizontal">
         <StackPanel Grid.Row="2" Margin="0 10 0 0" Orientation="Horizontal">
             <TextBlock Text="Tags: " Foreground="Gray"/>
             <TextBlock Text="Tags: " Foreground="Gray"/>
-            <ItemsControl  ItemsSource="{Binding ElementName=paletteItem, Path=Palette.Tags}">
+            <ItemsControl ItemsSource="{Binding ElementName=paletteItem, Path=Palette.Tags}">
                 <ItemsControl.ItemsPanel>
                 <ItemsControl.ItemsPanel>
                     <ItemsPanelTemplate>
                     <ItemsPanelTemplate>
                         <StackPanel Orientation="Horizontal"/>
                         <StackPanel Orientation="Horizontal"/>

+ 57 - 7
PixiEditor/Views/UserControls/Palettes/PaletteViewer.xaml.cs

@@ -1,4 +1,5 @@
-using System.Linq;
+using System.IO;
+using System.Linq;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls;
@@ -6,6 +7,7 @@ using System.Windows.Input;
 using Microsoft.Win32;
 using Microsoft.Win32;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders.Palettes;
 using PixiEditor.Models.DataHolders.Palettes;
+using PixiEditor.Models.DataProviders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO.JascPalFile;
 using PixiEditor.Models.IO.JascPalFile;
 using PixiEditor.Views.Dialogs;
 using PixiEditor.Views.Dialogs;
@@ -49,6 +51,51 @@ namespace PixiEditor.Views.UserControls.Palettes
         public static readonly DependencyProperty ImportPaletteCommandProperty =
         public static readonly DependencyProperty ImportPaletteCommandProperty =
             DependencyProperty.Register("ImportPaletteCommand", typeof(ICommand), typeof(PaletteViewer));
             DependencyProperty.Register("ImportPaletteCommand", typeof(ICommand), typeof(PaletteViewer));
 
 
+        public WpfObservableRangeCollection<PaletteListDataSource> DataSources
+        {
+            get { return (WpfObservableRangeCollection<PaletteListDataSource>)GetValue(DataSourcesProperty); }
+            set { SetValue(DataSourcesProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for DataSources.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty DataSourcesProperty =
+            DependencyProperty.Register("DataSources", typeof(WpfObservableRangeCollection<PaletteListDataSource>), typeof(PaletteViewer), new PropertyMetadata(new WpfObservableRangeCollection<PaletteListDataSource>()));
+
+        public WpfObservableRangeCollection<PaletteFileParser> FileParsers
+        {
+            get { return (WpfObservableRangeCollection<PaletteFileParser>)GetValue(FileParsersProperty); }
+            set { SetValue(FileParsersProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for FileParsers.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty FileParsersProperty =
+            DependencyProperty.Register("FileParsers", typeof(WpfObservableRangeCollection<PaletteFileParser>), typeof(PaletteViewer), new PropertyMetadata(new WpfObservableRangeCollection<PaletteFileParser>()));
+
+        private string _filesFilter;
+
+        public string FilesFilter
+        {
+            get
+            {
+                if(_filesFilter == null)
+                {
+                    string filter = "";
+
+                    foreach (var parser in FileParsers)
+                    {
+                        string supportedFormats = string.Join(';', parser.SupportedFileExtensions);
+                        filter += $"{parser.FileName} ({supportedFormats})|{supportedFormats}|";
+                    }
+                    
+                    _filesFilter = filter.Remove(filter.Length - 1);
+                }
+
+                return _filesFilter;
+            }
+            set => _filesFilter = value;
+        }
+
+
         private PaletteList _cachedPaletteList;
         private PaletteList _cachedPaletteList;
 
 
         public PaletteViewer()
         public PaletteViewer()
@@ -70,7 +117,7 @@ namespace PixiEditor.Views.UserControls.Palettes
         {
         {
             OpenFileDialog openFileDialog = new OpenFileDialog
             OpenFileDialog openFileDialog = new OpenFileDialog
             {
             {
-                Filter = "Palette (*.pal)|*.pal"
+                Filter = FilesFilter
             };
             };
             if (openFileDialog.ShowDialog() == true)
             if (openFileDialog.ShowDialog() == true)
             {
             {
@@ -80,22 +127,24 @@ namespace PixiEditor.Views.UserControls.Palettes
 
 
         private async Task ImportPalette(string fileName)
         private async Task ImportPalette(string fileName)
         {
         {
-            var jascData = await JascFileParser.ParseFile(fileName);
+            var parser = FileParsers.FirstOrDefault(x => x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+            var data = await parser.Parse(fileName);
             Colors.Clear();
             Colors.Clear();
-            Colors.AddRange(jascData.Colors);
+            Colors.AddRange(data.Colors);
         }
         }
 
 
         private async void SavePalette_OnClick(object sender, RoutedEventArgs e)
         private async void SavePalette_OnClick(object sender, RoutedEventArgs e)
         {
         {
             SaveFileDialog saveFileDialog = new SaveFileDialog
             SaveFileDialog saveFileDialog = new SaveFileDialog
             {
             {
-                Filter = "Palette (*.pal)|*.pal"
+                Filter = FilesFilter
             };
             };
 
 
             if (saveFileDialog.ShowDialog() == true)
             if (saveFileDialog.ShowDialog() == true)
             {
             {
                 string fileName = saveFileDialog.FileName;
                 string fileName = saveFileDialog.FileName;
-                await JascFileParser.SaveFile(fileName, new PaletteFileData(Colors.ToArray()));
+                var foundParser = FileParsers.First(x => x.SupportedFileExtensions.Contains(Path.GetExtension(fileName)));
+                await foundParser.Save(fileName, new PaletteFileData(Colors.ToArray()));
             }
             }
         }
         }
 
 
@@ -171,7 +220,8 @@ namespace PixiEditor.Views.UserControls.Palettes
             PalettesBrowser browser = new PalettesBrowser
             PalettesBrowser browser = new PalettesBrowser
             {
             {
                 Owner = Application.Current.MainWindow,
                 Owner = Application.Current.MainWindow,
-                ImportPaletteCommand = this.ImportPaletteCommand
+                ImportPaletteCommand = this.ImportPaletteCommand,
+                PaletteListDataSources = DataSources,
             };
             };
 
 
             if(_cachedPaletteList != null)
             if(_cachedPaletteList != null)