<!-- Copyright © Northwoods Software Corporation, 2008-2026. All Rights Reserved. -->

<UserControl x:Class="FlowGrammer.FlowGrammer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:go="http://schemas.nwoods.com/GoXam"
    xmlns:local="clr-namespace:FlowGrammer">

  <UserControl.Resources>
    <!-- Converters for when a link or node is dragged over-->
    <go:BooleanBrushConverter x:Key="theStrokeColorConverter"
                              TrueColor="Green" FalseColor="Black" />
    <go:BooleanThicknessConverter x:Key="theStrokeThicknessConverter"
                                  TrueThickness="4" FalseThickness="2" />
    <local:LabelVisibilityConverter x:Key="theLabelVisibilityConverter" />
    <!-- The brushes for nodes -->
    <RadialGradientBrush x:Key="theGreenBrush" GradientOrigin="-0.2,-0.2">
      <GradientStop Color="White" Offset="0.35" />
      <GradientStop Color="Green" Offset="1" />
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="theYellowBrush" GradientOrigin="-0.2,-0.2">
      <GradientStop Color="White" Offset="0.35" />
      <GradientStop Color="Yellow" Offset="1" />
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="theBlueBrush" GradientOrigin="-0.2,-0.2">
      <GradientStop Color="White" Offset="0.35" />
      <GradientStop Color="SteelBlue" Offset="1" />
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="thePinkBrush" GradientOrigin="-0.2,-0.2">
      <GradientStop Color="White" Offset="0.35" />
      <GradientStop Color="Pink" Offset="1" />
    </RadialGradientBrush>
    <RadialGradientBrush x:Key="theRedBrush" GradientOrigin="-0.2,-0.2">
      <GradientStop Color="White" Offset="0.35" />
      <GradientStop Color="Red" Offset="1" />
    </RadialGradientBrush>

    <Style TargetType="go:SpotPanel" x:Key="SpotPanelStyle">
      <Setter Property="go:Part.SelectionAdorned" Value="True" />
      <Setter Property="go:Node.LocationSpot" Value="Center" />
      <Setter Property="go:Part.Movable" Value="False" />
    </Style>


    <!-- For the primary shape of each node -->
    <Style TargetType="go:NodeShape" x:Key="NodeShapeStyle">
      <Setter Property="Fill">
        <Setter.Value>
          <RadialGradientBrush GradientOrigin="-0.2,-0.2">
            <GradientStop Color="White" Offset="0.35" />
            <GradientStop Color="SkyBlue" Offset="1" />
          </RadialGradientBrush>
        </Setter.Value>
      </Setter>
    </Style>

    <!-- For the text of each node -->
    <Style TargetType="TextBlock" x:Key="TextBlockStyle">
      <Setter Property="TextWrapping" Value="Wrap" />
      <Setter Property="TextAlignment" Value="Center" />
      <Setter Property="VerticalAlignment" Value="Center" />
      <Setter Property="HorizontalAlignment" Value="Center" />
      <Setter Property="Margin" Value="5" />
      <Setter Property="go:Part.TextEditable" Value="True" />
    </Style>
    
    <!-- For the ports of each node -->
    <Style TargetType="Rectangle" x:Key="RectangleStyle">
      <Setter Property="Width" Value="7" />
      <Setter Property="Height" Value="7" />
      <Setter Property="Fill" Value="Transparent" />
      <Setter Property="go:Node.LinkableFrom" Value="False" />
      <Setter Property="go:Node.LinkableTo" Value="False" />
    </Style>

    <!-- The DataTemplateDictionary used to store all the
         DataTemplates for the Node categories. -->
    <go:DataTemplateDictionary x:Key="NodeTemplateDictionary">
      <!-- There is a separate DataTemplate for each Node category.
         This allows for large differences between categories
         while keeping each template small and simple. -->
      <DataTemplate x:Key="Start">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}"
                    go:Part.Deletable="False">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                      go:NodePanel.Figure="Circle"
                      Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                      Opacity="1"
                      Fill="{StaticResource theGreenBrush}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                   Text="{Binding Path=Data.Text, Mode=TwoWay}"
                   MinHeight="17"
                   MinWidth="17"
                   go:Part.TextEditable="False" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="BottomPort"
                   go:Node.FromSpot="MiddleBottom"
                   go:SpotPanel.Spot="MiddleBottom"
                   go:SpotPanel.Alignment="MiddleBottom" />
        </go:SpotPanel>
      </DataTemplate>

      <DataTemplate x:Key="If">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                        go:NodePanel.Figure="Diamond"
                        Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                        StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                        Opacity="{Binding Path=Data.Opacity}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                     Text="{Binding Path=Data.Text, Mode=TwoWay}" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="RightPort"
                   go:Node.FromSpot="MiddleRight"
                   go:SpotPanel.Spot="MiddleRight"
                   go:SpotPanel.Alignment="MiddleRight" />
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="LeftPort"
                   go:Node.FromSpot="MiddleLeft"
                   go:SpotPanel.Spot="MiddleLeft"
                   go:SpotPanel.Alignment="MiddleLeft" />
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="TopPort"
                   go:Node.ToSpot="MiddleTop"
                   go:SpotPanel.Spot="MiddleTop"
                   go:SpotPanel.Alignment="MiddleTop" />
        </go:SpotPanel>
      </DataTemplate>

      <DataTemplate x:Key="Action">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                      go:NodePanel.Figure="Rectangle" 
                      Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                      Opacity="{Binding Path=Data.Opacity}"
                      Fill="{StaticResource theYellowBrush}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                   Text="{Binding Path=Data.Text, Mode=TwoWay}"
                   MinWidth="65"
                   go:Part.TextEditable="True" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="TopPort"
                   go:Node.ToSpot="MiddleTop"
                   go:SpotPanel.Spot="MiddleTop"
                   go:SpotPanel.Alignment="MiddleTop" />
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="BottomPort"
                   go:Node.FromSpot="MiddleBottom"
                   go:SpotPanel.Spot="MiddleBottom"
                   go:SpotPanel.Alignment="MiddleBottom" />
        </go:SpotPanel>
      </DataTemplate>

      <DataTemplate x:Key="Effect">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                      go:NodePanel.Figure="Rectangle" 
                      Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                      Opacity="{Binding Path=Data.Opacity}"
                      Fill="{StaticResource theBlueBrush}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                   Text="{Binding Path=Data.Text, Mode=TwoWay}"
                   MinWidth="65"
                   go:Part.TextEditable="True" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="TopPort"
                   go:Node.ToSpot="MiddleTop"
                   go:SpotPanel.Spot="MiddleTop"
                   go:SpotPanel.Alignment="MiddleTop" />
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="BottomPort"
                   go:Node.FromSpot="MiddleBottom"
                   go:SpotPanel.Spot="MiddleBottom"
                   go:SpotPanel.Alignment="MiddleBottom" />
        </go:SpotPanel>
      </DataTemplate>

      <DataTemplate x:Key="Output">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                      go:NodePanel.Figure="RoundedRectangle" 
                      Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                      Opacity="{Binding Path=Data.Opacity}"
                      Fill="{StaticResource thePinkBrush}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                   Text="{Binding Path=Data.Text, Mode=TwoWay}"
                   MinWidth="65"
                   go:Part.TextEditable="True" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="TopPort"
                   go:Node.ToSpot="MiddleTop"
                   go:SpotPanel.Spot="MiddleTop"
                   go:SpotPanel.Alignment="MiddleTop" />
        </go:SpotPanel>
      </DataTemplate>

      <DataTemplate x:Key="End">
        <go:SpotPanel Style="{StaticResource SpotPanelStyle}"
                    go:Node.Location="{Binding Path=Data.Location, Mode=TwoWay}"
                    go:Part.Deletable="False">
          <go:NodePanel Sizing="Auto" go:SpotPanel.Main="True">
            <go:NodeShape x:Name="Shape" Style="{StaticResource NodeShapeStyle}"
                      go:NodePanel.Figure="StopSign"
                      Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}"
                      Opacity="1"
                      Fill="{StaticResource theRedBrush}" />
            <TextBlock Style="{StaticResource TextBlockStyle}"
                   Text="{Binding Path=Data.Text, Mode=TwoWay}"
                   MinHeight="17"
                   MinWidth="17"
                   go:Part.TextEditable="False" />
          </go:NodePanel>
          <Rectangle Style="{StaticResource RectangleStyle}"
                   go:Node.PortId="TopPort"
                   go:Node.ToSpot="MiddleTop"
                   go:SpotPanel.Spot="MiddleTop"
                   go:SpotPanel.Alignment="MiddleTop" />
        </go:SpotPanel>
      </DataTemplate>
    </go:DataTemplateDictionary>

    <!-- A fairly standard LinkTemplate with AvoidsNodes routing,
         a JumpOver curve, and a slight curviness.
         It has a polygon shaped like an arrowhead and a label. -->
    <DataTemplate x:Key="LinkTemplate">
      <go:LinkPanel go:Part.Selectable="False">
        <go:Link.Route>
          <go:Route Routing="AvoidsNodes" Curve="JumpOver" Corner="10" Curviness="10" />
        </go:Link.Route>
        <Path Fill="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
              go:LinkPanel.ToArrow="Standard" go:LinkPanel.ToArrowScale="1.5" />
        <go:LinkShape Stroke="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeColorConverter}}"
                      StrokeThickness="{Binding Path=Data.Highlight, Converter={StaticResource theStrokeThicknessConverter}}" />
        <TextBlock Text="False"
                   go:LinkPanel.Index="0"
                   go:LinkPanel.Offset="10 10"
                   go:LinkPanel.Orientation="Upright"
                   Visibility="{Binding Path=Link,
                                Converter={StaticResource theLabelVisibilityConverter}}" />
      </go:LinkPanel>
    </DataTemplate>
  </UserControl.Resources>

  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="100" />
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <!-- The palette of nodes that can be dragged onto the main diagram -->
    <go:Palette Grid.Column="0" x:Name="myPalette" 
                Padding="5" Margin="2" BorderBrush="Black" BorderThickness="1"
                NodeTemplateDictionary="{StaticResource NodeTemplateDictionary}"
                MaximumSelectionCount="1">
      <go:Palette.Layout>
        <go:GridLayout Sorting="Forward" Alignment="Position" CellSize="5 5" Spacing="5 5" />
      </go:Palette.Layout>
    </go:Palette>

    <GridSplitter Grid.Column="1" Width="5"
                  HorizontalAlignment="Center" VerticalAlignment="Stretch" />

    <!-- The editable diagram; uses a LayeredDigraphLayout to deal with formatting
         when new nodes are dragged in-->
    <Grid Grid.Column="2">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
      </Grid.RowDefinitions>

      <TextBlock Grid.Row="0" Padding="5"
               Text="Drag nodes from left onto the links or nodes of the diagram to insert them." />
      <go:Diagram Grid.Row="1" x:Name="myDiagram"
                Padding="10"
                VerticalContentAlignment="Stretch"
                HorizontalContentAlignment="Stretch"
                NodeTemplateDictionary="{StaticResource NodeTemplateDictionary}"
                LinkTemplate="{StaticResource LinkTemplate}">
        <go:Diagram.Layout>
          <go:LayeredDigraphLayout Direction="90" SetsPortSpots="False" LayerSpacing="30" />
        </go:Diagram.Layout>
      </go:Diagram>
      <StackPanel Grid.Row="1" Orientation="Horizontal"
                HorizontalAlignment="Right" VerticalAlignment="Top">
        <Button Content="Save" Click="Save_Click" />
        <Button Content="Load" Click="Load_Click" x:Name="LoadButton" IsEnabled="False" />
      </StackPanel>
    </Grid>
  </Grid>
</UserControl>
