Skip to content

Commit 06cbee7

Browse files
committed
Refactor Pixel2CPP component to enhance structure and modularity. Introduced custom hooks for canvas state management, code generation, and testing. Updated UI components for better organization, including a collapsible sidebar and improved tab navigation. Streamlined event handling and integrated keyboard shortcuts for enhanced user experience.
1 parent e0ac528 commit 06cbee7

File tree

10 files changed

+1752
-1625
lines changed

10 files changed

+1752
-1625
lines changed

src/Pixel2CPP.jsx

Lines changed: 174 additions & 1625 deletions
Large diffs are not rendered by default.

src/components/CodeModal.jsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Pixel2CPP - Code Modal Component
3+
*
4+
* MIT License
5+
* Copyright (c) 2025 CodeRandom
6+
*
7+
* This software is provided free of charge for educational and personal use.
8+
* Commercial use and redistribution must comply with the MIT License terms.
9+
*/
10+
11+
import React from "react";
12+
13+
/**
14+
* Code Modal component for displaying generated C++ code
15+
*
16+
* @param {Object} props - Component props
17+
* @param {boolean} props.showCodeModal - Whether modal is visible
18+
* @param {Function} props.setShowCodeModal - Function to close modal
19+
* @param {Function} props.handleCopyCode - Function to copy code to clipboard
20+
* @param {string} props.copyStatus - Copy operation status
21+
* @param {Function} props.generateCppCode - Function to generate C++ code
22+
*/
23+
export default function CodeModal({
24+
showCodeModal,
25+
setShowCodeModal,
26+
handleCopyCode,
27+
copyStatus,
28+
generateCppCode
29+
}) {
30+
if (!showCodeModal) return null;
31+
32+
return (
33+
<div className="fixed inset-0 bg-black bg-opacity-60 modal-backdrop flex items-center justify-center p-4 z-50" role="dialog" aria-modal="true" aria-labelledby="modal-title">
34+
<div className="bg-neutral-900 rounded-2xl p-6 max-w-5xl w-full max-h-[85vh] overflow-hidden flex flex-col shadow-2xl border border-neutral-700">
35+
<div className="flex items-center justify-between mb-6">
36+
<div>
37+
<h2 id="modal-title" className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
38+
Generated C++ Code
39+
</h2>
40+
<p className="text-sm text-neutral-400 mt-1">
41+
Ready to use in your Arduino project
42+
</p>
43+
</div>
44+
<div className="flex gap-3">
45+
<button
46+
onClick={handleCopyCode}
47+
className={`px-6 py-3 rounded-xl text-sm font-medium transition-all ${
48+
copyStatus === "copied"
49+
? "bg-green-500 text-white shadow-lg"
50+
: copyStatus === "error"
51+
? "bg-red-500 text-white shadow-lg"
52+
: "bg-blue-500 text-white hover:bg-blue-600 shadow-lg hover:shadow-xl"
53+
}`}
54+
aria-label="Copy generated code to clipboard"
55+
>
56+
{copyStatus === "copied" ? "✓ Copied!" : copyStatus === "error" ? "✗ Error!" : "📋 Copy Code"}
57+
</button>
58+
<button
59+
onClick={() => setShowCodeModal(false)}
60+
className="px-6 py-3 rounded-xl bg-neutral-800 hover:bg-neutral-700 text-sm transition-colors"
61+
aria-label="Close code modal"
62+
>
63+
✕ Close
64+
</button>
65+
</div>
66+
</div>
67+
<div className="flex-1 overflow-auto">
68+
<pre className="bg-neutral-950 rounded-xl p-6 overflow-auto text-sm whitespace-pre-wrap border border-neutral-700 shadow-inner">
69+
{(() => {
70+
try {
71+
const code = generateCppCode();
72+
console.log('Generated code length:', code.length);
73+
return code || '// No code generated - please check console for errors';
74+
} catch (error) {
75+
console.error('Error generating code:', error);
76+
return `// Error generating code: ${error.message}\n// Please check console for details`;
77+
}
78+
})()}
79+
</pre>
80+
</div>
81+
<div className="mt-4 text-xs text-neutral-500 text-center">
82+
Generated by Pixel2CPP • Made by <a href="https://coderandom.com" target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300">CodeRandom</a>
83+
</div>
84+
</div>
85+
</div>
86+
);
87+
}

