/// <summary> /// Add decorators to the instantiated objects /// </summary> /// <param name="jObject">decorator jobject</param> /// <param name="paintBase">paint element to decorate</param> /// <returns>Decorated paintbase of paintbase when there are no decorated in jobject</returns> private PaintBase AddDecorators(JObject jObject, PaintBase paintBase) { if (jObject.GetValue("decorators") is JArray decorators) { foreach (JToken decorator in decorators) { // Check for valid decorator if (decorator is JObject jDecorator && (jDecorator.ContainsKey("position") && jDecorator.ContainsKey("decoration"))) { // Decorate paintBase switch (jDecorator.GetValue("position").ToString()) { case "Top": paintBase = new TopDecoration(paintBase, jDecorator.GetValue("decoration").ToString()); break; case "Bottom": paintBase = new BottomDecoration(paintBase, jDecorator.GetValue("decoration").ToString()); break; case "Left": paintBase = new LeftDecoration(paintBase, jDecorator.GetValue("decoration").ToString()); break; case "Right": paintBase = new RightDecoration(paintBase, jDecorator.GetValue("decoration").ToString()); break; } } } } return(paintBase); }
/// <inheritdoc /> public Task PointerPressedExecuteAsync() { // Add entry to UndoStack UndoStack.Push(ShapeList.DeepCopy()); RedoStack.Clear(); // Set pointer starting point _pointerStart = PointerEventArgs.GetCurrentPoint(Canvas).Position; // Create new shape PaintBase shape = new PaintShape(ShapeType); shape.X = _pointerStart.X; shape.Y = _pointerStart.Y; shape.Width = 2; shape.Height = 2; ShapeList.Add(shape); current = shape; _page.Draw(); _page.UpdateList(); return(Task.CompletedTask); }
/// <inheritdoc /> public Task PointerReleasedExecuteAsync() { // remove current item current = null; return(Task.CompletedTask); }
/// <summary> /// Replace a PaintBase item in the ShapeList /// </summary> /// <param name="current">Item to replace</param> /// <param name="newItem">Item to replace with</param> private void ReplaceShapelistEntry(PaintBase current, PaintBase newItem) { int currentIndex = ShapeList.IndexOf(current); ShapeList.Remove(current); ShapeList.Insert(currentIndex, newItem); }
/// <summary> /// Convert PaintBase into jsonObject /// </summary> /// <param name="paintBase"></param> /// <returns>JSON object of PaintBase</returns> private JObject getBaseJObject(PaintBase paintBase) { return(new JObject { { "width", paintBase.Width }, { "height", paintBase.Height }, { "x", paintBase.X }, { "y", paintBase.Y } }); }
/// <summary> /// Add a new decorator to an element /// </summary> /// <param name="paintBase">element to be decorated</param> private async Task AddNewDecorator(PaintBase paintBase) { // Open dialog DecoratorDialog dialog = new DecoratorDialog(); ContentDialogResult result = await dialog.ShowAsync(); if (result == ContentDialogResult.Primary) { ReplaceShapelistEntry(paintBase, CreateNewTextDecoration(paintBase, dialog.Decoration, dialog.Position)); } }
/// <summary> /// Crate json object for visited element /// If visited element is a group, /// Visit its children recursively /// </summary> /// <param name="element">Element to visit</param> public void Visit(PaintBase element) { // Create JObject for visited element JObject masterJObject = new JObject(); // Array of decorators JArray decorators = null; // If visited element is decoration, add them to jArray if (element is TextDecoration decoration) { decorators = GetDecoratorArray(decoration); element = decoration.GetDrawable(); } if (element is PaintShape shape) { // Convert PaintShape to JObject masterJObject = new JObject { { "type", (int)PaintType.Shape }, { "shapeType", shape.ToString() } }; masterJObject.Merge(getBaseJObject(shape)); } else if (element is PaintGroup group) { // Convert PaintGroup to JObject and add it's children recursively masterJObject = new JObject { { "type", (int)PaintType.Group } }; masterJObject.Merge(getBaseJObject(group)); // Add children JArray children = new JArray(); foreach (PaintBase paintBase in group.Children) { paintBase.Accept(new WriteFileVisitor(children)); } masterJObject.Add("children", children); } // If decorators are found, add them to JObject if (decorators != null) { masterJObject.Add("decorators", decorators); } _jParent.Add(masterJObject); }
/// <summary> /// Scale visited element /// If visited element is a group, /// Visit its children recursively /// </summary> /// <param name="element">Element to visit</param> public void Visit(PaintBase element) { // Get inner non decorated element if element is decorated if (element is TextDecoration decor) { element = decor.GetDrawable(); } if (element is PaintShape shape) { // If element is a shape, apply the transforamtion if (shape.Width + _deltaX > 0 && shape.Height + _deltaY > 0) { shape.Width += _deltaX; shape.Height += _deltaY; } } else if (element is PaintGroup group) { // If element is a group, make sure inner element stay in correct place double originalX = group.X; double originalY = group.Y; // Percentage x and y transformation in regards to the new group size double groupXMultiplier = (group.Width + _deltaX) / group.Width; double groupYMultiplier = (group.Height + _deltaY) / group.Height; // Make sure scale is not negative if (group.Width + _deltaX > 0 && group.Height + _deltaY > 0) { // Apply new size to group group.Width += _deltaX; group.Height += _deltaY; foreach (PaintBase paintBase in group.Children) { double newX = (paintBase.X - originalX) * groupXMultiplier + originalX; double newY = (paintBase.Y - originalY) * groupYMultiplier + originalY; double newXScale = (paintBase.Width * groupXMultiplier) - paintBase.Width; double newYScale = (paintBase.Height * groupYMultiplier) - paintBase.Height; // Move child according to transformation of parent group. paintBase.Accept(new MoveVisitor(newX - paintBase.X, newY - paintBase.Y)); // Scale child accoarding to transformation of parent group. paintBase.Accept(new ScaleVisitor(newXScale, newYScale)); } } } }
/// <inheritdoc /> public Shape GetDrawShape(PaintBase paintBase) { Shape drawShape = new Ellipse(); double x = paintBase.Width < 0 ? paintBase.X + paintBase.Width : paintBase.X; double y = paintBase.Height < 0 ? paintBase.Y + paintBase.Height : paintBase.Y; drawShape.SetValue(Canvas.LeftProperty, x); drawShape.SetValue(Canvas.TopProperty, y); drawShape.Width = paintBase.Width < 0 ? paintBase.Width * -1 : paintBase.Width; drawShape.Height = paintBase.Height < 0 ? paintBase.Height * -1 : paintBase.Height; drawShape.Fill = new SolidColorBrush(Colors.Black); return(drawShape); }
/// <inheritdoc /> public Task ExecuteUserActionAsync() { // Get all selected elements that are of the type PaintGroup List <PaintBase> selected = ShapeList.Where(pb => pb.Selected && !(pb is PaintShape) && (pb is PaintGroup || (pb as TextDecoration).InnerPaintBase is PaintGroup)).ToList(); // Only run if 1 or more groups are selected if (selected.Count > 0) { // Add undo entry to the undo stack UndoStack.Push(ShapeList.DeepCopy()); RedoStack.Clear(); foreach (PaintBase paintBase in selected) { PaintBase element = paintBase; // Check if element is wrapped in a decorator if (element is TextDecoration decor) { // If so, get inner group element = decor.GetDrawable(); } if (element is PaintGroup group) { // Remove group from canvas ShapeList.Remove(paintBase); // Add the groups children back onto the canvas foreach (PaintBase groupChild in group.Children.ToList()) { group.Remove(groupChild); ShapeList.Add(groupChild); } } } _page.Draw(); _page.UpdateList(); } return(Task.CompletedTask); }
/// <summary> /// Create a new decorator instance /// </summary> /// <param name="decoratable">Item to be decorated</param> /// <param name="decoration">Decoration text</param> /// <param name="position">Position of the decoration</param> /// <returns>Decorated instance</returns> private TextDecoration CreateNewTextDecoration(PaintBase decoratable, string decoration, DecoratorAnchor position) { switch (position) { case DecoratorAnchor.Top: return(new TopDecoration(decoratable, decoration)); case DecoratorAnchor.Bottom: return(new BottomDecoration(decoratable, decoration)); case DecoratorAnchor.Left: return(new LeftDecoration(decoratable, decoration)); case DecoratorAnchor.Right: return(new RightDecoration(decoratable, decoration)); } return(null); }
/// <summary> /// Move visited element /// If visited element is a group, /// Visit its children recursively /// </summary> /// <param name="element">Element to visit</param> public void Visit(PaintBase element) { if (element is TextDecoration decor) { element = decor.GetDrawable(); } if (element is PaintShape shape) { shape.X += _deltaX; shape.Y += _deltaY; } else if (element is PaintGroup group) { group.X += _deltaX; group.Y += _deltaY; foreach (PaintBase paintBase in group.Children) { paintBase.Accept(this); } } }
public RightDecoration(PaintBase paintBase, string decorationText) : base(paintBase) { DecorationText = decorationText; }
public RightDecoration(PaintBase paintBase) : base(paintBase) { }
public BottomDecoration(PaintBase paintBase) : base(paintBase) { }
public BottomDecoration(PaintBase paintBase, string decorationText) : base(paintBase, decorationText) { }
public LeftDecoration(PaintBase paintBase) : base(paintBase) { }
public TopDecoration(PaintBase paintBase) : base(paintBase) { }
/// <inheritdoc /> public async Task PointerPressedExecuteAsync() { // Check where the click was executed Point pointer = PointerEventArgs.GetCurrentPoint(Canvas).Position; // Querry a list of selected items List <PaintBase> selected = ShapeList.Where(pb => pb.Selected).ToList(); // Check // if only one item is selected if (selected.Count == 1) { PaintBase paintBase = selected.First(); // Check if the selected item is a decorator if (paintBase is TextDecoration decoration) { // Check if a decorator was clicked TextDecoration deco = decoration.GetClickedDecoration(pointer.X, pointer.Y); if (deco != null) { // Create dialog for Decorator editing DecoratorDialog dialog = new DecoratorDialog(deco.DecorationText, deco.GetDecoratorPosition()); // When editing add a delete button dialog.SecondaryButtonText = "Delete"; ContentDialogResult result = await dialog.ShowAsync(); if (result == ContentDialogResult.Primary) { deco.DecorationText = dialog.Decoration; AddUndoEntry(); // Check if decorator should be moved if (dialog.Position != GetDecoratorPosition(deco)) { TextDecoration newDecoration = decoration.MovePosition(deco, dialog.Position); ReplaceShapelistEntry(decoration, newDecoration); } _page.Draw(); _page.UpdateList(); // Return to prevent 2 decorations in one action return; } else if (result == ContentDialogResult.Secondary) { AddUndoEntry(); PaintBase newElement = decoration.RemoveDecorator(deco); ReplaceShapelistEntry(decoration, newElement); _page.Draw(); _page.UpdateList(); } } } // when the item itself is clicked, add a new decorator if ((pointer.X > paintBase.X && pointer.X < paintBase.X + paintBase.Width) && (pointer.Y > paintBase.Y && pointer.Y < paintBase.Y + paintBase.Height)) { AddUndoEntry(); await AddNewDecorator(paintBase); _page.Draw(); _page.UpdateList(); } } else { // Show error ContentDialog dialog = new ContentDialog() { Title = "Failed adding decorator", Content = "You may only select one item to add a decorator to", CloseButtonText = "Ok" }; await dialog.ShowAsync(); } }