Progress dialogy pro archivátory
********************************
Autor: David Andrš

Tento dokument popisuje, jak vytvářet standardní progress dialogy, tzn. dialogy s ukazatelem dlouho
trvající činnosti, kterou jsou v případě archivátorů hlavně vybalování a zabalovaní.

Hlavní úskalí progress dialogů tkví v tom, že musíme předem vědět, kolik toho budeme dělat. Čili je
nutné nejdříve spočítat nějaké číslo, které bude vyjadřovat celkovou "délku" činnost. Například při
vybalování souborů to bude celková velikost vybalovaných souborů.

Operace s progress dialogy poskytuje třída CSalamanderForOperationsAbstract. Ukazatel na instanci
této třídy je předán do všech metod zabývajících se pakováním/rozbalováním.


Druhy progress dialogů
======================

V Salamanderovi lze používat dva druhy progress dialogů -- s jedním progress barem nebo se dvěma
progress bary. Typ progress dialogu určuje druhý parameter metody

  OpenProgressDialog(const char *title, BOOL twoProgressBars, HWND parent, BOOL fileProgress).

Snažíme se používat hlavně dvouprogressové dialogy. S oběma typy se pracuje téměř stejně, až na malé
detaily, které objasníme níže.


Životní cyklus progress dialogů
===============================

Proměnná salamander je ukazatel na instaci třídy CSalamanderForOperationsAbstract, která vstupuje do
pakovacích/rozbalovacích metod.


Jednoprogressový dialog
-----------------------

  // zjistění celkové "délky" činnosti
  ...

  salamander->OpenProgressDialog("titulek", FALSE, NULL, FALSE);
  salamander->ProgressDialogAddText("operace", FALSE);

  // první progress je nastaven na nulu, druhý, který představuje celkovou operaci, nastavíme na
  // totalSize, což je celková délka činnosti - v tomto případě suma velikosti jednotlivých souborů
  salamander->ProgressSetTotalSize(totalSize, CQuadWord(-1, -1));
  // progress nastavíme na nulu (to abysme něco viděli :-D)
  salamander->ProgressSetSize(CQuadWord(0, 0), CQuadWord(-1, -1), TRUE);

  while (cinnost_trva)
  {
    // každá iterace cyklu představuje zpracování jedné části celkové operace

    // 'part' je pocet zpracovanych (dilcich) bytu - inkrement, o ktery se zvysi progress
    // delayedPaint==TRUE, abychom nebrzdili
    if (!salamander->ProgressAddSize(part, TRUE))
    {
      salamander->ProgressDialogAddText("canceling operation, please wait...", FALSE);
      salamander->ProgressEnableCancel(FALSE);
      cinnost_trva = FALSE;
    }
  }

  salamander->CloseProgressDialog();


Dvouprogressový dialog
----------------------

  // zjistění celkové "délky" činnosti
  ...

  salamander->OpenProgressDialog("titulek", TRUE, NULL, FALSE);
  salamander->ProgressDialogAddText("operace", FALSE);

  // první progress je nastaven na nulu, druhý, který představuje celkovou operaci, nastavíme na
  // totalSize, což je celková délka činnosti - v tomto případě suma velikosti jednotlivých souborů
  salamander->ProgressSetTotalSize(CQuadWord(0, 0), totalSize);

  while (cinnost_trva)
  {
    // každá iterace cyklu představuje zpracování jednoho souboru

    // první progress nastavíme na nulu (to abysme něco viděli :-D)
    salamander->ProgressSetSize(CQuadWord(0, 0), CQuadWord(-1, -1), TRUE);
    // nastavíme, jak dlouhá bude tato operace, druhý progress necháváme na pokoji
    salamander->ProgressSetTotalSize(fileSize, CQuadWord(-1, -1));

    while (!zpracovan_cely_soubor)
    {
      // 'part' je pocet zpracovanych (dilcich) bytu - inkrement, o ktery se zvysi progress
      // delayedPaint==TRUE, abychom nebrzdili
      if (!salamander->ProgressAddSize(part, TRUE))
      {
        salamander->ProgressDialogAddText("canceling operation, please wait...", FALSE);
        salamander->ProgressEnableCancel(FALSE);
        cinnost_trva = FALSE;
        break;   // preruseni akce
      }
    }
  }

  salamander->CloseProgressDialog();


Poznamky
--------

- Metoda ProgressAddSize obslouží zvýšení jednoho (příp. obou) progress barů, takže se nemusíme
  starat o nějaké poměry, atd.

- Zpracovaní jednoho souboru je vhodné napsat do funkce, zlepší se tím čitelnost kódu a lépe se
  spravuje a udržuje.

- Pozor na spravné ošetření prázdných adresářů a souborů s nulovou délkou. Má-li soubor nulovou
  délku, potom přičtení inkrementu v metodě ProgressAddSize nezpůsobí posunutí progress baru. Tomu
  čelíme přičtením jedničky k délce souboru. Stejný trik můžeme použít pro prádzné adresáře. Pozor:
  je nutné změnit i 'totalSize'.

- Pokud nelze používat přírůstky a tedy metodu ProgressAddSize, jinými slovy máme v průběhu
  zpracovaní pozici progress baru, lze použít metodu ProgressSetSize(). Stačí pouze zaměnit,
  nemusíme měnit kód výše.

- Parametr 'delayedPaint' nastavený na FALSE způsobí, že progress dialog čeká na své překreslení.
  Toho využíváme při psaní zpráv jako "canceling operation, please wait...". Pokud vypisujeme
  soubory, které pakujeme/vybalujeme, nepoužíváme delayedPaint, abychom nebrzdili operaci (aby to
  měl uživatel rychle hotový a nemusel čekat)


Co zobrazovat v progress dialogu
================================

V následujících sekcích popíšeme, co by měl archivátor zobrazovat na progress dialogu v jednotlivých
operacích.

title: bude ukazovat, co má být titulku
následuje seznam nápisů, co by se měl objevit v progress dialogu.


ListArchive
-----------

Netřeba nic zobrazovat, pokud je listing archivem rychlý - což většinou bývá.


UnpackArchive
-------------

title: "Unpacking archive"
"Reading archive items..."
"Unpacking..."
"File1"
"File2"
...
"FileN"

Progress běží od "File1" do "FileN"


UnpackOneFile
-------------

title: "Unpacking archive"
"File1"

Progress běží v průběhu "File1"


UnpackWholeArchive
------------------

title: "Unpacking archive"
"Reading archive items..."
"Unpacking..."
"File1"
"File2"
...
"FileN"

Progress běží od "File1" do "FileN"


PackToArchive
-------------

title: "Packing archive"
"Reading directory tree..."
"Packing..."
"File1"
"File2"
...
"FileN"
["Removing files..."]

Progress běží od "File1" do "FileN"
Text "Removing files" se objevuje pouze při přesunu souborů do archivu.

Při odstraňování souborů je možné pustit progress. U dvouprogressového dialogu přičteme k totalSize
počet vymazávaných souborů. Před mazáním nastavíme první progress na počet souborů, a pak při každém
vymazání přičteme jedničku.

U jednoprogressovýho dialogu, nastavíme progress na nulu, a totalSize jako počet vymazávaných
souborů, inkrementujeme opět po jedničce.

Výpis vymazáných souborů se nedoporučuje.


DeleteFromArchive
-----------------

title: "Updating archive"
"Reading archive items..."
"Removing..."
"File1"
"File2"
...
"FileN"
