Skip to content

Commit

Permalink
Merge pull request #991 from b-editor/patch-3
Browse files Browse the repository at this point in the history
タイムライン/要素操作の改善
  • Loading branch information
yuto-trd authored Jun 24, 2024
2 parents b64e72f + 2134f93 commit 12063f5
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 180 deletions.
6 changes: 6 additions & 0 deletions src/Beutl.Language/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Beutl.Language/Strings.ja.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1216,4 +1216,7 @@ b-editorがダウンロードURLを管理します。</value>
<data name="ClipTransparentArea" xml:space="preserve">
<value>透明部分をクリップ</value>
</data>
<data name="EnableElement" xml:space="preserve">
<value>要素を有効化</value>
</data>
</root>
3 changes: 3 additions & 0 deletions src/Beutl.Language/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1216,4 +1216,7 @@ and b-editor maintains the download URL.</value>
<data name="ClipTransparentArea" xml:space="preserve">
<value>Clip transparent area</value>
</data>
<data name="EnableElement" xml:space="preserve">
<value>Enable element</value>
</data>
</root>
6 changes: 2 additions & 4 deletions src/Beutl/ViewModels/ElementViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,9 @@ public ElementViewModel(Element element, TimelineViewModel timeline)
{
LayerHeaderViewModel? newLH = Timeline.LayerHeaders.FirstOrDefault(i => i.Number.Value == number);

if (LayerHeader.Value != null)
LayerHeader.Value.ItemsCount.Value--;
LayerHeader.Value?.ElementRemoved(this);

if (newLH != null)
newLH.ItemsCount.Value++;
newLH?.ElementAdded(this);
LayerHeader.Value = newLH;
})
.AddTo(_disposables);
Expand Down
89 changes: 66 additions & 23 deletions src/Beutl/ViewModels/LayerHeaderViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using System.Collections.Specialized;
using System.Text.Json.Nodes;

using Avalonia.Media;

using Beutl.Commands;
using Beutl.ProjectSystem;
using Beutl.Reactive;

using Reactive.Bindings;
using Reactive.Bindings.Extensions;

