diff options
Diffstat (limited to 'Samples/PathPainter')
| -rw-r--r-- | Samples/PathPainter/Painter.cs | 203 | ||||
| -rw-r--r-- | Samples/PathPainter/PathPainter.csproj | 7 | ||||
| -rw-r--r-- | Samples/PathPainter/Program.cs | 76 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/Icons/Lines.svg | 7 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/Icons/Rect.svg | 6 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/Icons/Select.svg | 6 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/Painter.style | 3 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/Spinner.template | 14 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/colorSelector.template | 11 | ||||
| -rw-r--r-- | Samples/PathPainter/ui/main.crow | 43 |
10 files changed, 376 insertions, 0 deletions
diff --git a/Samples/PathPainter/Painter.cs b/Samples/PathPainter/Painter.cs new file mode 100644 index 00000000..7e3c97bb --- /dev/null +++ b/Samples/PathPainter/Painter.cs @@ -0,0 +1,203 @@ +using Crow.Cairo; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace Crow +{ + public class Painter : ScrollingObject + { + #region CTOR + protected Painter () { } + public Painter (Interface iface, string style = null) : base (iface, style) { } + #endregion + + public class Point + { + public double X; + public double Y; + } + + public enum DrawMode + { + Select, + Lines, + Rect, + Arc, + } + DrawMode currentDrawMode = DrawMode.Select; + public DrawMode CurrentDrawMode { + get => currentDrawMode; + set { + if (value == currentDrawMode) + return; + currentDrawMode = value; + NotifyValueChanged ("CurrentDrawMode", currentDrawMode); + updateMouseCursor (); + } + } + + void updateMouseCursor () { + if (currentDrawMode == DrawMode.Select) + MouseCursor = MouseCursor.arrow; + else + MouseCursor = MouseCursor.crosshair; + } + + public double[] Zooms => new double[] { 0.5, 1.0, 2.0, 4.0, 8.0, 16.0 }; + + string path; + double strokeWidth; + Size size; + double zoom; + Fill shapeBackground, shapeForeground; + + [DefaultValue(1.0)] + public double Zoom { + get => zoom; + set { + if (zoom == value) + return; + zoom = value; + NotifyValueChangedAuto (zoom); + RegisterForGraphicUpdate (); + updateMaxScrolls (); + } + } + + /// <summary> + /// Path expression, for syntax see 'PathParser'. + /// </summary> + public string Path { + get { return path; } + set { + if (path == value) + return; + path = value; + contentSize = default (Size); + NotifyValueChangedAuto (path); + RegisterForGraphicUpdate (); + } + } + /// <summary> + /// Default stroke width, may be overriden by a 'S' command in the path string. + /// </summary> + /// <value>The width of the stoke.</value> + [DefaultValue (1.0)] + public double StrokeWidth { + get { return strokeWidth; } + set { + if (strokeWidth == value) + return; + strokeWidth = value; + contentSize = default (Size); + NotifyValueChangedAuto (strokeWidth); + RegisterForGraphicUpdate (); + } + } + /// <summary> + /// View box size in pixel + /// </summary> + [DefaultValue ("32,32")] + public Size Size { + get { return size; } + set { + if (size == value) + return; + size = value; + NotifyValueChangedAuto (size); + //RegisterForLayouting (LayoutingType.Sizing); + RegisterForGraphicUpdate (); + updateMaxScrolls (); + } + } + + [DefaultValue ("White")] + public virtual Fill ShapeBackground { + get => shapeBackground; + set { + if (shapeBackground == value) + return; + shapeBackground = value; + NotifyValueChangedAuto (shapeBackground); + RegisterForRedraw (); + } + } + [DefaultValue ("Black")] + public virtual Fill ShapeForeground { + get => shapeForeground; + set { + if (shapeForeground == value) + return; + shapeForeground = value; + NotifyValueChangedAuto (shapeForeground); + RegisterForRedraw (); + } + } + + public override void OnLayoutChanges (LayoutingType layoutType) { + base.OnLayoutChanges (layoutType); + + if (layoutType == LayoutingType.Height) + NotifyValueChanged ("PageHeight", Slot.Height); + else if (layoutType == LayoutingType.Width) + NotifyValueChanged ("PageWidth", Slot.Width); + else + return; + updateMaxScrolls (); + } + public override void onMouseEnter (object sender, MouseMoveEventArgs e) { + base.onMouseEnter (sender, e); + updateMouseCursor (); + } + protected override void onDraw (Context gr) { + base.onDraw (gr); + + if (string.IsNullOrEmpty (path)) + return; + + Rectangle cr = ClientRectangle; + + gr.Save (); + gr.Translate (-ScrollX, -ScrollY); + gr.Scale (Zoom, Zoom); + + Rectangle r = new Rectangle (cr.Position, size); + shapeBackground.SetAsSource (IFace, gr); + gr.Rectangle (r); + gr.Fill (); + + gr.LineWidth = strokeWidth; + ShapeForeground.SetAsSource (IFace, gr, cr); + + using (PathParser parser = new PathParser (path)) + parser.Draw (gr); + + gr.Restore (); + } + + public override void onMouseWheel (object sender, MouseWheelEventArgs e) { + if (e.Delta > 0) + Zoom *= 2.0; + else + Zoom /= 2.0; + e.Handled = true; + base.onMouseWheel (sender, e); + } + + void updateMaxScrolls () { + Rectangle cb = ClientRectangle; + Size scalledSize = size * Zoom; + + MaxScrollX = scalledSize.Width - cb.Width; + if (scalledSize.Width > 0) + NotifyValueChanged ("ChildWidthRatio", (double)cb.Width / scalledSize.Width); + + MaxScrollY = scalledSize.Height - cb.Height; + if (scalledSize.Height > 0) + NotifyValueChanged ("ChildHeightRatio", (double)cb.Height / scalledSize.Height); + } + } +} diff --git a/Samples/PathPainter/PathPainter.csproj b/Samples/PathPainter/PathPainter.csproj new file mode 100644 index 00000000..173ecf80 --- /dev/null +++ b/Samples/PathPainter/PathPainter.csproj @@ -0,0 +1,7 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <ItemGroup> + <EmbeddedResource Include="ui\**\*.*"> + <LogicalName>ui.%(Filename)%(Extension)</LogicalName> + </EmbeddedResource> + </ItemGroup> +</Project> diff --git a/Samples/PathPainter/Program.cs b/Samples/PathPainter/Program.cs new file mode 100644 index 00000000..5993c852 --- /dev/null +++ b/Samples/PathPainter/Program.cs @@ -0,0 +1,76 @@ +using Crow; +using System; + +namespace PathPainter +{ + class Program : SampleBase + { + static void Main (string[] args) { + using (Program app = new Program ()) + app.Run (); + } + + protected override void OnInitialized () { + base.OnInitialized (); + Load ("#ui.main.crow").DataSource = this; + } + string currentPath = "M 5.5,0.5 L 10.5,10.5 L 0.5,10.5 Z F"; + int currentSize = 11; + double zoom = 1.0; + double strokeWidth = 1.0; + Color foreground = Colors.Black; + Color background = Colors.White; + + public Measure DesignSize => (int)(zoom * currentSize); + + public double StrokeWidth { + get => strokeWidth; + set { + if (strokeWidth == value) + return; + strokeWidth = value; + NotifyValueChanged (strokeWidth); + } + } + public string CurrentPath { + get => currentPath; + set { + if (currentPath == value) + return; + currentPath = value; + NotifyValueChanged (currentPath); + } + } + public Size Size => new Size (currentSize); + public int CurrentSize { + get => currentSize; + set { + if (currentSize == value) + return; + currentSize = value; + NotifyValueChanged (currentSize); + NotifyValueChanged ("Size", (object)new Size (currentSize)); + NotifyValueChanged ("CurrentPath", (object)CurrentPath); + } + } + public Color Foreground { + get => foreground; + set { + if (foreground == value) + return; + foreground = value; + NotifyValueChanged (foreground); + } + } + public Color Background { + get => background; + set { + if (background == value) + return; + background = value; + NotifyValueChanged (background); + } + } + + } +} diff --git a/Samples/PathPainter/ui/Icons/Lines.svg b/Samples/PathPainter/ui/Icons/Lines.svg new file mode 100644 index 00000000..9fb54c4b --- /dev/null +++ b/Samples/PathPainter/ui/Icons/Lines.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generated by IcoMoon.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"> +<path fill="#dddddd" d="M1 11.9l-1 4.1 4.1-1 9.2-9.2-3.1-3.1-9.2 9.2zM1.5 15l-0.4-0.5 0.4-2 2 2-2 0.5zM10.9 4.4l-8.1 8-0.6-0.6 8.1-8 0.6 0.6z"></path> +<path fill="#dddddd" d="M15.3 0.7c-1.1-1.1-2.6-0.5-2.6-0.5l-1.5 1.5 3.1 3.1 1.5-1.5c0-0.1 0.6-1.5-0.5-2.6zM13.4 1.6l-0.5-0.5c0.6-0.6 1.1-0.1 1.1-0.1l-0.6 0.6z"></path> +</svg> diff --git a/Samples/PathPainter/ui/Icons/Rect.svg b/Samples/PathPainter/ui/Icons/Rect.svg new file mode 100644 index 00000000..d7d1dc8a --- /dev/null +++ b/Samples/PathPainter/ui/Icons/Rect.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generated by IcoMoon.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"> +<path fill="#dddddd" d="M15 1h-14v14h14v-14zM14 14h-12v-12h12v12z"></path> +</svg> diff --git a/Samples/PathPainter/ui/Icons/Select.svg b/Samples/PathPainter/ui/Icons/Select.svg new file mode 100644 index 00000000..605c0e28 --- /dev/null +++ b/Samples/PathPainter/ui/Icons/Select.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generated by IcoMoon.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"> +<path fill="#dddddd" d="M11.6 5c-0.2 0-0.5 0-0.6 0 0-0.2-0.2-0.6-0.4-0.8s-0.6-0.4-1.1-0.4c-0.2 0-0.4 0-0.6 0.1-0.1-0.2-0.2-0.3-0.3-0.5-0.2-0.2-0.5-0.4-1.1-0.4-0.2 0-0.4 0-0.5 0.1v-1.7c0-0.6-0.4-1.4-1.4-1.4-0.4 0-0.8 0.2-1.1 0.4-0.5 0.6-0.5 1.4-0.5 1.4v4.3c-0.6 0.1-1.1 0.3-1.4 0.6-0.6 0.7-0.6 1.6-0.6 2.8 0 0.2 0 0.5 0 0.7 0 1.4 0.7 2.1 1.4 2.8l0.3 0.4c1.3 1.2 2.4 1.6 5.1 1.6 2.9 0 4.2-1.6 4.2-5.1v-2.5c0-0.7-0.2-2.1-1.4-2.4zM12 7.4v2.6c0 3.4-1.3 4.1-3.2 4.1-2.4 0-3.3-0.3-4.3-1.3-0.1-0.1-0.2-0.2-0.4-0.4-0.7-0.8-1.1-1.2-1.1-2.2 0-0.2 0-0.5 0-0.7 0-1 0-1.7 0.3-2.1 0.1-0.1 0.4-0.2 0.7-0.2v0.5l-0.3 1.5c0 0.1 0 0.1 0.1 0.2s0.2 0 0.2 0l1-1.2c0-0.1 0-0.2 0-0.2v-6.2c0-0.1 0-0.5 0.2-0.7 0.1 0 0.2-0.1 0.4-0.1 0.3 0 0.4 0.3 0.4 0.4v3.1c0 0 0 0 0 0v1.2c0 0.3 0.2 0.6 0.5 0.6s0.5-0.3 0.5-0.5v-1.3c0 0 0 0 0 0 0-0.1 0.1-0.5 0.5-0.5 0.3 0 0.5 0.1 0.5 0.4v1.3c0 0.3 0.2 0.6 0.5 0.6s0.5-0.3 0.5-0.5v-0.7c0-0.1 0.1-0.3 0.5-0.3 0.2 0 0.3 0.1 0.3 0.1 0.2 0.1 0.2 0.4 0.2 0.4v0.8c0 0.3 0.2 0.5 0.4 0.5 0.3 0 0.5-0.1 0.5-0.4 0-0.1 0.1-0.2 0.2-0.3 0 0 0.1 0 0.2 0 0.6 0.2 0.7 1.2 0.7 1.5 0-0.1 0-0.1 0 0z"></path> +</svg> diff --git a/Samples/PathPainter/ui/Painter.style b/Samples/PathPainter/ui/Painter.style new file mode 100644 index 00000000..02ad3e34 --- /dev/null +++ b/Samples/PathPainter/ui/Painter.style @@ -0,0 +1,3 @@ +DrawModeStyle { + Template="#polytest.ui.iconCheckBox.template"; +}
\ No newline at end of file diff --git a/Samples/PathPainter/ui/Spinner.template b/Samples/PathPainter/ui/Spinner.template new file mode 100644 index 00000000..b4baf524 --- /dev/null +++ b/Samples/PathPainter/ui/Spinner.template @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<VerticalStack> + <Label Text="{./Caption}"/> + <Border Style="ControlBorder" Background="{./Background}" CornerRadius="{./CornerRadius}"> + <HorizontalStack Spacing="1"> + <TextBox Style="ControlEditableText" Foreground="{./Foreground}" Font="{./Font}" Width="Stretched" + Text="{²./Value}" TextAlignment="Right" /> + <VerticalStack Width="16" Height="Stretched" Spacing="0" Margin="0"> + <Shape KeepProportions="false" Margin="1" Style="ArrowBut" Height="50%" MouseDown="./onUp" Size="10,10" Path="M 4.5,0.5 L 9.5,9.5 L 0.5,9.5 Z F"/> + <Shape KeepProportions="false" Margin="1" Style="ArrowBut" Height="50%" MouseDown="./onDown" Size="10,10" Path="M 0.5,0.5 L 9.5,0.5 L 4.5,9.5 Z F"/> + </VerticalStack> + </HorizontalStack> + </Border> +</VerticalStack>
\ No newline at end of file diff --git a/Samples/PathPainter/ui/colorSelector.template b/Samples/PathPainter/ui/colorSelector.template new file mode 100644 index 00000000..cc12a623 --- /dev/null +++ b/Samples/PathPainter/ui/colorSelector.template @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<CheckBox Caption="{./Caption}" IsChecked="{²./IsPopped}" Foreground="{./Foreground}" Background="{./Background}"> + <Template> + <Border Style="ControlBorder" CornerRadius="{./CornerRadius}"> + <HorizontalStack Spacing="10" Margin="5"> + <Label Style="ControlCaption" Text="{./Caption}" /> + <Border Foreground="White" Width="30" Height="20" Background="{./Background}" CornerRadius="5"/> + </HorizontalStack> + </Border> + </Template> +</CheckBox>
\ No newline at end of file diff --git a/Samples/PathPainter/ui/main.crow b/Samples/PathPainter/ui/main.crow new file mode 100644 index 00000000..bb0a6297 --- /dev/null +++ b/Samples/PathPainter/ui/main.crow @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<HorizontalStack Background="DarkGrey" > + <VerticalStack> + <HorizontalStack Height="Fit"> + <EnumSelector Fit="true" Caption="Draw Mode" EnumValue="{²../../painter.CurrentDrawMode}" /> + <ComboBox Data="{../../painter.Zooms}" SelectedItem="{²../../painter.Zoom}" Width="60"/> + </HorizontalStack> + <HorizontalStack> + <Border Foreground="Black" Width="Stretched" Height="Stretched" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top"> + <Painter Name="painter" ShapeForeground="{Foreground}" ShapeBackground="{Background}" + Zoom="1" + Size="{Size}" Path="{²CurrentPath}" StrokeWidth="{StrokeWidth}"/> + </Border> + <ScrollBar Value="{²../painter.ScrollY}" + LargeIncrement="{../painter.PageHeight}" SmallIncrement="1" + CursorRatio="{../painter.ChildHeightRatio}" Maximum="{../painter.MaxScrollY}" /> + </HorizontalStack> + <ScrollBar Style="HScrollBar" Value="{²../painter.ScrollX}" + LargeIncrement="{../painter.PageWidth}" SmallIncrement="1" + CursorRatio="{../painter.ChildWidthRatio}" Maximum="{../painter.MaxScrollX}" /> + </VerticalStack> + <Splitter/> + <VerticalStack Margin="2" Spacing="2"> + <TextBox Width="Stretched" Text="{²CurrentPath}"/> + <HorizontalStack Height="Fit"> + <Spinner Caption="Stroke Width" SmallIncrement="0.1" LargeIncrement="0.5" Value="{²StrokeWidth}" Width="Fit" Template="#ui.Spinner.template"/> + <Spinner Caption="Size" Value="{²CurrentSize}" Width="Fit" Template="#ui.Spinner.template"/> + <Popper Caption="Foreground" Background="{Foreground}" Fit="True" Template="#ui.colorSelector.template"> + <ColorPicker CurrentColor="{²Foreground}" Background="Onyx" Width="{../PopWidth}"/> + </Popper> + <Popper Caption="Background" Background="{Background}" Fit="True" Template="#ui.colorSelector.template"> + <ColorPicker CurrentColor="{²Background}" Background="Onyx" Width="{../PopWidth}"/> + </Popper> + </HorizontalStack> + <Group Height="200" Background="Jet"> + <Shape Left="23" Top="9" Margin="0" Width="16" Height="16" Foreground="{Foreground}" Background="{Background}" Size="{Size}" Path="{CurrentPath}" StrokeWidth="{StrokeWidth}"/> + <Shape Left="17" Top="31" Margin="0" Width="32" Height="32" Foreground="{Foreground}" Background="{Background}" Size="{Size}" Path="{CurrentPath}" StrokeWidth="{StrokeWidth}"/> + <Shape Left="65" Top="1" Margin="0" Width="64" Height="64" Foreground="{Foreground}" Background="{Background}" Size="{Size}" Path="{CurrentPath}" StrokeWidth="{StrokeWidth}"/> + <Shape Left="1" Top="66" Margin="0" Width="128" Height="128" Foreground="{Foreground}" Background="{Background}" Size="{Size}" Path="{CurrentPath}" StrokeWidth="{StrokeWidth}"/> + </Group> + + </VerticalStack> +</HorizontalStack> |