<commit_before>﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using DereTore.Applications.StarlightDirector.Components;
using DereTore.Applications.StarlightDirector.Entities;
using DereTore.Applications.StarlightDirector.Extensions;

namespace DereTore.Applications.StarlightDirector.UI.Controls {
    /// <summary>
    /// ScoreEditor.xaml 的交互逻辑
    /// </summary>
    partial class ScoreEditor {

        private void FrameLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            var path = FrameLayer.Children[0] as Path;
            Debug.Assert(path != null, "path != null");
            var rectGeom = path.Data as RectangleGeometry;
            Debug.Assert(rectGeom != null, "rectGeom != null");
            var rect = new Rect(new Point(), e.NewSize);
            rectGeom.Rect = rect;
        }

        private void BarLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            ResizeBars();
            RepositionBars();
        }

        private void LineLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            // Wait until NoteLayer_OnSizeChanged(). See the notes in that one.
        }

        private void AvatarLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            RepositionAvatars();
            RepositionAvatarLine();
        }

        private void NoteLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            RepositionNotes();
            // We have to be sure the lines reposition after the notes did.
            RepositionLines();
        }

        private void WorkingAreaClip_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            var clip = WorkingAreaClip.Clip as RectangleGeometry;
            if (clip == null) {
                clip = new RectangleGeometry();
                WorkingAreaClip.Clip = clip;
            }
            var rect = new Rect();
            rect.Y = e.NewSize.Height * BaseLineYPosition;
            rect.Height = e.NewSize.Height - rect.Y - rect.Y;
            rect.Width = e.NewSize.Width;
            clip.Rect = rect;
            var definition = WorkingAreaUpperHalf.RowDefinitions[0];
            Debug.Assert(definition != null, "definition != null");
            definition.Height = new GridLength(rect.Y);
        }

        private void ScoreEditor_OnMouseWheel(object sender, MouseWheelEventArgs e) {
            double change;
            if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) {
                change = LargeChange;
            } else {
                change = SmallChange;
            }
            var targetOffset = ScrollOffset + change * (e.Delta < 0 ? -1 : 1);
            targetOffset = -MathHelper.Clamp(-targetOffset, MinimumScrollOffset, MaximumScrollOffset);
            if (!targetOffset.Equals(ScrollOffset)) {
                ScrollOffset = targetOffset;
            }
        }

        private void ScoreBar_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
            var scoreBar = (ScoreBar)sender;
            var hitTestInfo = scoreBar.HitTest(e.GetPosition(scoreBar));
            AddScoreNote(scoreBar, hitTestInfo, null);
            e.Handled = true;
        }

        private void ScoreBar_ScoreBarHitTest(object sender, ScoreBarHitTestEventArgs e) {
            Debug.Print($"row: {e.Info.Row}, col: {e.Info.Column}");
        }

        private void ScoreBar_MouseDown(object sender, MouseButtonEventArgs e) {
            SelectScoreBar(sender as ScoreBar);
            UnselectAllScoreNotes();
            e.Handled = true;
        }

        private void ScoreNote_MouseDown(object sender, MouseButtonEventArgs e) {
            var scoreNote = (ScoreNote)sender;
            if (scoreNote.IsSelected) {
                scoreNote.IsSelected = EditMode != EditMode.Select;
            } else {
                scoreNote.IsSelected = true;
            }
            var hitPosition = e.GetPosition(BarLayer);
            var scoreBarIndex = (int)((ScrollOffset + hitPosition.Y) / BarHeight);
            SelectScoreBar(ScoreBars[scoreBarIndex]);
            if (scoreNote.IsSelected && EditMode != EditMode.Select && EditMode != EditMode.Clear) {
                switch (EditMode) {
                    case EditMode.Sync:
                        EditingLine.Stroke = SyncRelationBrush;
                        break;
                    case EditMode.Flick:
                        EditingLine.Stroke = FlickRelationBrush;
                        break;
                    case EditMode.Hold:
                        EditingLine.Stroke = HoldRelationBrush;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(EditMode));
                }
                EditingLine.X1 = EditingLine.X2 = scoreNote.X;
                EditingLine.Y1 = EditingLine.Y2 = scoreNote.Y;
                EditingLine.Visibility = Visibility.Visible;
            }
            var note = scoreNote.Note;
            var barIndex = note.Bar.Index;
            var row = note.PositionInGrid;
            var column = (int)note.FinishPosition - 1;
            Debug.Print($"Note @ bar#{barIndex}, row={row}, column={column}");
            DraggingStartNote = scoreNote;<commit_msg>Fixed rare crash when finding the clicked ScoreBar.<commit_after>﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using DereTore.Applications.StarlightDirector.Components;
using DereTore.Applications.StarlightDirector.Entities;
using DereTore.Applications.StarlightDirector.Extensions;

