JSON Canvas Viewer

Arquitetura Técnica

Visão Geral

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.

Estrutura do Projeto

jsoncanvasviewer/
├── lib/
   ├── main.dart                          # Ponto de entrada
   └── src/
       ├── modules/
          └── home/
              └── ui/
                  ├── home_page.dart             # Coordenador principal
                  └── widgets/
                      ├── canvas_viewer_widget.dart
                      └── json_editor_widget.dart
       └── shared/
           ├── colors/
              ├── app_colors.dart
              └── editor_theme.dart
           └── jsonWidget/
               └── json_canvas_widget.dart       # Motor de renderização
├── pubspec.yaml
└── analysis_options.yaml

Diagrama de Componentes

graph TB
    subgraph "Camada de Apresentação"
        MA[MyApp]
        HP[HomePage]
        JE[JsonEditorWidget]
        CV[CanvasViewerWidget]
    end
    
    subgraph "Camada de Renderização"
        JCV[JsonCanvasViewer]
        AR[ApplyRotation]
    end
    
    subgraph "Camada de Dados"
        JSON[JSON Data]
        EL[Elements List]
    end
    
    subgraph "Camada de Tema"
        ET[EditorTheme]
        AC[AppColors]
    end
    
    MA --> HP
    HP --> JE
    HP --> CV
    JE --> JSON
    CV --> JCV
    JCV --> JSON
    JCV --> EL
    JCV --> AR
    JE --> ET
    CV --> ET
    JCV --> AC

Camadas da Arquitetura

Camada de Apresentação

Responsável pela interface do usuário e interação.

Componentes:

Camada de Renderização

Processa JSON e renderiza elementos visuais.

Componentes:

Camada de Dados

Gerencia estrutura de dados e parsing.

Componentes:

Camada de Tema

Define estilos visuais e cores.

Componentes:

Fluxo de Comunicação

Fluxo de Edição (Editor → Canvas)

sequenceDiagram
    participant U as Usuário
    participant JE as JsonEditor
    participant HP as HomePage
    participant CV as CanvasViewer
    participant JCV as JsonCanvasViewer

    U->>JE: Digita no editor
    JE->>JE: Inicia debounce (300ms)
    Note over JE: Timer expira
    JE->>JE: _validateJson()
    JE->>HP: onJsonChanged(jsonString)
    JE->>HP: onValidationChanged(isValid)
    HP->>HP: setState(_jsonData, _isValid)
    HP->>CV: Passa jsonData e isValid
    CV->>CV: didUpdateWidget detecta mudança
    CV->>JCV: Cria/atualiza JsonCanvasViewer
    JCV->>JCV: _parseAndSetupJson()
    JCV->>JCV: build() renderiza elementos
    JCV->>U: Exibe canvas atualizado

Fluxo de Interação (Canvas → Editor)

sequenceDiagram
    participant U as Usuário
    participant JCV as JsonCanvasViewer
    participant CV as CanvasViewer
    participant HP as HomePage
    participant JE as JsonEditor

    U->>JCV: onPanStart (inicia drag)
    JCV->>JCV: setState(_draggedElementIndex)
    U->>JCV: onPanUpdate (arrasta)
    JCV->>JCV: Atualiza elemento local
    JCV->>CV: onElementMoved(index, newX, newY)
    CV->>CV: _updateJsonOnElementMove()
    CV->>CV: Modifica Map decoded
    CV->>HP: onJsonUpdated(updatedJson)
    HP->>HP: _isUpdatingFromCanvas = true
    HP->>HP: setState(_jsonData)
    HP->>HP: _isUpdatingFromCanvas = false
    HP->>JE: externalJsonData atualizado
    JE->>JE: didUpdateWidget detecta mudança
    JE->>JE: _isUpdatingFromExternal = true
    JE->>JE: _codeController.text = externalJson
    JE->>JE: _isUpdatingFromExternal = false
    JE->>U: Editor exibe JSON atualizado
    U->>JCV: onPanEnd (termina drag)
    JCV->>JCV: setState(limpa flags)

Gerenciamento de Estado

HomePage State

class _HomePageState extends State<HomePage> {
  String _jsonData = '';
  bool _isValid = false;
  bool _isUpdatingFromCanvas = false;
  
  // Atualização do editor
  void _onJsonChanged(String jsonData) {
    if (_isUpdatingFromCanvas) return;  // Previne loop
    Future.microtask(() {
      if (mounted) setState(() => _jsonData = jsonData);
    });
  }
  
  // Atualização do canvas
  void onCanvasUpdate(String updatedJson) {
    _isUpdatingFromCanvas = true;
    setState(() => _jsonData = updatedJson);
    _isUpdatingFromCanvas = false;
  }
}

Prevenção de Loop Infinito

O sistema usa múltiplas flags para prevenir loops de atualização:

  1. HomePage: _isUpdatingFromCanvas
    • Ativada quando Canvas atualiza JSON
    • Previne HomePage de notificar Canvas novamente
  2. JsonEditorWidget: _isUpdatingFromExternal
    • Ativada quando recebe dados externos
    • Previne Editor de notificar HomePage novamente
  3. JsonEditorWidget: _lastExternalData
    • Cache do último dado externo
    • Previne atualizações redundantes

Responsabilidades por Módulo

Módulo Responsabilidades Dependências
main.dart Inicialização, tema global MaterialApp, HomePage
HomePage Coordenação, estado compartilhado JsonEditor, CanvasViewer
JsonEditorWidget Edição JSON, validação CodeController, Debounce
CanvasViewerWidget Exibição canvas, detecção mudanças JsonCanvasViewer
JsonCanvasViewer Parsing JSON, renderização elementos Dart core, Flutter widgets
EditorTheme Estilos do editor CodeThemeData
AppColors Cores da aplicação Color constants

Sistema de Escala

O sistema implementa coordenadas de design fixo que escalam proporcionalmente:

// Dimensões de design (referência)
designWidth = 1080
designHeight = 1920

// Fator de escala
scaleFactor = min(canvasWidth / designWidth, canvasHeight / designHeight)

// Aplicação
finalX = originalX * scaleFactor
finalFontSize = originalFontSize * scaleFactor

Benefícios:

Padrões Utilizados

Observer Pattern

State Management

Composition over Inheritance

Debouncing

Performance

Otimizações Implementadas

  1. Debouncing: Timer de 300ms nas atualizações do editor
  2. Microtasks: Future.microtask para callbacks assíncronos
  3. Conditional Rebuild: Verificações em didUpdateWidget
  4. Z-Index Sorting: Ordenação única durante parse
  5. Scale Factor Cache: Cálculo único por build

Limitações de Performance

Próximos Passos