معماری این پروژه بر پایه اصول مهندسی نرمافزار مدرن، الگوهای طراحی اثباتشده و رویکرد State-Centric طراحی شده است. در ادامه، لایههای مختلف معماری و اجزای کلیدی آن تشریح میگردد.
🎨 لایه ۱: رابط کاربری (UI Layer)
این لایه مسئول ارائه تجربه کاربری حرفهای و تعامل با کاربر است. شامل Sidebar ابزارها، Tab Bar برای مدیریت چند نمودار، Properties Panel برای ویرایش ویژگیها، و Modalهای مختلف (ایجاد نمودار، تنظیمات، ذخیره، Export PNG و ویرایشگر Class) میباشد.
- تکنولوژی: HTML5 Semantic + CSS3 (با CSS Variables برای تم داینامیک) + Tailwind CSS (CDN)
- ویژگی کلیدی: پشتیبانی کامل RTL، فونت Vazirmatn، تم تاریک/روشن، طراحی Responsive
🧠 لایه ۲: مدیریت وضعیت (State Management Layer)
قلب تپنده برنامه که تمامی وضعیتهای سراسری را در یک آبجکت مرکزی نگهداری میکند. این رویکرد باعث سادگی، قابلیت پیشبینی و نگهداری آسان کد میشود.
const state = {
diagrams: [],
activeDiagramId: null,
currentTool: 'select',
selectedElement: null,
isDragging: false,
isDrawingRelationship: false,
mousePos: { x:0, y:0 },
sidebarVisible: true,
gridType: 'lines',
darkMode: true,
fileMetadata: { ... }
// ... سایر ویژگیهای وضعیت
};
🎨 لایه ۳: موتور رسم (Rendering Engine)
موتور رسم بر پایه HTML5 Canvas 2D API و رویکرد Immediate Mode Rendering طراحی شده است. در این رویکرد، در هر تغییر وضعیت، کل بوم پاکسازی شده و تمامی المانها از نو رسم میشوند.
- تابع اصلی رسم:
function draw() { ... } - چرخه اصلی رسم که Grid، المانها و روابط را مدیریت میکند
- تابع Dispatch:
function drawDiag(c,d,tc) { ... } - بر اساس نوع نمودار، تابع اختصاصی را فراخوانی میکند
- توابع اختصاصی هر نمودار:
function drawUseCase(c,d,tc) { ... }
function drawStateMachine(c,d,tc) { ... }
function drawActivity(c,d,tc) { ... }
function drawComponent(c,d,tc) { ... }
function drawDeployment(c,d,tc) { ... }
function drawClassDiagram(c,d,tc) { ... }
function drawSequenceDiagram(c,d,tc) { ... }
function drawSwimlaneDiagram(c,d,tc) { ... }
- تابع رسم Grid:
function drawGrid(c,w,h,tc,trans) { ... } - پشتیبانی از سه حالت Lines, Dots, None
🎯 لایه ۴: سیستم تعامل و Hit Testing
این لایه مسئول تشخیص موقعیت ماوس، انتخاب المانها، Drag & Drop و رسم روابط است.
- تابع Hit Test:
function hitTest(x,y) { ... } - بر اساس نوع نمودار، الگوریتمهای متفاوتی برای تشخیص المان زیر ماوس اجرا میکند
- مدیریت رویدادها:
canvas.addEventListener('mousedown', e => { ... }) - شروع Drag یا رسم رابطه
canvas.addEventListener('mousemove', e => { ... }) - بهروزرسانی موقعیت المانها
canvas.addEventListener('mouseup', e => { ... }) - پایان Drag یا تکمیل رابطه
canvas.addEventListener('dblclick', e => { ... }) - باز کردن ویرایشگرها
🗂️ لایه ۵: رجیستری نمودارها (Diagram Registry)
الگوی طراحی Registry Pattern برای تعریف مرکزی انواع نمودارها و قابلیتهای آنها بهکار رفته است.
const DIAGRAM_TYPES = {
usecase: {
id: 'usecase',
name: 'نمودار مورد کاربرد (Use Case)',
icon: '⭕',
available: true,
tools: ['select', 'actor', 'useCase', ...],
groups: ['selection', 'uc-elements', ...]
},
statemachine: { /* ... */ },
activity: { /* ... */ },
component: { /* ... */ },
deployment: { /* ... */ },
class: { /* ... */ },
sequence: { /* ... */ },
swimlane: { /* ... */ }
};
این رجیستری بهعنوان Single Source of Truth برای ابزارها، گروهها و قابلیتهای هر نمودار عمل میکند و افزودن نمودار جدید را بسیار آسان میسازد.
💾 لایه ۶: سیستم Persistence
سیستم ذخیرهسازی و بازیابی مبتنی بر JSON File API است. این رویکرد مزایای متعددی نسبت به LocalStorage یا Backend دارد.
- تابع ساخت داده ذخیره:
function buildSaveData() { ... } - ساختار کامل JSON شامل متادیتا، ترجیحات و همه نمودارها
- تابع ذخیره:
document.getElementById('confirmSaveBtn').addEventListener('click', () => { ... }) - ایجاد Blob و دانلود فایل
- تابع بارگذاری:
document.getElementById('fileInput').addEventListener('change', e => { ... }) - خواندن فایل JSON و بازیابی وضعیت
🎨 لایه ۷: سیستم تم و رنگ
سیستم تم بر پایه CSS Custom Properties (Variables) طراحی شده است. با تغییر کلاس body.dark، تمامی متغیرهای رنگی بهصورت آنی تغییر میکنند.
- تابع دریافت رنگها:
function getTC() { ... } - استخراج رنگهای فعال از CSS Variables در زمان اجرا
- تابع اعمال تم:
function applyTheme() { ... } - تغییر کلاس body و بهروزرسانی UI
🔧 لایه ۸: مدیریت نمودارها
توابع مدیریت چرخه حیات نمودارها (ایجاد، سوئیچ، حذف) در این لایه قرار دارند.
function createNewDiagram(type='usecase') { ... }
function switchDiagram(id) { ... }
function deleteDiagram(id) { ... }
function renderTabs() { ... } - رسم Tab Bar
function updateToolVisibility() { ... } - نمایش/مخفی کردن ابزارها بر اساس نوع نمودار فعال
🗂️ لایه ۹: ویرایشگرهای تخصصی
برای المانهای پیچیده مانند Class، ویرایشگرهای اختصاصی طراحی شدهاند.
function openClassEditor(classId) { ... } - باز کردن ویرایشگر Class با Attributes و Methods
function renderAttributesTable() { ... } - رسم جدول ویژگیها
function renderMethodsTable() { ... } - رسم جدول متدها
الگوهای طراحی بهکار رفته:
| الگو |
محل کاربرد |
مزیت |
| Registry Pattern |
DIAGRAM_TYPES |
مرجع مرکزی، توسعهپذیری آسان |
| State Pattern |
آبجکت state |
مدیریت متمرکز وضعیت |
| Strategy Pattern |
توابع draw* |
انتخاب استراتژی رسم بر اساس نوع |
| Command Pattern |
مدیریت ابزارها |
رفتارهای مشخص برای هر ابزار |
| Observer Pattern |
Event Listeners |
واکنش به رویدادهای کاربر |
| Factory Pattern |
createNewDiagram() |
ساخت ساختار اولیه نمودار |
| Singleton Pattern |
Canvas Context، State |
تنها یک نمونه از منابع حیاتی |
💡 نکته معماری: انتخاب Vanilla JS به جای فریمورکهایی مانند React یا Angular، باعث کاهش چشمگیر حجم نهایی، اجرای سریعتر، عدم وابستگی به ابزارهای Build و سادگی نگهداری شده است. این رویکرد برای ابزارهای تخصصی و آفلاین، انتخاب بهینهای است.