فهرست منبع

Added visibility to group and adjusted style

flabbet 4 سال پیش
والد
کامیت
6ab6dc4b20

BIN
PixiEditor/Images/transparentbg_mini.png


+ 49 - 0
PixiEditor/Models/Controllers/UndoManager.cs

@@ -99,6 +99,55 @@ namespace PixiEditor.Models.Controllers
             UndoStack.Push(change);
         }
 
+        /// <summary>
+        /// Merges multiple undo changes into one.
+        /// </summary>
+        /// <param name="amount">Amount of changes to squash.</param>
+        /// <param name="description">Final change description.</param>
+        public void SquashUndoChanges(int amount, string description)
+        {
+            Change[] changes = new Change[amount];
+            for (int i = 0; i < amount; i++)
+            {
+                changes[i] = UndoStack.Pop();
+            }
+
+            Action<object[]> reverseProcess = (object[] props) =>
+            {
+                foreach (var prop in props)
+                {
+                    Change change = (Change)prop;
+                    if (change.ReverseProcess == null)
+                    {
+                        SetPropertyValue(GetChangeRoot(change), change.Property, change.OldValue);
+                    }
+                    else
+                    {
+                        change.ReverseProcess(change.ReverseProcessArguments);
+                    }
+                }
+            };
+
+            Action<object[]> process = (object[] props) =>
+            {
+                foreach (var prop in props)
+                {
+                    Change change = (Change)prop;
+                    if (change.Process == null)
+                    {
+                        SetPropertyValue(GetChangeRoot(change), change.Property, change.NewValue);
+                    }
+                    else
+                    {
+                        change.Process(change.ProcessArguments);
+                    }
+                }
+            };
+
+            Change change = new Change(reverseProcess, changes, process, changes, description);
+            AddUndoChange(change);
+        }
+
         private bool ChangeIsBlockedProperty(Change change)
         {
             return (change.Root != null || change.FindRootProcess != null)

+ 22 - 22
PixiEditor/Models/ImageManipulation/BitmapUtils.cs

@@ -33,9 +33,9 @@ namespace PixiEditor.Models.ImageManipulation
         /// <summary>
         ///     Converts layers bitmaps into one bitmap.
         /// </summary>
-        /// <param name="layers">Layers to combine.</param>
         /// <param name="width">Width of final bitmap.</param>
         /// <param name="height">Height of final bitmap.</param>.
+        /// <param name="layers">Layers to combine.</param>
         /// <returns>WriteableBitmap of layered bitmaps.</returns>
         public static WriteableBitmap CombineLayers(int width, int height, params Layer[] layers)
         {
@@ -99,32 +99,13 @@ namespace PixiEditor.Models.ImageManipulation
         /// <param name="maxPreviewWidth">Max width of preview.</param>
         /// <param name="maxPreviewHeight">Max height of preview.</param>
         /// <returns>WriteableBitmap image.</returns>
-        public static WriteableBitmap GeneratePreviewBitmap(IEnumerable<Layer> layers, int maxPreviewWidth, int maxPreviewHeight)
+        public static WriteableBitmap GeneratePreviewBitmap(IEnumerable<Layer> layers, int maxPreviewWidth, int maxPreviewHeight, bool showHidden = false)
         {
             int minOffsetX = layers.Min(x => x.OffsetX);
             int minOffsetY = layers.Min(x => x.OffsetY);
             int width = layers.Max(x => x.OffsetX + x.Width) - minOffsetX;
             int height = layers.Max(x => x.OffsetY + x.Height) - minOffsetY;
-            return GeneratePreviewBitmap(layers, maxPreviewWidth, maxPreviewHeight, width, height, minOffsetX, minOffsetY);
-        }
-
-        private static WriteableBitmap GeneratePreviewBitmap(IEnumerable<Layer> layers, int maxPreviewWidth, int maxPreviewHeight, int width, int height, int minOffsetX, int minOffsetY)
-        {
-            WriteableBitmap previewBitmap = BitmapFactory.New(width, height);
-
-            // 0.8 because blit doesn't take into consideration layer opacity. Small images with opacity > 80% are simillar enough.
-            foreach (var layer in layers.Where(x => x.IsVisible && x.Opacity > 0.8f))
-            {
-                previewBitmap.Blit(
-                    new Rect(layer.OffsetX - minOffsetX, layer.OffsetY - minOffsetY, layer.Width, layer.Height),
-                    layer.LayerBitmap,
-                    new Rect(0, 0, layer.Width, layer.Height));
-            }
-
-            int finalWidth = width >= height ? maxPreviewWidth : (int)Math.Ceiling(width / ((float)height / maxPreviewHeight));
-            int finalHeight = height > width ? maxPreviewHeight : (int)Math.Ceiling(height / ((float)width / maxPreviewWidth));
-
-            return previewBitmap.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
+            return GeneratePreviewBitmap(layers, maxPreviewWidth, maxPreviewHeight, width, height, minOffsetX, minOffsetY, showHidden);
         }
 
         public static Dictionary<Guid, Color[]> GetPixelsForSelection(Layer[] layers, Coordinates[] selection)
@@ -155,5 +136,24 @@ namespace PixiEditor.Models.ImageManipulation
 
             return result;
         }
+
+        private static WriteableBitmap GeneratePreviewBitmap(IEnumerable<Layer> layers, int maxPreviewWidth, int maxPreviewHeight, int width, int height, int minOffsetX, int minOffsetY, bool showHidden = false)
+        {
+            WriteableBitmap previewBitmap = BitmapFactory.New(width, height);
+
+            // 0.8 because blit doesn't take into consideration layer opacity. Small images with opacity > 80% are simillar enough.
+            foreach (var layer in layers.Where(x => (x.IsVisible || showHidden) && x.Opacity > 0.8f))
+            {
+                previewBitmap.Blit(
+                    new Rect(layer.OffsetX - minOffsetX, layer.OffsetY - minOffsetY, layer.Width, layer.Height),
+                    layer.LayerBitmap,
+                    new Rect(0, 0, layer.Width, layer.Height));
+            }
+
+            int finalWidth = width >= height ? maxPreviewWidth : (int)Math.Ceiling(width / ((float)height / maxPreviewHeight));
+            int finalHeight = height > width ? maxPreviewHeight : (int)Math.Ceiling(height / ((float)width / maxPreviewWidth));
+
+            return previewBitmap.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
+        }
     }
 }

