# Diff Viewer - Visualizzazione Side-by-Side delle Differenze

## Descrizione

Il Diff Viewer è una nuova funzionalità che permette di visualizzare le differenze tra due versioni di un file in modo affiancato, con evidenziazione delle modifiche e una minimappa per navigare rapidamente tra le differenze.

## Come Utilizzare

### Accesso dalla GUI

1. Esegui un'operazione di **Differing** dalla GUI principale
2. Nella tabella dei risultati, **doppio-click** su qualsiasi riga per aprire il Diff Viewer
3. La finestra mostrerà il file della baseline (a sinistra) e il file corrente (a destra) affiancati

### Funzionalità

#### Visualizzazione Affiancata
- **Colonna Sinistra**: File dalla baseline (versione precedente)
- **Colonna Centrale**: Minimappa con rappresentazione visiva delle differenze
- **Colonna Destra**: File corrente (versione attuale)

#### Evidenziazione delle Differenze
- 🔴 **Rosso**: Linee **cancellate** (presenti solo nella baseline)
- 🟢 **Verde**: Linee **aggiunte** (presenti solo nella versione corrente)
- 🟡 **Giallo**: Linee **modificate** (diverse tra baseline e corrente)
- ⚪ **Bianco**: Linee **uguali** (nessuna modifica)

#### Numeri di Riga
- Ogni riga mostra il numero di linea originale
- Simboli speciali:
  - `####  | ` = Linea uguale
  - `####  - ` = Linea cancellata
  - `####  + ` = Linea aggiunta
  - `####  ~ ` = Linea modificata
  - `     ~ ` = Linea vuota (per allineamento)

#### Minimappa
- Visualizzazione compatta di tutte le differenze
- I colori corrispondono al tipo di modifica
- **Click sulla minimappa** per navigare rapidamente a una sezione specifica
- Il rettangolo blu indica la porzione attualmente visibile

#### Navigazione
- **Scroll sincronizzato**: entrambi i file scorrono insieme
- **Mouse wheel**: scorri verticalmente
- **Frecce su/giù**: navigazione linea per linea
- **Scrollbar condivisa**: controllo centralizzato dello scroll verticale
- **Scrollbar orizzontali**: separate per ogni file

#### Informazioni
- **Barra info** in basso:
  - Numero di linee: baseline → corrente
  - Conteggio linee: aggiunte, cancellate, modificate

### Casi d'Uso

#### File Modificato
```
Baseline (test.py)         Current (test.py)
------------------         -----------------
1  | def hello():          1  | def hello():
2  | ~   print("Hi")       2  + ~   # nuovo
3  | ~   return 42         3  + ~   print("Hi")
                           4  | ~   return 42
```

#### File Cancellato
- Baseline: mostra il contenuto del file
- Current: mostra "N/A" (file non esiste più)

#### File Aggiunto
- Baseline: mostra "N/A" (file non esisteva)
- Current: mostra il contenuto del nuovo file

## Architettura Tecnica

### File: `pyucc/gui/diff_viewer.py`

#### Classe `DiffViewer(tk.Toplevel)`
Finestra modale per la visualizzazione delle differenze.

**Parametri del costruttore:**
- `parent`: Widget parent (finestra principale)
- `file_a_path`: Path del file baseline (può essere None)
- `file_b_path`: Path del file corrente (può essere None)
- `title_a`: Titolo per il pannello sinistro (default: "Baseline")
- `title_b`: Titolo per il pannello destro (default: "Current")

**Metodi principali:**
- `_load_file(filepath)`: Carica il contenuto di un file
- `_compute_diff_blocks()`: Calcola i blocchi di differenze usando `difflib.SequenceMatcher`
- `_build_ui()`: Costruisce l'interfaccia utente
- `_populate_content()`: Popola i text widget con evidenziazione
- `_draw_minimap()`: Disegna la minimappa delle differenze
- `_setup_scroll_sync()`: Configura la sincronizzazione dello scroll

#### Funzione Helper `show_diff_viewer()`
Funzione di convenienza per aprire il diff viewer.

```python
from pyucc.gui.diff_viewer import show_diff_viewer

show_diff_viewer(parent, file_a_path, file_b_path, 
                 title_a="Baseline", title_b="Current")
```

### Integrazione con GUI Principale

#### File: `pyucc/gui/gui.py`

**Modifiche apportate:**

1. **Tracking della modalità corrente** (`_current_mode`):
   - `'scan'`: Modalità scanning
   - `'countings'`: Modalità conteggi
   - `'metrics'`: Modalità metriche
   - `'differ'`: Modalità differ (abilita double-click)

