|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: Arquitetura |
| 4 | +--- |
| 5 | + |
| 6 | +# Arquitetura Técnica |
| 7 | + |
| 8 | +## Visão Geral |
| 9 | + |
| 10 | +O JSON Canvas Viewer segue uma arquitetura modular com separação clara de responsabilidades, implementando o padrão de apresentação baseado em widgets do Flutter com gerenciamento de estado local usando StatefulWidget. |
| 11 | + |
| 12 | +## Estrutura do Projeto |
| 13 | + |
| 14 | +``` |
| 15 | +jsoncanvasviewer/ |
| 16 | +├── lib/ |
| 17 | +│ ├── main.dart # Ponto de entrada |
| 18 | +│ └── src/ |
| 19 | +│ ├── modules/ |
| 20 | +│ │ └── home/ |
| 21 | +│ │ └── ui/ |
| 22 | +│ │ ├── home_page.dart # Coordenador principal |
| 23 | +│ │ └── widgets/ |
| 24 | +│ │ ├── canvas_viewer_widget.dart |
| 25 | +│ │ └── json_editor_widget.dart |
| 26 | +│ └── shared/ |
| 27 | +│ ├── colors/ |
| 28 | +│ │ ├── app_colors.dart |
| 29 | +│ │ └── editor_theme.dart |
| 30 | +│ └── jsonWidget/ |
| 31 | +│ └── json_canvas_widget.dart # Motor de renderização |
| 32 | +├── pubspec.yaml |
| 33 | +└── analysis_options.yaml |
| 34 | +``` |
| 35 | + |
| 36 | +## Diagrama de Componentes |
| 37 | + |
| 38 | +```mermaid |
| 39 | +graph TB |
| 40 | + subgraph "Camada de Apresentação" |
| 41 | + MA[MyApp] |
| 42 | + HP[HomePage] |
| 43 | + JE[JsonEditorWidget] |
| 44 | + CV[CanvasViewerWidget] |
| 45 | + end |
| 46 | + |
| 47 | + subgraph "Camada de Renderização" |
| 48 | + JCV[JsonCanvasViewer] |
| 49 | + AR[ApplyRotation] |
| 50 | + end |
| 51 | + |
| 52 | + subgraph "Camada de Dados" |
| 53 | + JSON[JSON Data] |
| 54 | + EL[Elements List] |
| 55 | + end |
| 56 | + |
| 57 | + subgraph "Camada de Tema" |
| 58 | + ET[EditorTheme] |
| 59 | + AC[AppColors] |
| 60 | + end |
| 61 | + |
| 62 | + MA --> HP |
| 63 | + HP --> JE |
| 64 | + HP --> CV |
| 65 | + JE --> JSON |
| 66 | + CV --> JCV |
| 67 | + JCV --> JSON |
| 68 | + JCV --> EL |
| 69 | + JCV --> AR |
| 70 | + JE --> ET |
| 71 | + CV --> ET |
| 72 | + JCV --> AC |
| 73 | +``` |
| 74 | + |
| 75 | +## Camadas da Arquitetura |
| 76 | + |
| 77 | +### Camada de Apresentação |
| 78 | + |
| 79 | +Responsável pela interface do usuário e interação. |
| 80 | + |
| 81 | +**Componentes**: |
| 82 | +- `MyApp`: Configuração global da aplicação |
| 83 | +- `HomePage`: Coordenador principal, gerencia estado compartilhado |
| 84 | +- `JsonEditorWidget`: Editor de código JSON |
| 85 | +- `CanvasViewerWidget`: Visualizador do canvas |
| 86 | + |
| 87 | +### Camada de Renderização |
| 88 | + |
| 89 | +Processa JSON e renderiza elementos visuais. |
| 90 | + |
| 91 | +**Componentes**: |
| 92 | +- `JsonCanvasViewer`: Motor de renderização principal |
| 93 | +- `ApplyRotation`: Widget para aplicar transformações de rotação |
| 94 | + |
| 95 | +### Camada de Dados |
| 96 | + |
| 97 | +Gerencia estrutura de dados e parsing. |
| 98 | + |
| 99 | +**Componentes**: |
| 100 | +- JSON parseado como `Map<String, dynamic>` |
| 101 | +- Lista de elementos ordenados por z-index |
| 102 | + |
| 103 | +### Camada de Tema |
| 104 | + |
| 105 | +Define estilos visuais e cores. |
| 106 | + |
| 107 | +**Componentes**: |
| 108 | +- `EditorTheme`: Tema do editor de código |
| 109 | +- `AppColors`: Paleta de cores da aplicação |
| 110 | + |
| 111 | +## Fluxo de Comunicação |
| 112 | + |
| 113 | +### Fluxo de Edição (Editor → Canvas) |
| 114 | + |
| 115 | +```mermaid |
| 116 | +sequenceDiagram |
| 117 | + participant U as Usuário |
| 118 | + participant JE as JsonEditor |
| 119 | + participant HP as HomePage |
| 120 | + participant CV as CanvasViewer |
| 121 | + participant JCV as JsonCanvasViewer |
| 122 | +
|
| 123 | + U->>JE: Digita no editor |
| 124 | + JE->>JE: Inicia debounce (300ms) |
| 125 | + Note over JE: Timer expira |
| 126 | + JE->>JE: _validateJson() |
| 127 | + JE->>HP: onJsonChanged(jsonString) |
| 128 | + JE->>HP: onValidationChanged(isValid) |
| 129 | + HP->>HP: setState(_jsonData, _isValid) |
| 130 | + HP->>CV: Passa jsonData e isValid |
| 131 | + CV->>CV: didUpdateWidget detecta mudança |
| 132 | + CV->>JCV: Cria/atualiza JsonCanvasViewer |
| 133 | + JCV->>JCV: _parseAndSetupJson() |
| 134 | + JCV->>JCV: build() renderiza elementos |
| 135 | + JCV->>U: Exibe canvas atualizado |
| 136 | +``` |
| 137 | + |
| 138 | +### Fluxo de Interação (Canvas → Editor) |
| 139 | + |
| 140 | +```mermaid |
| 141 | +sequenceDiagram |
| 142 | + participant U as Usuário |
| 143 | + participant JCV as JsonCanvasViewer |
| 144 | + participant CV as CanvasViewer |
| 145 | + participant HP as HomePage |
| 146 | + participant JE as JsonEditor |
| 147 | +
|
| 148 | + U->>JCV: onPanStart (inicia drag) |
| 149 | + JCV->>JCV: setState(_draggedElementIndex) |
| 150 | + U->>JCV: onPanUpdate (arrasta) |
| 151 | + JCV->>JCV: Atualiza elemento local |
| 152 | + JCV->>CV: onElementMoved(index, newX, newY) |
| 153 | + CV->>CV: _updateJsonOnElementMove() |
| 154 | + CV->>CV: Modifica Map decoded |
| 155 | + CV->>HP: onJsonUpdated(updatedJson) |
| 156 | + HP->>HP: _isUpdatingFromCanvas = true |
| 157 | + HP->>HP: setState(_jsonData) |
| 158 | + HP->>HP: _isUpdatingFromCanvas = false |
| 159 | + HP->>JE: externalJsonData atualizado |
| 160 | + JE->>JE: didUpdateWidget detecta mudança |
| 161 | + JE->>JE: _isUpdatingFromExternal = true |
| 162 | + JE->>JE: _codeController.text = externalJson |
| 163 | + JE->>JE: _isUpdatingFromExternal = false |
| 164 | + JE->>U: Editor exibe JSON atualizado |
| 165 | + U->>JCV: onPanEnd (termina drag) |
| 166 | + JCV->>JCV: setState(limpa flags) |
| 167 | +``` |
| 168 | + |
| 169 | +## Gerenciamento de Estado |
| 170 | + |
| 171 | +### HomePage State |
| 172 | + |
| 173 | +```dart |
| 174 | +class _HomePageState extends State<HomePage> { |
| 175 | + String _jsonData = ''; |
| 176 | + bool _isValid = false; |
| 177 | + bool _isUpdatingFromCanvas = false; |
| 178 | + |
| 179 | + // Atualização do editor |
| 180 | + void _onJsonChanged(String jsonData) { |
| 181 | + if (_isUpdatingFromCanvas) return; // Previne loop |
| 182 | + Future.microtask(() { |
| 183 | + if (mounted) setState(() => _jsonData = jsonData); |
| 184 | + }); |
| 185 | + } |
| 186 | + |
| 187 | + // Atualização do canvas |
| 188 | + void onCanvasUpdate(String updatedJson) { |
| 189 | + _isUpdatingFromCanvas = true; |
| 190 | + setState(() => _jsonData = updatedJson); |
| 191 | + _isUpdatingFromCanvas = false; |
| 192 | + } |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +### Prevenção de Loop Infinito |
| 197 | + |
| 198 | +O sistema usa múltiplas flags para prevenir loops de atualização: |
| 199 | + |
| 200 | +1. **HomePage**: `_isUpdatingFromCanvas` |
| 201 | + - Ativada quando Canvas atualiza JSON |
| 202 | + - Previne HomePage de notificar Canvas novamente |
| 203 | + |
| 204 | +2. **JsonEditorWidget**: `_isUpdatingFromExternal` |
| 205 | + - Ativada quando recebe dados externos |
| 206 | + - Previne Editor de notificar HomePage novamente |
| 207 | + |
| 208 | +3. **JsonEditorWidget**: `_lastExternalData` |
| 209 | + - Cache do último dado externo |
| 210 | + - Previne atualizações redundantes |
| 211 | + |
| 212 | +## Responsabilidades por Módulo |
| 213 | + |
| 214 | +| Módulo | Responsabilidades | Dependências | |
| 215 | +|--------|------------------|--------------| |
| 216 | +| **main.dart** | Inicialização, tema global | MaterialApp, HomePage | |
| 217 | +| **HomePage** | Coordenação, estado compartilhado | JsonEditor, CanvasViewer | |
| 218 | +| **JsonEditorWidget** | Edição JSON, validação | CodeController, Debounce | |
| 219 | +| **CanvasViewerWidget** | Exibição canvas, detecção mudanças | JsonCanvasViewer | |
| 220 | +| **JsonCanvasViewer** | Parsing JSON, renderização elementos | Dart core, Flutter widgets | |
| 221 | +| **EditorTheme** | Estilos do editor | CodeThemeData | |
| 222 | +| **AppColors** | Cores da aplicação | Color constants | |
| 223 | + |
| 224 | +## Sistema de Escala |
| 225 | + |
| 226 | +O sistema implementa coordenadas de design fixo que escalam proporcionalmente: |
| 227 | + |
| 228 | +```dart |
| 229 | +// Dimensões de design (referência) |
| 230 | +designWidth = 1080 |
| 231 | +designHeight = 1920 |
| 232 | +
|
| 233 | +// Fator de escala |
| 234 | +scaleFactor = min(canvasWidth / designWidth, canvasHeight / designHeight) |
| 235 | +
|
| 236 | +// Aplicação |
| 237 | +finalX = originalX * scaleFactor |
| 238 | +finalFontSize = originalFontSize * scaleFactor |
| 239 | +``` |
| 240 | + |
| 241 | +**Benefícios**: |
| 242 | +- Designers trabalham em resolução fixa |
| 243 | +- Canvas se adapta a qualquer tamanho |
| 244 | +- Coordenadas intuitivas e previsíveis |
| 245 | + |
| 246 | +## Padrões Utilizados |
| 247 | + |
| 248 | +### Observer Pattern |
| 249 | +- Callbacks para comunicação entre widgets |
| 250 | +- `onJsonChanged`, `onValidationChanged`, `onElementMoved` |
| 251 | + |
| 252 | +### State Management |
| 253 | +- Local state com `StatefulWidget` |
| 254 | +- Props drilling para estado compartilhado |
| 255 | + |
| 256 | +### Composition over Inheritance |
| 257 | +- Widgets compostos de outros widgets |
| 258 | +- Reutilização através de composição |
| 259 | + |
| 260 | +### Debouncing |
| 261 | +- Timer de 300ms para otimizar performance |
| 262 | +- Reduz chamadas desnecessárias ao parser |
| 263 | + |
| 264 | +## Performance |
| 265 | + |
| 266 | +### Otimizações Implementadas |
| 267 | + |
| 268 | +1. **Debouncing**: Timer de 300ms nas atualizações do editor |
| 269 | +2. **Microtasks**: `Future.microtask` para callbacks assíncronos |
| 270 | +3. **Conditional Rebuild**: Verificações em `didUpdateWidget` |
| 271 | +4. **Z-Index Sorting**: Ordenação única durante parse |
| 272 | +5. **Scale Factor Cache**: Cálculo único por build |
| 273 | + |
| 274 | +### Limitações de Performance |
| 275 | + |
| 276 | +- Não virtualizado: todos elementos renderizados sempre |
| 277 | +- Rebuild completo do Stack a cada mudança |
| 278 | +- Recomendado: máximo 50-100 elementos |
| 279 | + |
| 280 | +## Próximos Passos |
| 281 | + |
| 282 | +- Explore [Componentes](components.md) para detalhes de implementação |
| 283 | +- Veja [Renderização](rendering.md) para entender o pipeline |
| 284 | +- Confira [Decisões Técnicas](technical-decisions.md) para justificativas |
| 285 | + |
0 commit comments