/// file: Form1.cs /// Author: Maxime Rohmer /// Brief: Class that is controlling the view /// Version: 0.1.0 /// Date: 17/06/2022 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Paint_2 { public partial class PaintForm : Form { const int WINDOW_OFFSET = 15; //readonly Font FONT = new Font("Arial", fontSize); readonly Color FLAT_RED = Color.FromArgb(0xC6, 0x28, 0x28); readonly Color FLAT_GREEN = Color.FromArgb(0x00, 0x89, 0x7B); readonly Color FLAT_GREY1 = Color.FromArgb(0x59, 0x59, 0x59); private Color _hoveringColor; private Project _project; private int _selectedLayer; private List _selectedLayers; public Color HoveringColor { get => _hoveringColor; set => _hoveringColor = value; } public Project Project { get => _project; set => _project = value; } public int SelectedLayer { get => _selectedLayer; set => _selectedLayer = value; } public List SelectedLayers { get => _selectedLayers; set => _selectedLayers = value; } public PaintForm() { InitializeComponent(); Project = new Project("Untitled project", canvas.Size); SelectedLayers = new List(); SelectedLayers.Add(Project.GetAllLayers()[0].Id); this.KeyPreview = true; RefreshUi(); } private Point MousePositionToCanvasPosition() { return canvas.PointToClient(MousePosition); } private void canvas_MouseDown(object sender, MouseEventArgs e) { canvas.Focus(); Color hoveringColor = GetHoverColor(); Point mousePosition = MousePositionToCanvasPosition(); int toolWidth = (int)nupPencilWidth.Value; Project.MouseDown(SelectedLayers, hoveringColor, mousePosition, toolWidth); RefreshUi(); } private void canvas_MouseUp(object sender, MouseEventArgs e) { Point mousePosition = MousePositionToCanvasPosition(); Project.MouseUp(SelectedLayers, mousePosition); RefreshUi(); } private void tmrRefresh_Tick(object sender, EventArgs e) { Point mousePosition = MousePositionToCanvasPosition(); Project.TimerTick(SelectedLayers, mousePosition); RefreshUi(); } private void BtnColor_Click(object sender, EventArgs e) { Color newColor = (sender as Button).BackColor; Project.ChangeColor(SelectedLayers, newColor); tmrRefresh_Tick(sender, e); } private string ColorToString(Color color) { // Expected Hex:FFFFFF R:255 G:255 B:255 string result = ""; result += ColorPicker.ColorToHex(color); result += " "; result += "R:" + color.R + " G:" + color.G + " B:" + color.B + " A:" + color.A; return result; } private void ForceRefresh() { //canvas.Image = Project.ForcePaintAllLayers(); canvas.Image = Project.ForcePaintLayers(); RefreshUi(); } private void RefreshUi() { lsbTools.DataSource = Project.AvaibleTools; DebugLabel1.Text = ""; PaintTool currentTool = Project.GetCurrentTool(SelectedLayers); if (currentTool != null && currentTool.NeedsFullRefresh) { canvas.Image = Project.ForcePaintLayers(); } else { canvas.Image = Project.PaintLayers(); } lblSelectedColor.Text = ColorToString(Project.GetCurrentToolColor(SelectedLayers)); btnSelectedColor.BackColor = Project.GetCurrentToolColor(SelectedLayers); HoveringColor = GetHoverColor(); lblHoveringColor.Text = ColorToString(HoveringColor); btnHoveringColor.BackColor = HoveringColor; List colorHistory = Project.GetLayerColorHistory(SelectedLayers, 4); btnColorHistory1.BackColor = colorHistory[0]; btnColorHistory1.ForeColor = colorHistory[0]; btnColorHistory2.BackColor = colorHistory[1]; btnColorHistory2.ForeColor = colorHistory[1]; btnColorHistory3.BackColor = colorHistory[2]; btnColorHistory3.ForeColor = colorHistory[2]; btnColorHistory4.BackColor = colorHistory[3]; btnColorHistory4.ForeColor = colorHistory[3]; lblWidth.Text = "W: " + canvas.Width.ToString(); lblHeight.Text = "H: " + canvas.Height.ToString(); pbxSample.Image = DrawSample(pbxSample.Size); DebugLabel1.Text = "Control"; DebugLabel2.Text = "Shift"; if (Project.GetCurrentTool(SelectedLayers).IsCtrlPressed) { DebugLabel1.ForeColor = Color.Green; } else { DebugLabel1.ForeColor = Color.Red; } if (Project.GetCurrentTool(SelectedLayers).IsShiftPressed) { DebugLabel2.ForeColor = Color.Green; } else { DebugLabel2.ForeColor = Color.Red; } if (Project.RandomColor) { btnRandomColor.BackColor = FLAT_GREEN; } else { btnRandomColor.BackColor = FLAT_RED; } if (Project.Eyedropping) { btnEyeDrop.BackColor = FLAT_GREEN; } else { btnEyeDrop.BackColor = FLAT_RED; } } private Bitmap DrawSample(Size size) { Bitmap map = new Bitmap(size.Width, size.Height); Graphics gr = Graphics.FromImage(map); if (Project.GetCurrentTool(SelectedLayers) != null) { PaintTool currentTool = (PaintTool)Project.GetCurrentTool(SelectedLayers).Clone(); Color paint_tool_color = Project.GetCurrentToolColor(SelectedLayers); int paint_tool_width = Project.GetCurrentToolWidth(SelectedLayers); //Would have loved to use a switch case but I cant if (currentTool is Pencil) { Pencil pencil = currentTool as Pencil; pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(new Point(0, size.Height)); pencil.Add(new Point(size.Width, 0)); pencil.Stop(); pencil.Paint(map); } else { if (currentTool is DotPencil) { DotPencil pencil = currentTool as DotPencil; pencil.Start(paint_tool_color, paint_tool_width); int precision = 5; for (int i = 0; i <= precision; i++) { Point newPoint = new Point(i * (size.Width / precision), size.Height - (i * (size.Height / precision))); pencil.Add(newPoint); } pencil.Stop(); pencil.Paint(map); } else { if (currentTool is BezierPencil) { BezierPencil pencil = currentTool as BezierPencil; Point p1 = new Point(0 - paint_tool_width / 2, 0 - paint_tool_width / 2); Point p2 = new Point(0 - paint_tool_width / 2, size.Height + paint_tool_width / 2); Point p3 = new Point(size.Width / 2 - paint_tool_width / 2, size.Height + paint_tool_width / 2); Point p4 = new Point(size.Width / 2 - paint_tool_width / 2, 0 - paint_tool_width / 2); Point p5 = new Point(size.Width + paint_tool_width / 2, 0 - paint_tool_width / 2); Point p6 = new Point(size.Width + paint_tool_width / 2, size.Height + paint_tool_width / 2); // I KNOW THIS IS HARD CODED BUT ITS ONLY PURPOSE IS TO BE PRETTY so it does'nt matter pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p1); pencil.Stop(); pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p2); pencil.Stop(); pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p3); pencil.Stop(); pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p4); pencil.Stop(); pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p5); pencil.Stop(); pencil.Start(paint_tool_color, paint_tool_width); pencil.Add(p6); pencil.Stop(); pencil.Paint(map); } else { if (currentTool is RectanglePencil || currentTool is RectangleBorderPencil || currentTool is EllipsePencil || currentTool is EllipseBorderPencil) { currentTool.Start(paint_tool_color, paint_tool_width); currentTool.Add(new Point(0 + size.Width / 10, 0 + size.Height / 10)); currentTool.Add(new Point(size.Width - size.Width / 10, size.Height - size.Height / 10)); currentTool.Stop(); currentTool.Paint(map); } } } } } //gr.DrawLine(new Pen(Project.GetCurrentToolColor(SelectedLayers), Project.GetCurrentToolWidth(SelectedLayers)), new Point(0, 0), new Point(size.Width, size.Height)); return map; } private Color GetHoverColor() { Point cursorLocation = MousePositionToCanvasPosition(); Color pixel; if (cursorLocation.X > 0 && cursorLocation.X < canvas.Width && cursorLocation.Y > 0 && cursorLocation.Y < canvas.Height && cursorLocation.X < Width && cursorLocation.Y < Height) { int DEBUG = Width; pixel = (canvas.Image as Bitmap).GetPixel(cursorLocation.X, cursorLocation.Y); } else { pixel = Color.FromArgb(0x00, 0x00, 0x00); } return pixel; } private void btnClear_Click(object sender, EventArgs e) { Project.Clear(); ForceRefresh(); } private void nupPencilWidth_ValueChanged(object sender, EventArgs e) { int newWidth = (int)nupPencilWidth.Value; Project.ChangeWidth(SelectedLayers, newWidth); } private void btnSave_Click(object sender, EventArgs e) { string fileName = tbxProjectName.Text; Bitmap image = (Bitmap)canvas.Image; Project.Save(fileName, image); } private void btnSaveCopy_Click(object sender, EventArgs e) { string fileName = tbxProjectName.Text; Bitmap image = (Bitmap)canvas.Image; Project.SaveCopy(fileName, image); } private void lsbTools_SelectedIndexChanged(object sender, EventArgs e) { int toolId = lsbTools.SelectedIndex; Project.ChangeTool(SelectedLayers, toolId); //Yeah that is a little janky but I just want to refresh the tool nupPencilWidth_ValueChanged(sender, e); RefreshUi(); } private void PaintForm_Resize(object sender, EventArgs e) { canvas.Size = new Size(this.Width - (this.Width - panelTools.Location.X) - canvas.Location.X - WINDOW_OFFSET, this.Height - (this.Height - panelHoverColor.Location.Y) - WINDOW_OFFSET - (panelFile.Location.Y + panelFile.Height)); Project.Resize(canvas.Size); RefreshUi(); } private void btnRandomColor_Click(object sender, EventArgs e) { Project.SwitchRandom(); RefreshUi(); } private void btnEyeDrop_Click(object sender, EventArgs e) { Project.SwitchEyeDrop(); RefreshUi(); } private void btnUndo_Click(object sender, EventArgs e) { Project.Undo(SelectedLayers); ForceRefresh(); } private void btnRedo_Click(object sender, EventArgs e) { Project.Redo(SelectedLayers); ForceRefresh(); } private void btnColorPicker_Click(object sender, EventArgs e) { ColorPicker cp = new ColorPicker(this); cp.Show(); } private void PaintForm_Load(object sender, EventArgs e) { tmrRefresh.Enabled = true; DisplayLayers(); } private void btnLayerRemove_Click(object sender, EventArgs e) { int layersCount = SelectedLayers.Count; List LayersToRemove = new List(); foreach (string layer in SelectedLayers) { LayersToRemove.Add(layer); } for (int id = layersCount - 1; id >= 0; id--) { if (Project.RemoveLayer(LayersToRemove[id])) { SelectedLayers.RemoveAt(id); } else { Console.WriteLine("Could not delete the layer"); } } DisplayLayers(); RefreshUi(); } private void BtnAddLayer_Click(object sender, EventArgs e) { SelectedLayers.Add(Project.AddLayer()); DisplayLayers(); RefreshUi(); } private void DisplayLayers() { int Yoffset = 10; int Xoffset = 10; float fontSize = 10; Size blocSize = new Size(pnlLayers.Width, pnlLayers.Height / 6); int blocsCount = 0; int btnWidth = (int)(blocSize.Width / 2.7); int labelWidth = (int)(blocSize.Width / 3.0); int BtnXoffset = labelWidth; int ChkXOffset = BtnXoffset + btnWidth /*+ Xoffset*/; int ChkWidth = (int)(blocSize.Width / 6.0); pnlLayers.Controls.Clear(); List layers = Project.GetAllLayers(); foreach (Sketch layer in layers) { //LABEL LAYER NAME Label lblName = new Label(); //Style lblName.Name = "lblLayer" + layer.Id; lblName.Font = new Font("Arial", fontSize); lblName.AutoSize = false; lblName.Width = labelWidth; lblName.Text = layer.Name; lblName.BackColor = Color.Transparent; lblName.Location = new Point(0, blocsCount * blocSize.Height + Yoffset); //Style //Behaviour pnlLayers.Controls.Add(lblName); //Behaviour //BUTTON VISIBILITY Button BtnVisbility = new Button(); //Style BtnVisbility.FlatStyle = FlatStyle.Popup; BtnVisbility.BackColor = FLAT_GREY1; BtnVisbility.Location = new Point(BtnXoffset, blocsCount * blocSize.Height + Yoffset / 2); BtnVisbility.Width = btnWidth; //Style //Behaviour if (Project.LayersToPrint.Contains(layer.Id)) { BtnVisbility.Text = "Visible"; } else { BtnVisbility.Text = "Invisible"; } BtnVisbility.Name = "ChkLayerVisible:" + layer.Id; BtnVisbility.Click += LayerSelection; pnlLayers.Controls.Add(BtnVisbility); //Behaviour //BUTTON LAYER SELECTION Button chk = new Button(); //Style chk.Location = new Point(ChkXOffset, blocsCount * blocSize.Height + Yoffset / 2); chk.AutoSize = false; chk.Text = ""; chk.FlatStyle = FlatStyle.Popup; chk.Width = ChkWidth; chk.Name = "ChkLayerSelected:" + layer.Id; //Style //Behaviour chk.Click += LayerCheck; if (SelectedLayers.Contains(layer.Id)) { chk.BackColor = Color.Green; } else { chk.BackColor = Color.Red; } pnlLayers.Controls.Add(chk); //Behaviour blocsCount++; } } private void LayerSelection(object sender, EventArgs e) { //We know that the button's name is ChkLayerVisible:... ... being the GUID of the layer Button btn = sender as Button; string rawId = btn.Name; string id = rawId.Replace("ChkLayerVisible:", String.Empty); Project.SwitchLayer(id); DisplayLayers(); } private void LayerCheck(object sender, EventArgs e) { //We know that the button's name is ChkLayerSelected:... ... being the GUID of the layer Button btn = sender as Button; //MessageBox.Show("Btn " + btn.Name + " pressed"); string rawId = btn.Name; string id = rawId.Replace("ChkLayerSelected:", String.Empty); //MessageBox.Show("Select or Deslect layer n:"+id); if (SelectedLayers.Contains(id)) { SelectedLayers.Remove(id); } else { SelectedLayers.Add(id); } DisplayLayers(); } private void btnSvgExport_Click(object sender, EventArgs e) { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.Description = "Custom Description"; if (fbd.ShowDialog() == DialogResult.OK) { string SelectedPath = fbd.SelectedPath; if (Project.SaveSvg(SelectedPath, tbxProjectName.Text)) { MessageBox.Show("Svg saved at " + SelectedPath); } else { MessageBox.Show("Ooops, could not save the SVG in " + SelectedPath); } } } private void PaintForm_KeyPress(object sender, KeyPressEventArgs e) { //empty for now } private void PaintForm_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.ControlKey: Project.CtrlDown(); break; case Keys.ShiftKey: Project.ShiftDown(); break; default: //send the key to the tools break; } } private void PaintForm_KeyUp(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.ControlKey: Project.CtrlUp(); break; case Keys.ShiftKey: Project.ShiftUp(); break; default: //send the key to the tools break; } } } }