Expand All @@ -15,6 +12,9 @@ namespace Beutl.ViewModels;
public sealed class LayerHeaderViewModel : IDisposable, IJsonSerializable
{
private readonly CompositeDisposable _disposables = [];
private readonly List<ElementViewModel> _elements = [];
private IDisposable? _elementsSubscription;
private bool _skipSubscription;

public LayerHeaderViewModel(int num, TimelineViewModel timeline)
{
Expand All @@ -26,30 +26,40 @@ public LayerHeaderViewModel(int num, TimelineViewModel timeline)
.ToReadOnlyReactivePropertySlim()
.DisposeWith(_disposables);

IsEnabled.Skip(1).Subscribe(b =>
{
CommandRecorder recorder = Timeline.EditorContext.CommandRecorder;
Timeline.Scene.Children.Where(i => i.ZIndex == Number.Value && i.IsEnabled != b)
.Select(item => RecordableCommands.Edit(item, Element.IsEnabledProperty, b).WithStoables([item]))
.ToArray()
.ToCommand()
.DoAndRecord(recorder);
}).DisposeWith(_disposables);
SwitchEnabledCommand = new ReactiveCommand()
.WithSubscribe(() =>
{
CommandRecorder recorder = Timeline.EditorContext.CommandRecorder;
try
{
_skipSubscription = true;
IsEnabled.Value = !IsEnabled.Value;
Timeline.Scene.Children.Where(i => i.ZIndex == Number.Value && i.IsEnabled != IsEnabled.Value)
.Select(item => RecordableCommands.Edit(item, Element.IsEnabledProperty, IsEnabled.Value).WithStoables([item]))
.ToArray()
.ToCommand()
.DoAndRecord(recorder);
}
finally
{
_skipSubscription = false;
}
});

Height.Subscribe(_ => Timeline.RaiseLayerHeightChanged(this)).DisposeWith(_disposables);

Inlines.ForEachItem(
(idx, x) =>
{
Height.Value += FrameNumberHelper.LayerHeight;
x.Index.Value = idx;
},
(_, x) =>
{
Height.Value -= FrameNumberHelper.LayerHeight;
x.Index.Value = -1;
},
() => { })
(idx, x) =>
{
Height.Value += FrameNumberHelper.LayerHeight;
x.Index.Value = idx;
},
(_, x) =>
{
Height.Value -= FrameNumberHelper.LayerHeight;
x.Index.Value = -1;
},
() => { })
.DisposeWith(_disposables);

Inlines.CollectionChangedAsObservable()
Expand Down Expand Up @@ -118,6 +128,8 @@ void OnRemoved()

public CoreList<InlineAnimationLayerViewModel> Inlines { get; } = new() { ResetBehavior = ResetBehavior.Remove };

public ReactiveCommand SwitchEnabledCommand { get; }

public void AnimationRequest(int layerNum, bool affectModel = true)
{
if (affectModel)
Expand All @@ -127,6 +139,37 @@ public void AnimationRequest(int layerNum, bool affectModel = true)
PosY.Value = 0;
}

public void ElementAdded(ElementViewModel element)
{
ItemsCount.Value++;
_elements.Add(element);
BuildSubscription();
}

public void ElementRemoved(ElementViewModel element)
{
ItemsCount.Value--;
_elements.Remove(element);
BuildSubscription();
}

private void BuildSubscription()
{
_elementsSubscription?.Dispose();
_elementsSubscription = null;
if (_elements.Count == 0)
{
IsEnabled.Value = true;
return;
}

_elementsSubscription = _elements.Select(obj => obj.IsEnabled.Select(b => (bool?)b))
.Aggregate((x, y) => x.CombineLatest(y)
.Select(t => t.First == t.Second ? t.First : null))
.Where(b => b.HasValue && !_skipSubscription)
.Subscribe(b => IsEnabled.Value = b!.Value);
}

public void Dispose()
{
_disposables.Dispose();
Expand Down
20 changes: 19 additions & 1 deletion src/Beutl/Views/ElementView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,25 @@
x:DataType="vm:ElementViewModel"
ClipToBounds="True"
Focusable="True"
IsEnabled="{CompiledBinding IsEnabled.Value}"
mc:Ignorable="d">
<Border x:Name="border"
Width="{Binding Width.Value}"
Margin="{Binding BorderMargin.Value}"
HorizontalAlignment="Left"
Background="{Binding Color.Value, Converter={StaticResource ColorToBrushConverter}}"
BorderThickness="1"
Classes.elm-disabled="{Binding !IsEnabled.Value}"
Classes.selected="{Binding IsSelected.Value}">
<Border.Styles>
<Style Selector="Border:pressed">
<Setter Property="Opacity" Value="0.8" />
</Style>
<Style Selector="Border.elm-disabled">
<Setter Property="Opacity" Value="0.5" />
</Style>
<Style Selector="Border.elm-disabled:pressed">
<Setter Property="Opacity" Value="0.4" />
</Style>
<Style Selector="Border.selected">
<Setter Property="BorderBrush" Value="{DynamicResource TextControlForeground}" />
</Style>
Expand All @@ -38,6 +47,15 @@
</Border.Styles>
<Border.ContextFlyout>
<ui:FAMenuFlyout>
<ui:ToggleMenuFlyoutItem Click="EnableElementClick"
IsChecked="{Binding IsEnabled.Value}"
Text="{x:Static lang:Strings.EnableElement}">
<ui:ToggleMenuFlyoutItem.Styles>
<Style Selector="ui|ToggleMenuFlyoutItem /template/ Viewbox#IconRoot">
<Setter Property="Width" Value="0" />
</Style>
</ui:ToggleMenuFlyoutItem.Styles>
</ui:ToggleMenuFlyoutItem>
<ui:MenuFlyoutItem Command="{Binding Split}" Text="{x:Static lang:Strings.Split}">
<ui:MenuFlyoutItem.IconSource>
<icons:SymbolIconSource Symbol="SplitVertical" />
Expand Down
Loading

0 comments on commit 12063f5

Please sign in to comment.