Zum Inhalt
Kuonen.UI

Gesten

Die Gestenschicht: eine Karte lässt sich mit einem Finger verschieben (mit Trägheit) und mit zwei Fingern skalieren und drehen; Tippen, Doppeltippen und Wischen werden gemeldet. Mit „Maus erlaubt“ verschiebt auch die Maus.

Vorführung: GestenVorführung: Gesten

KXAML

GestenSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.GestenVorfuehrung"
            Spacing="12">
  <!-- Das Innere (Einträge, Kopplungen, Ereignisse) baut GestenSeite.Fuelle, dieselbe Methode wie die C#-Fassung. -->
  <CheckBox x:Name="Maus" Content="Maus erlaubt" />
  <Canvas x:Name="Flaeche" Width="360" Height="220" />
  <TextBlock x:Name="Meldung" Text="Noch keine Geste." />
</StackPanel>
GestenSeite.kxaml.cs
using Kuonen.UI;

namespace Kuonen.UI.Galerie.Seiten;

public sealed partial class GestenSeite
{
    protected override Func<UIElement>? KxamlFabrik => () => new GestenVorfuehrung();
}

/// <summary>KXAML-Fassung der Seite Gesten: das Gerüst steht in GestenSeite.kxaml, das Innere füllt GestenSeite.Fuelle.</summary>
public sealed partial class GestenVorfuehrung
{
    public GestenVorfuehrung()
    {
        InitializeComponent();
        GestenSeite.Fuelle(Maus, Flaeche, Meldung);
    }
}

C#

GestenSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Eingabe;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: Gesten (Plan 6f).</summary>
public sealed partial class GestenSeite : GalerieSeite
{
    public override string Titel => "Gesten";

    public override string Beschreibung =>
        "Die Gestenschicht: eine Karte lässt sich mit einem Finger verschieben (mit Trägheit) und mit zwei Fingern skalieren und drehen; Tippen, Doppeltippen und Wischen werden gemeldet. Mit „Maus erlaubt“ verschiebt auch die Maus.";

    public override string Stichworte => "Gesten Manipulation Kneifen Pinch Drehen Rotate Trägheit Inertia Tippen Tapped DoubleTapped Wischen Swipe";

    public override string Datei => nameof(GestenSeite);

    public override UIElement Baue()
    {
        var seite = new StackPanel { Spacing = 12 };
        var maus = new CheckBox { Content = "Maus erlaubt" };
        var flaeche = new Canvas { Width = 360, Height = 220 };
        var meldung = new TextBlock { Text = "Noch keine Geste." };
        Fuelle(maus, flaeche, meldung);
        seite.Children.Add(maus);
        seite.Children.Add(flaeche);
        seite.Children.Add(meldung);
        return seite;
    }

    /// <summary>Die Karte und ihre Gesten (auch von der KXAML-Fassung benutzt).</summary>
    public static void Fuelle(CheckBox maus, Canvas flaeche, TextBlock meldung)
    {
        flaeche.Background = new SolidColorBrush(Color.FromRgb(0xF0, 0xF0, 0xF0));
        flaeche.ClipToBounds = true;
        var karte = new Border
        {
            Width = 120, Height = 80, Background = new SolidColorBrush(Color.FromRgb(0x90, 0xCA, 0xF9)), ManipulationMode = ManipulationModes.All,
            Child = new TextBlock { Text = "Karte", Margin = new Thickness(12) },
        };
        Canvas.SetLeft(karte, 120);
        Canvas.SetTop(karte, 70);
        flaeche.Children.Add(karte);
        var lage = Matrix.Identity;
        karte.ManipulationDelta += (_, e) =>
        {
            // Um den Schwerpunkt der Finger skalieren und drehen, dann verschieben (in Koordinaten der Fläche).
            var p = e.PositionIn(flaeche);
            var d = e.Delta;
            lage *= Matrix.CreateTranslation(-p.X, -p.Y) * Matrix.CreateScale(d.Scale, d.Scale) * Matrix.CreateRotation(d.Rotation * Math.PI / 180)
                * Matrix.CreateTranslation(p.X + d.Translation.X, p.Y + d.Translation.Y);
            karte.RenderTransform = Matrix.CreateTranslation(-120, -70) * lage * Matrix.CreateTranslation(120, 70) is var m && double.IsFinite(m.M11) ? m : Matrix.Identity;
        };
        karte.Tapped += (_, _) => meldung.Text = "Getippt.";
        karte.DoubleTapped += (_, _) =>
        {
            lage = Matrix.Identity;
            karte.RenderTransform = Matrix.Identity;
            meldung.Text = "Doppelt getippt: zurückgesetzt.";
        };
        flaeche.Gewischt += (_, e) => meldung.Text = $"Gewischt nach {e.Richtung}.";
        maus.Checked += (_, _) => karte.ManipulationMode = ManipulationModes.All | ManipulationModes.Maus;
        maus.Unchecked += (_, _) => karte.ManipulationMode = ManipulationModes.All;
    }
}