====== Strom se soubory ======
Na záložce **Files** zobrazíme jednotlivé disky a jejich adresáře a soubory. \\
Kliknutím na některé soubory zobrazíme odpovídající panel
{{diagram_tree.png}}
Podadresáře budeme načítat průběžně podle toho, které adresáře si uživatel bude prohlížet.
Aby byly vidět značky naznačující, že prvek stromu má v sobě schované další větve, \\
načteme do stromu o úroveň (o patro) prvků více než uživatel dosud navštívil.
==== Třída FileNode ====
Rozšíříme standardní třídu **TreeNode** o proměnnou **path** skladující kompletní cestu k souboru, \\
a proměnou **ready** obsahující příznak, zda byly nacteny i podadresáře daného uzlu.
class FileNode : TreeNode
{
public string path;
public bool ready = false; // true ... podadresare jiz nacteny
}
==== Jednotlivé disky =====
Metoda **displayDrives**
* Vymažeme původní obsah stromu
* Statická funkce **GetDrives** ve třídě **DriveInfo** nám poskytne pole informací o jednotlivých discích ( C:, D:, ... )
* V cyklu projedeme pole disků
* Pro jednotlivé disky zavoláme metodu **displayDirectory**
* první parametr bude podobjekt **Nodes** ve stromu, tím budeme přidávat disky jako větve stromu na nejvyšší úrovni
* druhým parametrem bude informace o kořenovém adresáři disku
private void displayDrives ()
{
fileTree.Nodes.Clear ();
DriveInfo[] roots = DriveInfo.GetDrives ();
foreach (DriveInfo r in roots)
displayDirectory (fileTree.Nodes, r.RootDirectory);
}
==== Zobrazení adresáře souborů ve stromu ====
Metoda **displayDirectory**
* má za první parametr objekt typpu "kolekce" uzlů, do které budeme přidávat nový uzel
* druhý parametr typu **DirectoryInfo** poskytne informace o adres85i na disku
* parametr **level** určuje kolik pater do stromu přidáme
* Vytvoříme nový uzel našeho typu **FileNode**
* do **node.path** uložíme cestu k adresáři
* **node.ready** nastavíme na //false//, podadresáře ještě nejsou načteny
* v **node.Text** bude text zobrazovaný v daném uzlu, uložíme tam jen krátké jméno adresáře bez nadřazených adresářů
* do **ToolTipText**, textu v malém obdélníčku (pokud se na chilku zastavíme s myší), bude úplná cesta k adresáři
* **ForeColor** určuje barvu textu
* **target.Add (node);** přidá nový uzel do příslušného místa stromu
* metoda **displayDetail**, popsaná dále, doplní pod nový uzel další adresáře a soubory
private void displayDirectory (TreeNodeCollection target, DirectoryInfo dir, int levels = 2)
{
FileNode node = new FileNode ();
node.path = dir.FullName;
node.ready = false;
node.Text = dir.Name;
node.ToolTipText = node.path;
node.ForeColor = Color.Blue;
target.Add (node);
displayDetail (node, dir, levels);
}
==== Zobrazení souboru ve stromu ====
Metoda **displayFile** obdoně zobrazí informace o jednom souboru.
Standardní třida **FileInfo** také může poskytnout informace o délce a datumu souboru
private void displayFile (TreeNodeCollection target, FileInfo f)
{
FileNode node = new FileNode ();
node.path = f.FullName;
node.ready = true;
node.Text = f.Name;
node.ToolTipText = node.path;
node.ForeColor = Color.Orange;
target.Add (node);
}
==== Soubory a podadresáře =====
Metoda **displayDetail**
* dostane jako parametr již existující uzel stromu **node**
* a v tomto uzlu je již zobrazeno jméno adresáře **dir**
* poslední parametr určuje kolik pater je ještě potřeba zobrazit
* Pokud je **level** větší než jedna, budeme pokračovat
* Blok **try** ... **catch** má zachytit výjimky, například nedovolený přístup do adresáře nebo disk bez CD/DVD média
* **dir.GetFiles ()** poskytne pole s popisy jednotlivý souborů, zavoláme pro ně metodu **displayFile**
* **dir.GetDirectories ()** zjistí seznam podadresářů, funkci **displayDirectory** zavoláme pro počet pater o zmenšený o jedna
* Pokud vznikne výjimka
* informace o výjimce budou v proměnné **e** typu **Exception**
* vytvoříme uzel stromu (jen typu //TreNode// nikoliv //FileNode//)
* jako //Text// přidáme zprávu o výjimce **e.ToString ()**
* v plovoucím obdélníčku zobrazíme seznam právě prováděných funkcí **e.ToString ()**
* text obarvíme na červeno a přídáme do stromu
private void displayDetail (FileNode node, DirectoryInfo dir, int levels)
{
if (levels > 1)
try
{
foreach (FileInfo f in dir.GetFiles ())
displayFile (node.Nodes, f);
foreach (DirectoryInfo d in dir.GetDirectories ())
displayDirectory (node.Nodes, d, levels - 1);
node.ready = true;
}
catch (Exception e)
{
TreeNode t = new TreeNode ();
t.Text = e.ToString ();
t.ToolTipText = e.StackTrace;
t.ForeColor = Color.Red;
node.Nodes.Add (t);
}
}
{{diagram_exception.png}}
==== Rozvinutí větve představující adresář ====
Pokud uživatel "rozklikne" v2tev stromu, dřive než uvidí výsledek, tak proběhne **treeView_BeforeExpand**
V parametru **e** se skrývá odkaz na otvíranou větev **e.Node**, \
ta by již měla být dobře zobrazena,
my se podíváme na dosud skryté pod poduzly **e.Node.Nodes**.
Poduzly přetypujeme na //FileNode//
FileNode node = n as FileNode;
pokud by **n** bylo jen //TreeNode// (např. červená zpráva o chybě), bude **node** rovno **null**.
Pro jednotlivé poduzly nám standardní třída //DirectoryInfo//poskytne informace o adresáři na disku **new DirectoryInfo (node.path)**\\
Pokud by při tom vznikla výjimka, přidáme //try ... catch//
DirectoryInfo dir = new DirectoryInfo (node.path);
Nakonec funkce displayDetail přidá do stromu vnořené adresáře a soubory
private void treeView_BeforeExpand (object sender, TreeViewCancelEventArgs e)
{
foreach (TreeNode n in e.Node.Nodes)
{
FileNode node = n as FileNode;
if (node != null && !node.ready)
{
try
{
DirectoryInfo dir = new DirectoryInfo (node.path);
displayDetail (node, dir, 2);
}
catch (Exception ex)
{
}
}
}
}
==== Výběr souboru ve stromu ====
Při dvojitém kliknutí do stromu pomocí **FileInfo** získáme příponu souboru a pro některé přípony zobrazíme panel
private void fileTree_DoubleClick (object sender, EventArgs e)
{
TreeNode node = fileTree.SelectedNode as TreeNode;
if (node != null)
{
string path = node.FullPath;
FileInfo f = new FileInfo (path);
string ext = f.Extension;
statusLabel.Text = path + ", " + ext;
switch (ext)
{
case ".txt":
case ".bat":
case ".ini":
case ".cs":
case ".c":
case ".cpp":
case ".cc":
case ".h":
case ".hpp":
displayText (path);
break;
case ".png":
case ".bmp":
case ".jpg":
case ".jpeg":
displayImage (path);
break;
case ".csv":
displayTable (path);
break;
case ".chart":
displayChart (path);
break;
case ".html":
displayHtml (path);
break;
}
}
}
Funkce **displayText** vytvoří nový panel **TextArea** a zavolá dále popsanou funkci **displayObject**
public void displayText (string path)
{
TextArea a = new TextArea (path);
displayObject (a);
}
public void displayImage (string path)
{
ImageArea a = new ImageArea (path);
displayObject (a);
}
public void displayTable (string path)
{
TableArea a = new TableArea (path);
displayObject (a);
}
public void displayChart (string path)
{
ChartArea a = new ChartArea (path);
displayObject (a);
}
public void displayHtml (string path)
{
HtmlArea a = new HtmlArea (path);
displayObject (a);
}
==== Zobrazení nového panelu (nebo jiného objektu) ====
Na záložku **Tree** přidáme informace o novém objektu
* jako text ve stromu použijeme standardní konverzi **obj.ToString ()**, kterou používá i sčítání řetězců znaků
* do standardní položky **node.Tag** typu **object** schováme ukazatel na objekt
Pokud je objekt typu **Control** nebo třídy z //Control// odvozené, \\
umístíme objekt nad **pictureBox**.
**BringToFront** umístí objekt nad jiné plouvoucí panely, aby byl vidět
public void displayObject (object obj)
{
TreeNode node = new TreeNode ();
node.Text = obj.ToString ();
node.Tag = obj;
tree.Nodes.Add (node);
if (obj is Control)
{
Control c = obj as Control;
c.Parent = pictureBox;
c.BringToFront ();
}
}
==== Kliknutí do stromu na záložce Tree ====
* Z uzlu stromu z položky **Tag** vyzvedneme ukazatel na objekt
* //PropertyGrid// na pravé straně okna zobrazí jednotlivé vlastnosti objektu
* Pokud je náš objekt plovoucím objektem nad původním obrázkem, umístíme objekt nad jiné objekty
private void tree_AfterSelect (object sender, TreeViewEventArgs e)
{
object obj = e.Node.Tag;
propGrid.SelectedObject = obj;
if (obj is Control)
{
Control c = obj as Control;
c.BringToFront ();
}
}
[[https://gitlab.fjfi.cvut.cz/culikzde/pw/-/tree/master/Diagram|gitlab]]
[[http://kmlinux.fjfi.cvut.cz/~culikzde/pw/Diagram2020.zip|zip]]