+ 1 - 24
PixiEditor/Styles/DarkScrollBarStyle.xaml

@@ -123,7 +123,7 @@
                 <ColumnDefinition Width="0.00001*"/>
                 <ColumnDefinition MaxWidth="18"/>
             </Grid.ColumnDefinitions>
-            <Border Grid.ColumnSpan="3" CornerRadius="2" Background="#F0F0F0"/>
+            <Border Grid.ColumnSpan="3" CornerRadius="2" Background="Transparent"/>
             <RepeatButton Grid.Column="0"  Style="{StaticResource ScrollBarLineButton}" Width="18" Command="ScrollBar.LineLeftCommand" Content="M 4 0 L 4 8 L 0 4 Z" />
             <Track Name="PART_Track" Grid.Column="1" IsDirectionReversed="False">
                 <Track.DecreaseRepeatButton>
@@ -156,27 +156,4 @@
         </Style.Triggers>
     </Style>
 
-    <Style x:Key="FavsScrollViewer" TargetType="{x:Type ScrollViewer}">
-        <Setter Property="OverridesDefaultStyle" Value="True"/>
-        <Setter Property="Template">
-            <Setter.Value>
-                <ControlTemplate TargetType="{x:Type ScrollViewer}">
-                    <Grid>
-                        <Grid.ColumnDefinitions>
-                            <ColumnDefinition Width="Auto"/>
-                            <ColumnDefinition/>
-                        </Grid.ColumnDefinitions>
-                        <Grid.RowDefinitions>
-                            <RowDefinition/>
-                            <RowDefinition Height="Auto"/>
-                        </Grid.RowDefinitions>
-                        <ScrollContentPresenter Grid.Column="1"/>
-                        <ScrollBar Name="PART_VerticalScrollBar" Value="{TemplateBinding VerticalOffset}" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
-                        <ScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Value="{TemplateBinding HorizontalOffset}" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
-                    </Grid>
-                </ControlTemplate>
-            </Setter.Value>
-        </Setter>
-    </Style>
-
 </ResourceDictionary>

+ 12 - 19
PixiEditor/Styles/TreeViewStyle.xaml

@@ -9,22 +9,14 @@
         <Setter Property="BorderThickness" Value="0"/>
     </Style>
 
-    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
+    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#3A3A3D"/>
     <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
                       Color="Black" />
     <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
                       Color="Transparent" />
     <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}"
                       Color="Black" />
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF27C7F7"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="#FFCCEEFB"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF1CC4F7"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF82DFFB"/>
     <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="#FFFFFFFF"/>
-    <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF818181"/>
 
     <Style x:Key="TreeViewItemFocusVisual">
         <Setter Property="Control.Template">
@@ -44,7 +36,7 @@
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type ToggleButton}">
                     <Border Width="16" Height="16" Background="Transparent" Padding="5,5,5,5">
