# CATIA-Style Metin Notu (Text Annotation) Sistemi

**Tarih:** 2025-12-21
**Durum:** ✅ Tamamlandı
**Konum:** `fikoyt-zorro.com/src/app/uygulamalar/urun-agaci/fiko-metin-notu/`

## 📋 Genel Bakış

FikoYT 3D görüntüleyici için profesyonel CATIA-tarzı metin notu (text annotation) sistemi. Ultra-minimal UI tasarımı ve yüksek kaliteli canvas rendering ile tam özelleştirilebilir metin açıklamaları.

## 🎯 Temel Özellikler

### UI Özellikleri
- ✅ **Ultra-Minimal CATIA Tasarım**: 0.3-0.4rem spacing, 10-12px fontlar
- ✅ **Neon Tema**: Cyan (#00FFFF) & Gold (#FFD700) renk şeması
- ✅ **Accordion Sekmeler**: 3 kategoride organize edilmiş ayarlar
- ✅ **Kompakt Kontroller**: Icon-based butonlar, küçük sliderlar
- ✅ **Anlık Önizleme**: Tüm değişiklikler gerçek zamanlı güncellenir

### Rendering Özellikleri
- ✅ **Profesyonel Canvas Rendering**: 2x supersampling anti-aliasing
- ✅ **GPU Accelerated**: CanvasTexture ile Three.js sprite rendering
- ✅ **Material Pooling**: 100,000+ not için performans optimizasyonu
- ✅ **High-Quality Text**: Subpixel anti-aliasing, çoklu font desteği
- ✅ **Leader Line Support**: Solid/dashed/dotted ok çizgileri

## 📁 Dosya Yapısı

```
fiko-metin-notu/
├── fiko-metin-notu.component.html    # Ultra-minimal accordion UI (224 satır)
├── fiko-metin-notu.component.css     # CATIA-style kompakt styling (487 satır)
├── fiko-metin-notu.component.ts      # Dialog component logic (364 satır)
└── (FikoMetinNotuCizgisi.ts)         # 3D rendering engine (662 satır)
```

**Related Files:**
- `src/service/fikoyt-ui/.../IFikoThreeJS/FikoMetinNotuCizgisi.ts` - Core 3D rendering class
- `src/service/fikoyt-ui/.../fiko-annotation-toolbar.component.ts` - Toolbar integration

## 🎨 UI Tasarımı

### Üst Toolbar
```html
<div class="catia-toolbar">
  <div class="input-icon-grup">
    <i class="font icon"></i>
    <textarea [(ngModel)]="notMetni" class="catia-textarea"></textarea>
  </div>
</div>
```

**Özellikler:**
- Icon-prefixed textarea (font simgesi)
- Courier New monospace font
- rgba(0, 127, 127, 0.7) arka plan
- 0.4rem padding, 12px font

### Kontrol Paneli (3 Sekme)

#### 1. Görünüm Sekmesi
**Kontroller:**
- **Metin Rengi**: 7 preset renk + custom picker
- **Arka Plan**: Renk picker + opacity slider (0-100%)
- **Çerçeve**: Renk picker + kalınlık slider (0-5px)
- **Font Boyutu**: Slider (8-48px)

**CSS Pattern:**
```css
.renk-kutu {
  width: 20px;
  height: 20px;
  border: 2px solid rgba(127, 255, 255, 0.2);
  transition: all 0.2s ease;
}

.renk-kutu.secili {
  border-color: #FFD700;
  border-width: 3px;
  box-shadow: 0 0 8px rgba(255, 215, 0, 0.7);
}
```

#### 2. Stil Sekmesi
**Kontroller:**
- **Font Ailesi**: Select (Arial, Courier New, Times, Verdana, Consolas)
- **Font Stili**: Bold/Italic toggle butonları
- **Hizalama**: Left/Center/Right butonları
- **İç Boşluk**: Slider (4-32px)

**Mini Button Pattern:**
```css
.mini-btn {
  width: 28px;
  height: 24px;
  border-radius: 3px;
  background: rgba(127, 255, 255, 0.1);
}

.mini-btn.active {
  background: rgba(255, 215, 0, 0.2);
  border-color: #FFD700;
  box-shadow: 0 0 6px rgba(255, 215, 0, 0.4);
}
```

#### 3. Çizim Sekmesi
**Kontroller:**
- **Ok İşaretçi**: Checkbox (göster/gizle)
- **Ok Rengi**: Renk picker + kalınlık slider (1-5px)
- **Ok Tipi**: Select (Düz, Kesik, Noktalı)
- **Gölge**: Checkbox + mesafe slider (0-20px)

### Alt Aksiyon Bar
**Butonlar:**
- **Ekle** (Gold): Yeni not ekle
- **Güncelle** (Cyan): Aktif notu güncelle
- **Sil** (Red): Aktif notu sil
- **Kapat** (Grey): Dialog'u kapat

**Button Gradient Pattern:**
```css
.ekle-btn {
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.2), rgba(255, 215, 0, 0.3));
  border-color: rgba(255, 215, 0, 0.5);
  color: #FFD700;
}

.ekle-btn:hover {
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.3), rgba(255, 215, 0, 0.4));
  box-shadow: 0 0 8px rgba(255, 215, 0, 0.5);
}
```

## 🔧 TypeScript API

### Component Properties

```typescript
// Temel özellikler
notMetni: string = 'Yeni not...';
renk: string = '#FFD700';
boyut: number = 14;

// Arka plan
arkaplanRengi: string = '#001a1a';
arkaplanOpaklik: number = 90; // 0-100

// Çerçeve
cercevRengi: string = '#FFD700';
cercevKalinlik: number = 2; // 0-5px

// Font styling
fontAilesi: string = 'Arial';
fontKalin: boolean = true;
fontItalik: boolean = false;
hizalama: 'left' | 'center' | 'right' = 'left';
padding: number = 16; // 4-32px

// Leader line
okGoster: boolean = true;
okRengi: string = '#FFD700';
okKalinlik: number = 2; // 1-5px
okTipi: 'solid' | 'dashed' | 'dotted' = 'solid';

// Gölge
golgeGoster: boolean = true;
golgeMesafe: number = 4; // 0-20px

// Tab states
sekmeler = {
  gorunum: true,
  stil: false,
  cizim: false
};
```

### Component Methods

#### notEkle()
Sahneye yeni metin notu ekler.

```typescript
notEkle(): void {
  const sahne = this.anaGosterim.sahneler[0];
  const not = new FikoMetinNotuCizgisi(sahne, this.notMetni, {
    renk: this.renk,
    boyut: this.boyut,
    arkaplanRengi: this.arkaplanRengi,
    cercevRengi: this.cercevRengi,
    okGoster: this.okGoster
  });

  // Add to annotations group
  const etiketler = sahne.fikoEtiketler;
  const metin = etiketler.ekleMetinNotu(`Metin Notu.${etiketler.sayac}`);
  metin.userData['FikoMetinNotuCizgisi'] = not;

  sahne.add(not);
  this.anaGosterim.ciz();
}
```

#### notGuncelle()
Aktif notu tüm ayarlarla günceller.

```typescript
notGuncelle(): void {
  if (!this.aktifNot) return;

  this.aktifNot.setText(this.notMetni);
  this.aktifNot.setColor(this.renk);
  this.aktifNot.setSize(this.boyut);
  this.aktifNot.setBackgroundColor(rgba);
  this.aktifNot.setBorderStyle(this.cercevRengi, this.cercevKalinlik);
  this.aktifNot.setFontStyle({
    ailesi: this.fontAilesi,
    kalin: this.fontKalin,
    italik: this.fontItalik,
    hizalama: this.hizalama,
    padding: this.padding
  });
  this.aktifNot.setLeaderStyle({
    renk: this.okRengi,
    kalinlik: this.okKalinlik,
    tip: this.okTipi
  });
  this.aktifNot.setShadow(this.golgeGoster, this.golgeMesafe);

  this.anaGosterim.ciz();
}
```

#### Real-time Update Methods
```typescript
renkDegistir(yeniRenk: string): void
boyutDegistir(): void
metniGuncelle(): void
arkaplanDegistir(): void
cerceveDegistir(): void
stilDegistir(): void
okStilDegistir(): void
okDurumDegistir(): void
golgeDegistir(): void
```

### LocalStorage Persistence

```typescript
private ayarlariKaydet(): void {
  const settings = {
    renk: this.renk,
    boyut: this.boyut,
    arkaplanRengi: this.arkaplanRengi,
    cercevRengi: this.cercevRengi,
    okGoster: this.okGoster
  };
  localStorage.setItem('FikoMetinNotu_Ayarlar', JSON.stringify(settings));
}

private ayarlariYukle(): void {
  const settings = localStorage.getItem('FikoMetinNotu_Ayarlar');
  if (settings) {
    const parsed = JSON.parse(settings);
    this.renk = parsed.renk || '#FFD700';
    this.boyut = parsed.boyut || 14;
    // ... restore all settings
  }
}
```

## 🎨 FikoMetinNotuCizgisi Rendering Engine

### Core Class Structure

```typescript
export interface FontStyleOptions {
  ailesi?: string;
  kalin?: boolean;
  italik?: boolean;
  hizalama?: 'left' | 'center' | 'right';
  padding?: number;
}

export interface LeaderStyleOptions {
  renk?: string;
  kalinlik?: number;
  tip?: 'solid' | 'dashed' | 'dotted';
}

export class FikoMetinNotuCizgisi extends THREE.Group {
  // Canvas rendering with anti-aliasing
  private canvas: HTMLCanvasElement;
  private context: CanvasRenderingContext2D;
  private texture: THREE.CanvasTexture;

  // Three.js objects
  private metinSprite: THREE.Sprite | null = null;
  private okCizgisi: THREE.Line | null = null;
}
```

### Professional Canvas Rendering

```typescript
private updateCanvasTexture(): void {
  const ctx = this.context;

  // Build font with all styling
  const fontStyle = this.fontItalik ? 'italic' : 'normal';
  const fontWeight = this.fontKalin ? 'bold' : 'normal';
  const fontString = `${fontStyle} ${fontWeight} ${this.boyut}px ${this.fontAilesi}`;

  // 2x supersampling for retina quality
  const scale = 2;
  const width = Math.pow(2, Math.ceil(Math.log2(contentWidth * scale)));
  const height = Math.pow(2, Math.ceil(Math.log2(contentHeight * scale)));

  // High-quality rendering
  ctx.imageSmoothingEnabled = true;
  ctx.imageSmoothingQuality = 'high';

  // Draw shadow if enabled
  if (this.golgeGoster) {
    ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
    ctx.shadowBlur = this.golgeMesafe * 2;
    ctx.shadowOffsetX = this.golgeMesafe;
    ctx.shadowOffsetY = this.golgeMesafe;
  }

  // Background with RGBA
  ctx.fillStyle = this.arkaplanRengi;
  ctx.fillRect(boxX, boxY, boxWidth, boxHeight);

  // Border with custom thickness
  if (this.cercevKalinlik > 0) {
    ctx.strokeStyle = this.cercevRengi;
    ctx.lineWidth = this.cercevKalinlik;
    ctx.strokeRect(boxX, boxY, boxWidth, boxHeight);
  }

  // Text with alignment
  ctx.font = fontString;
  ctx.fillStyle = this.renk;
  ctx.textAlign = this.hizalama; // left/center/right
  ctx.fillText(this.metin, textX, textY);
}
```

### Leader Line Rendering

```typescript
private createLeaderLine(): void {
  const points = [
    new THREE.Vector3(0, 0, 0),
    new THREE.Vector3(0, 1, 0)
  ];

  const geometry = new THREE.BufferGeometry().setFromPoints(points);

  // Support for different line types
  if (this.okTipi === 'dashed') {
    const material = new THREE.LineDashedMaterial({
      color: new THREE.Color(this.okRengi),
      linewidth: this.okKalinlik,
      dashSize: 0.2,
      gapSize: 0.1
    });
    this.okCizgisi = new THREE.Line(geometry, material);
    this.okCizgisi.computeLineDistances();
  } else if (this.okTipi === 'dotted') {
    const material = new THREE.LineDashedMaterial({
      color: new THREE.Color(this.okRengi),
      linewidth: this.okKalinlik,
      dashSize: 0.05,
      gapSize: 0.1
    });
    this.okCizgisi = new THREE.Line(geometry, material);
    this.okCizgisi.computeLineDistances();
  } else {
    // Solid line
    const material = new THREE.LineBasicMaterial({
      color: new THREE.Color(this.okRengi),
      linewidth: this.okKalinlik
    });
    this.okCizgisi = new THREE.Line(geometry, material);
  }
}
```

### Public API Methods

```typescript
// Text content
setText(yeniMetin: string): void
setColor(yeniRenk: string): void
setSize(yeniBoyut: number): void

// Background & Border
setBackgroundColor(color: string): void  // Accepts hex or rgba
setBorderStyle(color: string, thickness: number): void

// Font styling
setFontStyle(options: FontStyleOptions): void

// Leader line
setLeaderVisible(visible: boolean): void
setLeaderStyle(options: LeaderStyleOptions): void

// Shadow
setShadow(enabled: boolean, distance?: number): void

// Position
updateLeaderLine(target: THREE.Vector3): void
```

### Performance Optimizations

#### Material Pooling
```typescript
private static readonly materialPool = {
  sprite: new Map<string, THREE.SpriteMaterial>(),
  line: new Map<string, THREE.LineBasicMaterial>(),
  background: new Map<string, THREE.MeshBasicMaterial>()
};

// Static cleanup
static disposePool(): void {
  FikoMetinNotuCizgisi.materialPool.sprite.forEach(mat => mat.dispose());
  FikoMetinNotuCizgisi.materialPool.line.forEach(mat => mat.dispose());
  FikoMetinNotuCizgisi.materialPool.background.forEach(mat => mat.dispose());
}
```

#### Canvas Optimization
- **Power-of-2 sizing**: GPU-friendly texture dimensions
- **2x supersampling**: Retina quality anti-aliasing
- **Context hints**: `desynchronized: true`, `willReadFrequently: false`
- **Texture filters**: `LinearFilter` without mipmaps (better for text)

#### Zero-Allocation Updates
```typescript
private static readonly tempVec3 = new THREE.Vector3();

updateLeaderLine(target: THREE.Vector3): void {
  const positions = this.okCizgisi.geometry.attributes.position;
  positions.setXYZ(1, target.x, target.y, target.z);
  positions.needsUpdate = true;
}
```

### JSON Serialization

```typescript
toJSON(): any {
  return {
    type: this.type,
    uuid: this.uuid,
    name: this.name,
    metin: this.metin,
    renk: this.renk,
    boyut: this.boyut,
    arkaplanRengi: this.arkaplanRengi,
    arkaplanOpaklik: this.arkaplanOpaklik,
    cercevRengi: this.cercevRengi,
    cercevKalinlik: this.cercevKalinlik,
    fontAilesi: this.fontAilesi,
    fontKalin: this.fontKalin,
    fontItalik: this.fontItalik,
    hizalama: this.hizalama,
    padding: this.padding,
    okRengi: this.okRengi,
    okKalinlik: this.okKalinlik,
    okTipi: this.okTipi,
    golgeGoster: this.golgeGoster,
    golgeMesafe: this.golgeMesafe,
    position: this.position.toArray(),
    rotation: this.rotation.toArray(),
    scale: this.scale.toArray()
  };
}
```

## 🚀 Kullanım

### Dialog Açma (Annotation Toolbar)

```typescript
openMetinNotuDialog(): void {
  this.DialogFiko.ac({
    bilesen: FikoMetinNotuComponent,
    id: 'fiko-metin-notu-dialog',
    ayarlar: {
      baslik: 'Metin Notu',
      simgeResim: './simgeler/metin-notu.svg',
      modalMi: false,
      sinirlandi: false,
      boyut: { w: 400, h: 450 }
    },
    parametreler: {
      anaGosterim: this.anaGosterim
    }
  });
}
```

### Programmatic Note Creation

```typescript
const sahne = this.anaGosterim.sahneler[0];

// Create note with custom styling
const not = new FikoMetinNotuCizgisi(sahne, 'CATIA-style Note', {
  renk: '#FFD700',
  boyut: 16,
  arkaplanRengi: 'rgba(0, 26, 26, 0.95)',
  cercevRengi: '#00FFFF',
  okGoster: true
});

// Customize appearance
not.setFontStyle({
  ailesi: 'Courier New',
  kalin: true,
  italik: false,
  hizalama: 'center',
  padding: 20
});

not.setLeaderStyle({
  renk: '#00FFFF',
  kalinlik: 3,
  tip: 'dashed'
});

not.setShadow(true, 6);

// Position in 3D space
not.position.set(5, 2, 0);

// Add to scene
sahne.add(not);
```

### Integration with FikoEtiketler

```typescript
const etiketler = sahne.fikoEtiketler;
const metin = etiketler.ekleMetinNotu(`Metin Notu.${etiketler.sayac}`);
metin.userData['FikoMetinNotuCizgisi'] = not;
not.parent = metin;
```

## 📊 Performance Targets

**Rendering:**
- Canvas update: <5ms (retina quality)
- Leader line update: <1ms (zero allocation)
- 100,000+ notes: No frame drops (material pooling)

**Memory:**
- Material reuse: ~95% pool hit rate
- Canvas texture: Power-of-2 sizing for GPU efficiency
- Geometry pooling: Shared buffers for leader lines

**Quality:**
- 2x supersampling anti-aliasing
- Subpixel text rendering
- High-quality shadow effects
- Professional CATIA aesthetics

## 🎯 Best Practices

### UI Design
✅ **DO:**
- Use ultra-kompakt spacing (0.3-0.4rem)
- Follow CATIA color scheme (Cyan/Gold)
- Implement accordion for organization
- Provide real-time preview updates

❌ **DON'T:**
- Add excessive padding/margins
- Use bright or distracting colors
- Show all controls at once
- Delay visual feedback

### Canvas Rendering
✅ **DO:**
- Use power-of-2 dimensions
- Enable supersampling (2x)
- Set high-quality smoothing
- Minimize texture updates

❌ **DON'T:**
- Create new textures per frame
- Use odd canvas dimensions
- Disable anti-aliasing
- Redraw on every mouse move

### Performance
✅ **DO:**
- Pool materials and geometries
- Reuse Vector3/buffers
- Use static readonly for temps
- Implement dispose() properly

❌ **DON'T:**
- Create materials in loops
- Allocate in update methods
- Forget to dispose resources
- Ignore memory leaks

## 🔄 Future Enhancements

**Planned Features:**
- [ ] Multi-line text support with word wrapping
- [ ] Rich text formatting (bold/italic/underline mid-text)
- [ ] Image/icon attachments
- [ ] Text effects (outline, glow, blur)
- [ ] Batch note export/import (JSON/CSV)
- [ ] Note templates system
- [ ] Collaborative editing (multi-user)
- [ ] Voice-to-text integration

**Optimization Opportunities:**
- [ ] WebGL shader-based text rendering
- [ ] Instanced rendering for 1M+ notes
- [ ] LOD system for distant notes
- [ ] Occlusion culling for hidden notes

## 📝 Örnek Kod

### Tam Özelleştirilmiş Not

```typescript
const profesyonelNot = new FikoMetinNotuCizgisi(
  sahne,
  'CATIA V5 Tarzı\nProfesyonel Açıklama',
  {
    renk: '#00FFFF',
    boyut: 18,
    arkaplanRengi: 'rgba(0, 127, 127, 0.85)',
    cercevRengi: '#FFD700',
    okGoster: true
  }
);

// Font styling
profesyonelNot.setFontStyle({
  ailesi: 'Consolas',
  kalin: true,
  italik: false,
  hizalama: 'center',
  padding: 24
});

// Background transparency
profesyonelNot.setBackgroundColor('rgba(0, 26, 26, 0.95)');

// Border styling
profesyonelNot.setBorderStyle('#FFD700', 3);

// Leader line (dashed arrow)
profesyonelNot.setLeaderStyle({
  renk: '#FFD700',
  kalinlik: 2.5,
  tip: 'dashed'
});

// Drop shadow
profesyonelNot.setShadow(true, 8);

// Position
profesyonelNot.position.set(10, 5, 2);
profesyonelNot.updateLeaderLine(new THREE.Vector3(8, 3, 0));

sahne.add(profesyonelNot);
```

## 🐛 Troubleshooting

### Problem: Text blurry
**Çözüm:** Canvas 2x supersampling kullanıyor, texture.needsUpdate = true çağrıldığından emin olun.

### Problem: Leader line not visible
**Çözüm:** `setLeaderVisible(true)` çağrıldığından ve `okGoster` true olduğundan emin olun.

### Problem: Dashed line appears solid
**Çözüm:** `computeLineDistances()` çağrıldığından emin olun (LineDashedMaterial için gerekli).

### Problem: Performance issues with many notes
**Çözüm:** Material pooling kullanıldığından emin olun, `FikoMetinNotuCizgisi.disposePool()` ile temizleyin.

## 📚 Kaynaklar

**Related Documentation:**
- [02-threejs-sistemi.md](02-threejs-sistemi.md) - Three.js engine architecture
- [03-dialog-sistemi.md](03-dialog-sistemi.md) - FikoDialog system
- [08-practices-threejs.md](08-practices-threejs.md) - Three.js best practices

**External References:**
- [Three.js CanvasTexture](https://threejs.org/docs/#api/en/textures/CanvasTexture)
- [Canvas 2D Rendering Context](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D)
- [Three.js Line & LineDashedMaterial](https://threejs.org/docs/#api/en/materials/LineDashedMaterial)

---

**Status:** ✅ Production Ready
**Version:** 1.0.0
**Last Updated:** 2025-12-21
**Author:** FikoYT Development Team