src/components/EditorTab.jsx

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Pixel2CPP - Editor Tab Component
3+
*
4+
* MIT License
5+
* Copyright (c) 2025 CodeRandom
6+
*
7+
* This software is provided free of charge for educational and personal use.
8+
* Commercial use and redistribution must comply with the MIT License terms.
9+
*/
10+
11+
import React from "react";
12+
import PixelCanvas from "./PixelCanvas.jsx";
13+
14+
/**
15+
* Editor Tab component containing the main canvas editor interface
16+
*
17+
* @param {Object} props - Component props
18+
* @param {number} props.w - Canvas width
19+
* @param {number} props.h - Canvas height
20+
* @param {number} props.zoom - Zoom level
21+
* @param {Array} props.data - Pixel data array
22+
* @param {string} props.backgroundColor - Background color setting
23+
* @param {string} props.tool - Current active tool
24+
* @param {string} props.drawMode - Current draw mode
25+
* @param {Function} props.handleMouseDown - Mouse down handler
26+
* @param {Function} props.handleMouseMove - Mouse move handler
27+
* @param {Function} props.handleMouseUp - Mouse up handler
28+
*/
29+
export default function EditorTab({
30+
w,
31+
h,
32+
zoom,
33+
data,
34+
backgroundColor,
35+
tool,
36+
drawMode,
37+
handleMouseDown,
38+
handleMouseMove,
39+
handleMouseUp
40+
}) {
41+
return (
42+
<div className="space-y-4">
43+
{/* Canvas Container */}
44+
<div className="bg-neutral-900 rounded-2xl p-4 overflow-auto inline-block shadow-xl border border-neutral-700">
45+
<PixelCanvas
46+
width={w}
47+
height={h}
48+
zoom={zoom}
49+
pixels={data}
50+
backgroundColor={backgroundColor}
51+
cursor={tool === "eyedropper" ? "crosshair" : "pointer"}
52+
onPointerDown={handleMouseDown}
53+
onPointerMove={handleMouseMove}
54+
onPointerUp={handleMouseUp}
55+
/>
56+
</div>
57+
58+
{/* Canvas Info */}
59+
<div className="bg-neutral-900/50 rounded-xl p-4 border border-neutral-700">
60+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
61+
<div className="text-center">
62+
<div className="text-neutral-400">Canvas Size</div>
63+
<div className="font-mono text-white">{w} × {h} px</div>
64+
</div>
65+
<div className="text-center">
66+
<div className="text-neutral-400">Zoom Level</div>
67+
<div className="font-mono text-white">{zoom}×</div>
68+
</div>
69+
<div className="text-center">
70+
<div className="text-neutral-400">Active Tool</div>
71+
<div className="font-medium text-emerald-400 capitalize">{tool}</div>
72+
</div>
73+
<div className="text-center">
74+
<div className="text-neutral-400">Draw Mode</div>
75+
<div className="font-mono text-blue-400 text-xs">{drawMode}</div>
76+
</div>
77+
</div>
78+
</div>
79+
80+
{/* Keyboard Shortcuts Help */}
81+
<div className="bg-neutral-900/50 rounded-xl p-4 border border-neutral-700">
82+
<h3 className="font-medium text-sm mb-3">Keyboard Shortcuts</h3>
83+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-xs">
84+
<div className="space-y-1">
85+
<div className="flex justify-between">
86+
<span className="text-neutral-400">B:</span>
87+
<span className="font-mono text-white">Brush</span>
88+
</div>
89+
<div className="flex justify-between">
90+
<span className="text-neutral-400">E:</span>
91+
<span className="font-mono text-white">Erase</span>
92+
</div>
93+
<div className="flex justify-between">
94+
<span className="text-neutral-400">F:</span>
95+
<span className="font-mono text-white">Fill</span>
96+
</div>
97+
</div>
98+
<div className="space-y-1">
99+
<div className="flex justify-between">
100+
<span className="text-neutral-400">I:</span>
101+
<span className="font-mono text-white">Eyedropper</span>
102+
</div>
103+
<div className="flex justify-between">
104+
<span className="text-neutral-400">C:</span>
105+
<span className="font-mono text-white">Clear</span>
106+
</div>
107+
<div className="flex justify-between">
108+
<span className="text-neutral-400">X:</span>
109+
<span className="font-mono text-white">Swap Colors</span>
110+
</div>
111+
</div>
112+
<div className="space-y-1">
113+
<div className="flex justify-between">
114+
<span className="text-neutral-400">Ctrl+Z:</span>
115+
<span className="font-mono text-white">Undo</span>
116+
</div>
117+
<div className="flex justify-between">
118+
<span className="text-neutral-400">Ctrl+Y:</span>
119+
<span className="font-mono text-white">Redo</span>
120+
</div>
121+
<div className="flex justify-between">
122+
<span className="text-neutral-400">Ctrl++:</span>
123+
<span className="font-mono text-white">Zoom In</span>
124+
</div>
125+
</div>
126+
<div className="space-y-1">
127+
<div className="flex justify-between">
128+
<span className="text-neutral-400">Ctrl+-:</span>
129+
<span className="font-mono text-white">Zoom Out</span>
130+
</div>
131+
<div className="flex justify-between">
132+
<span className="text-neutral-400">Ctrl+0:</span>
133+
<span className="font-mono text-white">Reset Zoom</span>
134+
</div>
135+
<div className="flex justify-between">
136+
<span className="text-neutral-400">RMB:</span>
137+
<span className="font-mono text-white">Secondary Color</span>
138+
</div>
139+
</div>
140+
</div>
141+
</div>
142+
</div>
143+
);
144+
}