2. **Memorizzazione dei path root**:
   - `_differ_baseline_root`: Path root della baseline
   - `_differ_current_root`: Path root del progetto corrente

3. **Event handler per double-click**:
   ```python
   def _on_results_double_click(self, event):
       # Verifica modalità differ
       # Ottiene file dalla riga selezionata
       # Costruisce path completi
       # Apre DiffViewer
   ```

4. **Binding**:
   ```python
   self.results_tree.bind('<Double-Button-1>', 
                          self._on_results_double_click)
   ```

## Algoritmo di Diff

Il diff viewer utilizza `difflib.SequenceMatcher` di Python per calcolare le differenze:

1. **Caricamento file**: Legge entrambi i file in liste di linee
2. **Calcolo differenze**: `SequenceMatcher.get_opcodes()` restituisce blocchi:
   - `'equal'`: Blocco di linee uguali
   - `'delete'`: Linee presenti solo in A (baseline)
   - `'insert'`: Linee presenti solo in B (corrente)
   - `'replace'`: Linee diverse tra A e B
3. **Rendering**: Ogni blocco viene colorato appropriatamente
4. **Allineamento**: Linee vuote (`~`) mantengono l'allineamento visivo

## Limitazioni e Note

### Limitazioni Attuali
- ⚠️ La finestra è modale (blocca interazione con finestra principale)
- ⚠️ Non supporta diff a livello di carattere (solo linee intere)
- ⚠️ File molto grandi (>10k linee) potrebbero rallentare l'interfaccia
- ⚠️ Encoding: assume UTF-8 con fallback a ignore errors

### Gestione Errori
- Se un file non esiste, viene mostrato come vuoto
- Se entrambi i file non esistono, viene mostrato un warning
- Errori di lettura file vengono gestiti silenziosamente

### Performance
- Ottimizzato per file fino a ~5000 linee
- La minimappa usa rendering canvas nativo (veloce)
- Scroll sincronizzato con evento batching

## Estensioni Future Possibili

1. **Diff inline**: Evidenziare caratteri specifici modificati dentro una linea
2. **Navigazione tra differenze**: Bottoni "Previous/Next Difference"
3. **Merge tool**: Permettere di selezionare quale versione tenere
4. **Export diff**: Salvare il diff in formato unified o patch
5. **Fold equal blocks**: Nascondere blocchi di linee uguali lunghi
6. **Syntax highlighting**: Colorazione sintassi del linguaggio
7. **Line numbers toggle**: Nascondere/mostrare numeri di riga
8. **Search**: Cercare testo all'interno del diff

## Test

Per testare manualmente il diff viewer:

```bash
python tests/test_diff_viewer_manual.py
```

Questo script crea due file temporanei con differenze e apre il diff viewer.

## Esempio di Utilizzo Programmatico

```python
import tkinter as tk
from pyucc.gui.diff_viewer import show_diff_viewer

# Crea finestra principale
root = tk.Tk()
root.withdraw()

# Apri diff viewer
show_diff_viewer(
    root,
    file_a_path="/path/to/baseline/file.py",
    file_b_path="/path/to/current/file.py",
    title_a="Version 1.0",
    title_b="Version 2.0"
)

root.mainloop()
```

## Screenshot delle Funzionalità

### Layout Principale
```
┌─────────────────────────────────────────────────────────────┐
│  Baseline: file.py          Diff Map     Current: file.py   │
├───────────────────────────┬───────┬─────────────────────────┤
│                           │       │                         │
│  1  | def hello():        │ ████  │  1  | def hello():      │
│  2  | ~   print("Hi")     │ ████  │  2  + ~   # comment    │
│  3  | ~   return 42       │ ████  │  3  + ~   print("Hi")  │
│                           │ ████  │  4  | ~   return 42     │
│  4  | def goodbye():      │ ────  │  5  | def goodbye():    │
│  5  | ~   print("Bye")    │ ────  │  6  | ~   print("Bye")  │
│                           │ ████  │  7  + def new():        │
│                           │ ████  │  8  + ~   pass          │
│                           │       │                         │
├───────────────────────────┴───────┴─────────────────────────┤
│ Lines: 5 → 8  |  Added: 3  Deleted: 0  Modified: 2   [Close]│
└─────────────────────────────────────────────────────────────┘
```

Legenda colori:
- `████` Rosso = Linee cancellate
- `████` Verde = Linee aggiunte  
- `████` Giallo = Linee modificate
- `────` Grigio = Linee uguali
