Skip to content

Commit

Permalink
Merge pull request #13 from Viet281101/custom-grid
Browse files Browse the repository at this point in the history
Update toolbar
  • Loading branch information
Viet281101 authored Jun 1, 2024
2 parents 5900589 + f15734d commit cf518c5
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 14 deletions.
225 changes: 214 additions & 11 deletions 2D/js/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ export class Toolbar {
document.body.appendChild(this.canvas);

this.buttons = [
{ name: 'Create Polyomino', icon: '../assets/ic_plus.png', action: () => this.showPolyominoPopup() }
{ name: 'Create Polyomino', icon: '../assets/ic_plus.png', action: () => this.togglePolyominoPopup() },
{ name: 'Draw Grid', icon: '../assets/ic_table.png', action: () => this.toggleGridPopup() },
{ name: 'Solve', icon: '../assets/ic_solving.png', action: () => this.toggleSolvePopup() }
];

this.popupOpen = false;
this.currentPopup = null;
this.gridPopupCanvas = null;
this.solvePopupCanvas = null;
this.drawToolbar();
this.addEventListeners();
this.addHomeButton();
Expand Down Expand Up @@ -64,26 +69,71 @@ export class Toolbar {
});
document.addEventListener('click', (e) => {
if (this.popupOpen) {
const popup = document.getElementById('polyominoPopup');
if (popup && !popup.contains(e.target) && !this.canvas.contains(e.target)) {
this.closePopup();
if (this.gridPopupCanvas && !this.gridPopupCanvas.contains(e.target) && !this.canvas.contains(e.target)) {
this.closeGridPopup();
}
const pPopup = document.getElementById('polyominoPopup');
if (pPopup && !pPopup.contains(e.target) && !this.canvas.contains(e.target)) {
this.closePolyominoPopup();
}
if (this.solvePopupCanvas && !this.solvePopupCanvas.contains(e.target) && !this.canvas.contains(e.target)) {
this.closeSolvePopup();
}
}
});
};

addHomeButton() {
const img = new Image();
img.src = '../assets/ic_arrow_left.png';
img.src = '../assets/ic_home.png';
img.onload = () => {
this.ctx.drawImage(img, 10, 10, 30, 30);
this.ctx.strokeStyle = '#fff';
this.ctx.strokeRect(5, 5, 40, 40);
};
};

togglePolyominoPopup() {
if (this.currentPopup === 'polyomino') {
this.closePolyominoPopup();
} else {
this.closeCurrentPopup();
this.showPolyominoPopup();
this.currentPopup = 'polyomino';
}
};

toggleGridPopup() {
if (this.currentPopup === 'grid') {
this.closeGridPopup();
} else {
this.closeCurrentPopup();
this.showGridPopup();
this.currentPopup = 'grid';
}
};

toggleSolvePopup() {
if (this.currentPopup === 'solve') {
this.closeSolvePopup();
} else {
this.closeCurrentPopup();
this.showSolvePopup();
this.currentPopup = 'solve';
}
};

closeCurrentPopup() {
if (this.currentPopup === 'polyomino') {
this.closePolyominoPopup();
} else if (this.currentPopup === 'grid') {
this.closeGridPopup();
} else if (this.currentPopup === 'solve') {
this.closeSolvePopup();
}
}