src/components/Header.jsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Pixel2CPP - Header Component
3+
*
4+
* MIT License
5+
* Copyright (c) 2025 CodeRandom
6+
*
7+
* This software is provided free of charge for educational and personal use.
8+
* Commercial use and redistribution must comply with the MIT License terms.
9+
*/
10+
11+
import React from "react";
12+
13+
/**
14+
* Header component containing branding and main action buttons
15+
*
16+
* @param {Object} props - Component props
17+
* @param {string} props.name - Current asset name
18+
* @param {Function} props.setName - Function to update asset name
19+
* @param {Function} props.importImage - Function to handle image import
20+
* @param {Function} props.handleGenerateCode - Function to generate C++ code
21+
* @param {Function} props.exportCpp - Function to export as header file
22+
* @param {boolean} props.isGenerating - Whether code generation is in progress
23+
*/
24+
export default function Header({
25+
name,
26+
setName,
27+
importImage,
28+
handleGenerateCode,
29+
exportCpp,
30+
isGenerating
31+
}) {
32+
return (
33+
<header className="bg-gradient-to-r from-neutral-900 to-neutral-800 border-b border-neutral-700">
34+
<div className="flex items-center justify-between gap-4 px-3 sm:px-4 py-4">
35+
{/* Logo and Title Section */}
36+
<div className="flex items-center gap-3">
37+
<div className="flex items-center gap-2">
38+
<div className="w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center">
39+
<span className="text-white font-bold text-sm">P2C</span>
40+
</div>
41+
<div>
42+
<h1 className="text-xl sm:text-2xl font-bold tracking-tight bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
43+
Pixel2CPP
44+
</h1>
45+
<p className="text-xs text-neutral-400 -mt-1">
46+
Made by <a href="https://coderandom.com" target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 transition-colors">CodeRandom</a>
47+
</p>
48+
</div>
49+
</div>
50+
</div>
51+
52+
{/* Action Buttons */}
53+
<div className="flex items-center gap-2 sm:gap-3">
54+
<input
55+
className="bg-neutral-800 rounded px-3 py-1 outline-none text-sm border border-neutral-700 focus:border-blue-500 transition-colors"
56+
value={name}
57+
onChange={(e) => setName(e.target.value)}
58+
title="Asset name"
59+
placeholder="Asset name"
60+
aria-label="Asset name for exported code"
61+
/>
62+
<label className="px-3 py-1.5 rounded-xl bg-purple-500 text-white font-medium hover:bg-purple-600 cursor-pointer text-sm transition-colors">
63+
Upload Image
64+
<input
65+
type="file"
66+
accept="image/*"
67+
onChange={(e) => { const f = e.target.files?.[0]; if (f) importImage(f); }}
68+
className="hidden"
69+
aria-label="Upload image file"
70+
/>
71+
</label>
72+
<button
73+
onClick={handleGenerateCode}
74+
disabled={isGenerating}
75+
className="px-3 py-1.5 rounded-xl bg-blue-500 text-white font-medium hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm transition-colors"
76+
aria-label="Generate C++ code"
77+
>
78+
{isGenerating ? "Generating..." : "Generate Code"}
79+
</button>
80+
<button
81+
onClick={exportCpp}
82+
className="px-3 py-1.5 rounded-xl bg-emerald-500 text-black font-medium hover:brightness-110 text-sm transition-colors"
83+
aria-label="Export as header file"
84+
>
85+
Export .h
86+
</button>
87+
</div>
88+
</div>
89+
</header>
90+
);
91+
}

0 commit comments

Comments
 (0)