-                        <Path x:Name="ExpandPath" Fill="Transparent" Stroke="#FF989898" Data="{StaticResource TreeArrow}">
+                        <Path x:Name="ExpandPath" Fill="White" Stroke="White" Data="{StaticResource TreeArrow}">
                             <Path.RenderTransform>
                                 <RotateTransform Angle="135" CenterX="3" CenterY="3"/>
                             </Path.RenderTransform>
@@ -52,8 +44,8 @@
                     </Border>
                     <ControlTemplate.Triggers>
                         <Trigger Property="IsMouseOver" Value="True">
-                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
-                            <Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
+                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FFA8A8A8"/>
+                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FFA8A8A8"/>
                         </Trigger>
                         <Trigger Property="IsChecked" Value="True">
                             <Setter Property="RenderTransform" TargetName="ExpandPath">
@@ -61,8 +53,6 @@
                                     <RotateTransform Angle="180" CenterX="3" CenterY="3"/>
                                 </Setter.Value>
                             </Setter>
-                            <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>
-                            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
                         </Trigger>
                     </ControlTemplate.Triggers>
                 </ControlTemplate>
@@ -103,17 +93,21 @@
                         <Trigger Property="HasItems" Value="false">
                             <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
                         </Trigger>
-                        <Trigger Property="IsSelected" Value="true">
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="HasItems" Value="True"/>
+                                <Condition Property="IsSelected" Value="True"/>
+                            </MultiTrigger.Conditions>
                             <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                             <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
-                        </Trigger>
+                        </MultiTrigger>
                         <MultiTrigger>
                             <MultiTrigger.Conditions>
                                 <Condition Property="IsSelected" Value="true"/>
                                 <Condition Property="IsSelectionActive" Value="false"/>
                             </MultiTrigger.Conditions>
-                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
-                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
+                            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
+                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
                         </MultiTrigger>
                         <Trigger Property="IsEnabled" Value="false">
                             <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
@@ -126,7 +120,6 @@
 
     <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource TreeViewItemStyle}">
         <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
-        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
         <Setter Property="HorizontalContentAlignment" Value="Stretch" />
     </Style>
 

+ 9 - 4
PixiEditor/Views/UserControls/LayerGroupControl.xaml

@@ -22,14 +22,18 @@
             <Grid AllowDrop="True" DragEnter="Grid_DragEnter" Drop="Grid_Drop_Top" DragLeave="Grid_DragLeave" Grid.Row="0" Grid.ColumnSpan="3" Background="Transparent"/>
             <Grid Grid.Row="0" Grid.RowSpan="3" Margin="5 0 5 0">
                 <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="1*"/>
+                    <ColumnDefinition Width="30"/>
+                    <ColumnDefinition Width="*"/>
                     <ColumnDefinition Width="20"/>
                 </Grid.ColumnDefinitions>
-                <StackPanel Orientation="Horizontal">
-                <Rectangle Width="{Binding Path=(helpers:TreeViewItemHelper.Indent).Value, Mode=OneWay, RelativeSource={RelativeSource AncestorType=ItemsPresenter}}" Fill="Transparent" StrokeThickness="0"/>
+                <CheckBox Style="{StaticResource ImageCheckBox}" VerticalAlignment="Center"
+                      IsThreeState="False" HorizontalAlignment="Center" 
+                      IsChecked="{Binding Path=IsVisibleUndoTriggerable, Mode=TwoWay, ElementName=groupControl}" Grid.Column="0" Height="16" Margin="-10,0,0,0"/>
+                
+                <StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Left">
+                    <Rectangle Width="{Binding Path=(helpers:TreeViewItemHelper.Indent).Value, Mode=OneWay, RelativeSource={RelativeSource AncestorType=ItemsPresenter}}" Fill="Transparent" StrokeThickness="0"/>
                 
                 <StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
-                    <Image Source="/Images/Folder.png" Height="20" Margin="0,0,10,0"/>
                         <Border Width="30" Height="30" BorderThickness="1" BorderBrush="Black" Background="{StaticResource MainColor}"
                            Margin="5, 0, 10, 0">
                             <Image Source="{Binding PreviewImage, ElementName=groupControl}" Stretch="Uniform" Width="20" Height="20" 
@@ -41,6 +45,7 @@
                     IsEditing="{Binding GroupData.IsRenaming, ElementName=groupControl, Mode=TwoWay}"
                     Text="{Binding GroupData.Name, ElementName=groupControl, Mode=TwoWay}" />
                 </StackPanel>