showPolyominoPopup() {
if (this.popupOpen) return;
this.popupOpen = true;

const popupContainer = document.createElement('div');
Expand All @@ -92,7 +142,7 @@ export class Toolbar {
popupContainer.style.top = '50px';
popupContainer.style.left = '50%';
popupContainer.style.transform = 'translateX(-50%)';
popupContainer.style.width = '360px';
popupContainer.style.width = '370px';
popupContainer.style.height = '600px';
popupContainer.style.border = '3px solid #000';
popupContainer.style.backgroundColor = '#fff';
Expand All @@ -102,12 +152,18 @@ export class Toolbar {

const popup = document.createElement('canvas');
const ctx = popup.getContext('2d');
const width = 360;
const width = 370;
const height = 6000;
popup.width = width;
popup.height = height;
popupContainer.appendChild(popup);

const title = document.createElement('h3');
Object.assign(title.style, { position: 'fixed', top: '-10px', left: '50%',
transform: 'translateX(-50%)', zIndex: '1001', fontSize: '20px', color: '#00ffaa', });
title.textContent = 'Create Polyominoes';
popupContainer.appendChild(title);

const closeIcon = new Image();
closeIcon.src = '../assets/ic_close.png';
closeIcon.style.position = 'fixed';
Expand All @@ -116,7 +172,7 @@ export class Toolbar {
closeIcon.style.transform = 'translateX(-50%)';
closeIcon.style.cursor = 'pointer';
closeIcon.style.zIndex = '1001';
closeIcon.addEventListener('click', () => this.closePopup());
closeIcon.addEventListener('click', () => this.closePolyominoPopup());
document.body.appendChild(closeIcon);

const shapes = Object.keys(SHAPES);
Expand Down Expand Up @@ -150,7 +206,7 @@ export class Toolbar {
const newPolyomino = new Polyomino(SHAPES[shape].map(row => [...row]), mousePos.x, mousePos.y, getRandomColor(), this.mainApp);
this.mainApp.polyominoes.push(newPolyomino);
this.mainApp.redraw();
this.closePopup();
this.closePolyominoPopup();
};

popup.addEventListener('click', (e) => {
Expand All @@ -170,7 +226,133 @@ export class Toolbar {
});
};

closePopup() {
showGridPopup() {
this.popupOpen = true;

this.gridPopupCanvas = document.createElement('canvas');
this.gridPopupCanvas.width = 370;
this.gridPopupCanvas.height = 600;
this.gridPopupCanvas.style.position = 'absolute';
this.gridPopupCanvas.style.top = '50px';
this.gridPopupCanvas.style.left = '50%';
this.gridPopupCanvas.style.transform = 'translateX(-50%)';
this.gridPopupCanvas.style.border = '3px solid #000';
this.gridPopupCanvas.style.zIndex = '1000';
document.body.appendChild(this.gridPopupCanvas);

const ctx = this.gridPopupCanvas.getContext('2d');
ctx.fillStyle = '#a0a0a0';
ctx.fillRect(0, 0, this.gridPopupCanvas.width, this.gridPopupCanvas.height);

const title = 'Grid Settings';
ctx.font = '22px Pixellari';
ctx.fillStyle = '#00ffaa';
ctx.fillText(title, this.gridPopupCanvas.width / 2 - ctx.measureText(title).width / 2, 30);

const closeIcon = new Image();
closeIcon.src = '../assets/ic_close.png';
closeIcon.onload = () => {
ctx.drawImage(closeIcon, this.gridPopupCanvas.width - 38, 1, 32, 32);
};

const rows = [
{ label: 'Create new grid', box: true, title: true },
{ label: 'Enter n° rows', type: 'input' },
{ label: 'Enter n° columns', type: 'input' },
{ label: 'Draw grid', icon: '../assets/ic_draw.png' },
{ label: 'Delete current grid', icon: '../assets/ic_trash.png' },
{ label: 'Blacken the cells', icon: '../assets/ic_blackend_cell.png' }
];

const startY = 70;
const rowHeight = 70;
const colX = 30;

rows.forEach((row, index) => {
const y = startY + index * rowHeight;
if (row.box) {
if (row.title) {
ctx.strokeStyle = '#fff';
ctx.strokeRect(10, y - 30, this.gridPopupCanvas.width - 20, rowHeight * 4);
} else {
ctx.strokeStyle = '#fff';
ctx.strokeRect(10, y - 30, this.gridPopupCanvas.width - 20, rowHeight);
}
}
ctx.font = '20px Pixellari';
ctx.fillStyle = '#000';
ctx.fillText(row.label, colX, y + 20);

if (row.icon) {
const icon = new Image();
icon.src = row.icon;
icon.onload = () => {
ctx.drawImage(icon, this.gridPopupCanvas.width - 94, y - 30, 64, 64);
};
} else if (row.type === 'input') {
const input = document.createElement('input');
input.type = 'number';
input.style.position = 'absolute';
input.style.left = `${this.gridPopupCanvas.getBoundingClientRect().left + this.gridPopupCanvas.width - 120}px`;
input.style.top = `${this.gridPopupCanvas.getBoundingClientRect().top + y - 20}px`;
input.style.width = '60px';
document.body.appendChild(input);

this.gridPopupCanvas.addEventListener('remove', () => {
document.body.removeChild(input);
});
}
});

this.gridPopupCanvas.addEventListener('click', (e) => {
const rect = this.gridPopupCanvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;

if (mouseX >= this.gridPopupCanvas.width - 40 && mouseX <= this.gridPopupCanvas.width - 10 &&
mouseY >= 10 && mouseY <= 40) {
this.closeGridPopup();
}
});
};

showSolvePopup() {
this.popupOpen = true;

this.solvePopupCanvas = document.createElement('canvas');
this.solvePopupCanvas.width = 370;
this.solvePopupCanvas.height = 600;
this.solvePopupCanvas.style.position = 'absolute';
this.solvePopupCanvas.style.top = '50px';
this.solvePopupCanvas.style.left = '50%';
this.solvePopupCanvas.style.transform = 'translateX(-50%)';
this.solvePopupCanvas.style.border = '3px solid #000';
this.solvePopupCanvas.style.zIndex = '1000';
document.body.appendChild(this.solvePopupCanvas);

const ctx = this.solvePopupCanvas.getContext('2d');
ctx.fillStyle = '#a0a0a0';
ctx.fillRect(0, 0, this.solvePopupCanvas.width, this.solvePopupCanvas.height);

const closeIcon = new Image();
closeIcon.src = '../assets/ic_close.png';
closeIcon.onload = () => {
ctx.drawImage(closeIcon, this.solvePopupCanvas.width - 38, 1, 32, 32);
};

this.solvePopupCanvas.addEventListener('click', (e) => {
const rect = this.solvePopupCanvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;

if (mouseX >= this.solvePopupCanvas.width - 40 && mouseX <= this.solvePopupCanvas.width - 10 &&
mouseY >= 10 && mouseY <= 40) {
this.closeSolvePopup();
}
});
};

closePolyominoPopup() {
const popup = document.getElementById('polyominoPopup');
if (popup) {
document.body.removeChild(popup);
Expand All @@ -180,6 +362,27 @@ export class Toolbar {
document.body.removeChild(closeIcon);
}
this.popupOpen = false;
this.currentPopup = null;
};

closeGridPopup() {
if (this.gridPopupCanvas) {
const inputs = document.querySelectorAll('input[type="number"]');
inputs.forEach(input => document.body.removeChild(input));
document.body.removeChild(this.gridPopupCanvas);
this.gridPopupCanvas = null;
}
this.popupOpen = false;
this.currentPopup = null;
};

closeSolvePopup() {
if (this.solvePopupCanvas) {
document.body.removeChild(this.solvePopupCanvas);
this.solvePopupCanvas = null;
}
this.popupOpen = false;
this.currentPopup = null;
};

resizeToolbar() {
Expand Down
Binary file added assets/ic_blackend_cell.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic_draw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic_home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic_solution.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic_solving.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/ic_table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class MainApp {
this.polyominoes = [];
this.colors = ['#FF5733', '#33FF57', '#3357FF', '#F1C40F', '#9B59B6', '#3498DB', '#E74C3C', '#2ECC71'];
this.usedColors = [];
this.iconImage = new Image();
this.iconImage.src = './assets/ic_arrow_right.png';

this.initialize();
this.addEventListeners();
Expand Down Expand Up @@ -136,8 +138,8 @@ class MainApp {
this.ctx.fillText('Propose solving solutions.', this.canvas.width / 2, 230);

this.buttons = [];
this.drawButton('2D Version', this.canvas.width / 2, 350, () => { window.location.href = './2D/index.html'; });
this.drawButton('3D Version', this.canvas.width / 2, 450, () => { window.location.href = './3D/index.html'; });
this.drawButton('2D Version', (this.canvas.width / 2), 350, () => { window.location.href = './2D/index.html'; });
this.drawButton('3D Version', (this.canvas.width / 2), 450, () => { window.location.href = './3D/index.html'; });
};

drawButton(text, x, y, onClick) {
Expand All @@ -152,6 +154,13 @@ class MainApp {
this.ctx.textAlign = 'center';
this.ctx.fillText(text, x, y);

const iconSize = 32;
const textWidth = this.ctx.measureText(text).width;
const iconX = x + textWidth / 2 + 10;
const iconY = y - iconSize / 2;

this.ctx.drawImage(this.iconImage, iconX, iconY, iconSize, iconSize);

this.buttons.push({ text, x, y, width: buttonWidth, height: buttonHeight, onClick });
};

Expand Down
2 changes: 1 addition & 1 deletion style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@charset "UTF-8";
@font-face {font-family:'Pixellari';src: url("../assets/Pixellari.ttf") format("truetype");}
@font-face {font-family:'Pixellari';src: url("./assets/Pixellari.ttf") format("truetype");}
* {font-family: 'Pixellari', sans-serif;}

0 comments on commit cf518c5

Please sign in to comment.