551 lines
20 KiB
C#
551 lines
20 KiB
C#
/// file: Form1.cs
|
|
/// Author: Maxime Rohmer <maxluligames@gmail.com>
|
|
/// 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<string> _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<string> SelectedLayers { get => _selectedLayers; set => _selectedLayers = value; }
|
|
|
|
public PaintForm()
|
|
{
|
|
InitializeComponent();
|
|
Project = new Project("Untitled project", canvas.Size);
|
|
SelectedLayers = new List<string>();
|
|
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<Color> 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<String> LayersToRemove = new List<string>();
|
|
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<Sketch> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|