+                    <Image Source="/Images/Folder.png" Height="20" Margin="0,0,10,0" HorizontalAlignment="Right"/>
                 </StackPanel>
             </Grid>
             <Grid DragEnter="Grid_DragEnter" Drop="Grid_Drop_Bottom"  DragLeave="Grid_DragLeave" Grid.Row="2" AllowDrop="{Binding  GroupData.IsExpanded, ElementName=groupControl, Converter={StaticResource InverseBooleanConverter}}" Grid.ColumnSpan="2" Background="Transparent"/>

+ 37 - 6
PixiEditor/Views/UserControls/LayerGroupControl.xaml.cs

@@ -7,6 +7,7 @@ using System.Windows.Media.Imaging;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
+using PixiEditor.Models.Undo;
 using PixiEditor.ViewModels.SubViewModels.Main;
 
 namespace PixiEditor.Views.UserControls
@@ -36,6 +37,36 @@ namespace PixiEditor.Views.UserControls
         public static readonly DependencyProperty LayersViewModelProperty =
             DependencyProperty.Register("LayersViewModel", typeof(LayersViewModel), typeof(LayerGroupControl), new PropertyMetadata(default(LayersViewModel), LayersViewModelCallback));
 
+        public bool IsVisibleUndoTriggerable
+        {
+            get { return (bool)GetValue(IsVisibleUndoTriggerableProperty); }
+            set { SetValue(IsVisibleUndoTriggerableProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for IsVisibleUndoTriggerable.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty IsVisibleUndoTriggerableProperty =
+            DependencyProperty.Register("IsVisibleUndoTriggerable", typeof(bool), typeof(LayerGroupControl), new PropertyMetadata(true, IsVisibleChangedCallback));
+
+        private static void IsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            LayerGroupControl control = (LayerGroupControl)d;
+            var doc = control.LayersViewModel.Owner.BitmapManager.ActiveDocument;
+            var layers = doc.LayerStructure.GetGroupLayers(control.GroupData);
+
+            foreach (var layer in layers)
+            {
+                layer.IsVisible = (bool)e.NewValue;
+            }
+
+            doc.UndoManager.AddUndoChange(
+                new Change(
+                    nameof(IsVisibleUndoTriggerable), 
+                    e.OldValue,
+                    e.NewValue,
+                    $"Change {control.GroupName} visiblity",
+                    control), true);
+        }
+
         private static void LayersViewModelCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
             LayerGroupControl control = (LayerGroupControl)d;
@@ -70,6 +101,12 @@ namespace PixiEditor.Views.UserControls
         public static readonly DependencyProperty GroupDataProperty =
             DependencyProperty.Register("GroupData", typeof(GuidStructureItem), typeof(LayerGroupControl), new PropertyMetadata(default(GuidStructureItem), GroupDataChangedCallback));
 
+        public void GeneratePreviewImage()
+        {
+            var layers = LayersViewModel.Owner.BitmapManager.ActiveDocument.LayerStructure.GetGroupLayers(GroupData);
+            PreviewImage = BitmapUtils.GeneratePreviewBitmap(layers, 25, 25, true);
+        }
+
         private static void GroupDataChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
             ((LayerGroupControl)d).GeneratePreviewImage();
@@ -95,12 +132,6 @@ namespace PixiEditor.Views.UserControls
             GeneratePreviewImage();
         }
 
-        public void GeneratePreviewImage()
-        {
-            var layers = LayersViewModel.Owner.BitmapManager.ActiveDocument.LayerStructure.GetGroupLayers(GroupData);
-            PreviewImage = BitmapUtils.GeneratePreviewBitmap(layers, 25, 25);
-        }
-
         private void Grid_DragEnter(object sender, DragEventArgs e)
         {
             Grid item = sender as Grid;

+ 1 - 3
PixiEditor/Views/UserControls/LayersManager.xaml

@@ -41,8 +41,7 @@
             <Label Content="%" Foreground="White" VerticalAlignment="Center"/>
         </StackPanel>
         <Separator Grid.Row="2" Background="{StaticResource BrighterAccentColor}"/>
-        <ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
-            <TreeView ItemsSource="{Binding LayerTreeRoot, ElementName=layersManager}">
+        <TreeView Grid.Row="3" ItemsSource="{Binding LayerTreeRoot, ElementName=layersManager}">
                 <TreeView.ItemsPanel>
                     <ItemsPanelTemplate>
                         <ui:ReversedOrderStackPanel/>
@@ -60,6 +59,5 @@
                     </DataTemplate>
                 </TreeView.Resources>
             </TreeView>
-        </ScrollViewer>
     </Grid>
 </UserControl>