namespace DereTore.Applications.StarlightDirector.UI.Controls {
    /// <summary>
    /// ScoreEditor.xaml 的交互逻辑
    /// </summary>
    partial class ScoreEditor {

        private void FrameLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            var path = FrameLayer.Children[0] as Path;
            Debug.Assert(path != null, "path != null");
            var rectGeom = path.Data as RectangleGeometry;
            Debug.Assert(rectGeom != null, "rectGeom != null");
            var rect = new Rect(new Point(), e.NewSize);
            rectGeom.Rect = rect;
        }

        private void BarLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            ResizeBars();
            RepositionBars();
        }

        private void LineLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            // Wait until NoteLayer_OnSizeChanged(). See the notes in that one.
        }

        private void AvatarLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            RepositionAvatars();
            RepositionAvatarLine();
        }

        private void NoteLayer_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            RepositionNotes();
            // We have to be sure the lines reposition after the notes did.
            RepositionLines();
        }

        private void WorkingAreaClip_OnSizeChanged(object sender, SizeChangedEventArgs e) {
            var clip = WorkingAreaClip.Clip as RectangleGeometry;
            if (clip == null) {
                clip = new RectangleGeometry();
                WorkingAreaClip.Clip = clip;
            }
            var rect = new Rect();
            rect.Y = e.NewSize.Height * BaseLineYPosition;
            rect.Height = e.NewSize.Height - rect.Y - rect.Y;
            rect.Width = e.NewSize.Width;
            clip.Rect = rect;
            var definition = WorkingAreaUpperHalf.RowDefinitions[0];
            Debug.Assert(definition != null, "definition != null");
            definition.Height = new GridLength(rect.Y);
        }

        private void ScoreEditor_OnMouseWheel(object sender, MouseWheelEventArgs e) {
            double change;
            if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) {
                change = LargeChange;
            } else {
                change = SmallChange;
            }
            var targetOffset = ScrollOffset + change * (e.Delta < 0 ? -1 : 1);
            targetOffset = -MathHelper.Clamp(-targetOffset, MinimumScrollOffset, MaximumScrollOffset);
            if (!targetOffset.Equals(ScrollOffset)) {
                ScrollOffset = targetOffset;
            }
        }

        private void ScoreBar_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
            var scoreBar = (ScoreBar)sender;
            var hitTestInfo = scoreBar.HitTest(e.GetPosition(scoreBar));
            AddScoreNote(scoreBar, hitTestInfo, null);
            e.Handled = true;
        }

        private void ScoreBar_ScoreBarHitTest(object sender, ScoreBarHitTestEventArgs e) {
            Debug.Print($"row: {e.Info.Row}, col: {e.Info.Column}");
        }

        private void ScoreBar_MouseDown(object sender, MouseButtonEventArgs e) {
            SelectScoreBar(sender as ScoreBar);
            UnselectAllScoreNotes();
            e.Handled = true;
        }

        private void ScoreNote_MouseDown(object sender, MouseButtonEventArgs e) {
            var scoreNote = (ScoreNote)sender;
            if (scoreNote.IsSelected) {
                scoreNote.IsSelected = EditMode != EditMode.Select;
            } else {
                scoreNote.IsSelected = true;
            }
            var hitPosition = e.GetPosition(BarLayer);
            var hitResult = VisualTreeHelper.HitTest(BarLayer, hitPosition);
            var visual = hitResult.VisualHit as FrameworkElement;
            ScoreBar hitScoreBar = null;
            while (visual != null) {
                if (visual is ScoreBar) {
                    hitScoreBar = visual as ScoreBar;
                    break;
                }
                visual = visual.Parent as FrameworkElement;
            }
            SelectScoreBar(hitScoreBar);
            if (scoreNote.IsSelected && EditMode != EditMode.Select && EditMode != EditMode.Clear) {
                switch (EditMode) {
                    case EditMode.Sync:
                        EditingLine.Stroke = SyncRelationBrush;
                        break;
                    case EditMode.Flick:
                        EditingLine.Stroke = FlickRelationBrush;
                        break;
                    case EditMode.Hold:
                        EditingLine.Stroke = HoldRelationBrush;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(EditMode));
                }
                EditingLine.X1 = EditingLine.X2 = scoreNote.X;
                EditingLine.Y1 = EditingLine.Y2 = scoreNote.Y;
                EditingLine.Visibility = Visibility.Visible;
            }
            var note = scoreNote.Note;
            var barIndex = note.Bar.Index;
            var row = note.PositionInGrid;
            var column = (int)note.FinishPosition - 1;
            Debug.Print($"Note @ bar#{barIndex}, row={row}, column={column}");
            DraggingStartNote = scoreNote;
{'fraction_non_alphanumeric': 0.08638790035587189, 'fraction_numerical': 0.0017793594306049821, 'mean_word_length': 1.9091614906832297, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3229485', 'n_tokens_mistral': 2944, 'n_tokens_neox': 2816, 'n_words': 647}