# zapocet 25_01_2011

<{ForumPost(poster="nnn", timestamp=2011-01-25 22:07:13)}>

 > Prohlížeč-editor strukturovaných souborů  
 > Úlohou je vytvořit jednoduchý editor ve swingu, který bude umožňovat editaci textových souborů  
 > obsahující strukturu nadpisů ve WIKI formátu.  
 > Struktura souboru  
 >  Soubor se bude skládat z obyčejného textu a WIKI-like nadpisů první a druhé úrovně.  
 >  Nadpisy jsou formátovány jako řádky souboru, které mají následující formát  
 > <bílé znaky>=<Text nadpisu>=<bílé znaky>  
 >   
 > o V případě nadpisu druhé úrovně jsou tam znaky rovná se (=) dva.  
 > Layout editoru  
 >  Editor se bude skládat z tree view (JTree), textového pole (JTextArea) a hlavního menu.  
 >  Tree view bude od textového pole oddělen posuvným sliderem (JSplitPane).  
 > o Textové pole i tree view budou scrollovatelné.  
 >  Hlavní menu bude obsahovat submenu File, které bude obsahovat následující položky:  
 > o New – uzavře právě otevřený soubor a umožní editaci nového souboru (samotný  
 > soubor vznikne až po případném uložení).  
 > o Open – otevře soubor pomocí standardního dialogu.  
 > o Save – uloží otevřený soubor nebo vytvoří nový pomocí standardního dialogu.  
 > o Exit – ukončí editor  
 >  Na začátku je editor v módu vytváření nového souboru.  
 >  Poznámka: při hodnocení má přednost správnost editace souboru před funkcemi open/save  
 > Editace souboru  
 >  Při editaci se v tee view zobrazuje aktuální struktura nadpisů v dokumentu.  
 >  Struktura se upravuje okamžitě přímo při psaní.  
 > o JTextArea reprezentuje vlastní text třídou Document (getDocument()), která  
 > umožňuje například reagovat na změny textu apod.  
 > o JTextArea má kurzor (jeho pozici, vzhled atd.) reprezentován pod jménem Caret  
 > (existuje také přímo třída Caret, se ketrou je také možno manipulovat)  
 >  Tree view má jako kořen uzel s textem „Document“  
 >  Pokud text začímá nadpisem druhé úrovně, tree view k němu zobrazí položku první úrovně  
 > s popisem „<Undefined>“  
 >  Ostatní uzly tree view obsahují text nadpisu (text mezi znaky =)  
 >  Všechny nově vytvořené nadpisy první i druhé úrovně budou v tree view vyditelné (tree view  
 > bude rozbalený).  
 >  Po kliknutí na danou položku v tree view se přehodí fokus na editační okno s textem a kurzor  
 > bude na pozici kde začíná text odpovídajícího nadpisu (nikoli začátek odpovídajícího řádku ale  
 > přímo text mezi znaky =)  
 >  Není kladen důraz na efektivitu implementace.  
 > Použití JTree:  
 >  Jde o klasický view v klasickém MVC patternu (neboli pouze zobrazuje data, neobsahuje však  
 > tyto data sám o sobě).  
 >  Jako zdroj dat používa instanci implementující rozhraní TreeModel (my budeme používat  
 > třídu DefaultTreeModel).  
 >  Jednotlivé prvky modelu tvoří klasickou stromovou strukturu. Prvky musí implementovat  
 > interface TreeNode (my budeme používat DefaultMutableTreeNode, který umožňuje  
 > uložit uživatelská data ve formě Object reference a umožňuje k nim snadno přistupovat).  
 >  JTree využívá pro správu selekce tzv. selection model (getSelectionModel()), který  
 > umožňuje mimo jiné reagovat na události změny selekce v JTree. Také umožňuje nastavit,  
 > kolik prvků se dá označit (my budeme používat mód  
 > TreeSelectionModel.SINGLE_TREE_SELECTION).  
 >  Další užitečné funkce:  
 > o JTree.expandPath(...)  
 > o DefaultTreeModel.reload()  
 > o DefaultTreeModel(TreeNode root)

    package zap;
    
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileWriter;
    import java.io.InputStreamReader;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.JButton;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JSplitPane;
    import javax.swing.JTextArea;
    import javax.swing.JTree;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.text.BadLocationException;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreePath;
    import javax.swing.tree.TreeSelectionModel;
    
    public class MyFrame
    {
    private JFrame frame = new JFrame( "wiki");
            private JSplitPane pane;
            private JTree tree = new JTree();
            private JTextArea text = new JTextArea();
    
            private JMenuBar bar = new JMenuBar();
            private JMenu menuFile = new JMenu("File");
            private JMenuItem menuFileNew = new JMenuItem("New");
            private JMenuItem menuFileOpen = new JMenuItem("Open");
            private JMenuItem menuFileSave = new JMenuItem("Save");
            private JMenuItem menuFileClose = new JMenuItem("Close");
    public MyFrame(){frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
    
                    menuFileNew.addActionListener( new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            text.setText("");
                        }
                    });
    
                    menuFileClose.addActionListener( new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            System.exit(0);
                        }
                    });
    
                    menuFileOpen.addActionListener( new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            JFileChooser chooser = new JFileChooser();
                            int val = chooser.showOpenDialog(null);
                            if (val == JFileChooser.APPROVE_OPTION) {
                                File file = chooser.getSelectedFile();
                                new MyReader( file.getPath());
                            }
    
                        }
                    });
    
                    menuFileSave.addActionListener( new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            JFileChooser chooser = new JFileChooser();
                            int val = chooser.showSaveDialog(null);
                            if (val == JFileChooser.APPROVE_OPTION) {
                                File file = chooser.getSelectedFile();
                                new MyWriter( file.getPath());
                            }
    
                        }
                    });
    
    
                    menuFile.add( menuFileNew);
                    menuFile.add( menuFileOpen);
                    menuFile.add( menuFileSave);
                    menuFile.add( menuFileClose);
                    bar.add( menuFile);
                    frame.setJMenuBar( bar);
                    
                    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
                    tree.addTreeSelectionListener( new MyTreeSelectionListener());
                    text.getDocument().addDocumentListener(new MyDocumentListener());
    
    
                    pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), new JScrollPane(text));
                    pane.setDividerLocation(150);
                    frame.add( pane);
    
                    makeTree();
                    makeText();
                    frame.pack();frame.setVisible( true);}
    
            private void makeTree()
            {
                tree.clearSelection();
                DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeData(0, "Document", 0));
    
                DefaultMutableTreeNode lvl = null;
    
                DefaultTreeModel model = new DefaultTreeModel( root);
                tree.setModel( model);
    
                String[] lines = text.getText().split("\
    ");
                String tmp;
                DefaultMutableTreeNode node;
    
                for (int i = 0; i < lines.length; i++) {
    
                    if ( lines[i].matches("[ \t]*==[A-Za-z0-9]+==[ \t]*")) {
                        tmp = lines[i].split("==")[ 1];
                        node = new DefaultMutableTreeNode(new NodeData(i, tmp, 2));
                        root.insert(node, root.getChildCount());
                        lvl = node;
                    }
    
                    if ( lines[i].matches("[ \t]*=[A-Za-z0-9]+=[ \t]*")) {
                        tmp = lines[i].split("=")[ 1];
                        node = new DefaultMutableTreeNode(new NodeData(i, tmp, 1));
    
                        if ( lvl == null) {
                            lvl = new DefaultMutableTreeNode( new NodeData(i, "<Undefined>", 0));
                            root.insert(lvl, root.getChildCount());
                        }
                        
                        lvl.insert(node, lvl.getChildCount());
                    }
                }
    
                for (int i = 0; i < tree.getRowCount(); i++)
                    tree.expandRow(i);
    
            }
    
            private  void makeText()
            {
                text.append("bla bla bla 
    ");
                text.append("bla bla bla 
    ");
                text.append("
    ");
    
                
                text.append("=nadpis= 
    ");
                text.append("bla bla bla 
    ");
                text.append("bla bla bla 
    ");
                text.append("
    ");
    
                text.append("==nadpis== 
    ");
                text.append("=nadpis= 
    ");
                text.append("bla bla bla 
    ");
                text.append("bla bla bla 
    ");
                text.append("
    ");
    
                text.append("=nadpis= 
    ");
                text.append("=nadpis= 
    ");
                text.append("bla bla bla 
    ");
                text.append("bla bla bla 
    ");
                text.append("
    ");
                
            }
    
            private class NodeData
            {
                private int line;
                private String text;
                private int off;
    
                public NodeData(int line, String text, int off)
                {
                    this.line = line;
                    this.text = text;
                    this.off = off;
                }
    
                public int getLine()
                {
                    return line;
                }
    
                public String getText()
                {
                    return text;
                }
    
                public int getOff()
                {
                    return off;
                }
    
                @Override
                public String toString()
                {
                    return text;
                }
            }
    
            private class MyTreeSelectionListener implements TreeSelectionListener
            {
                public void valueChanged(TreeSelectionEvent e)
                {
                    int line = 0;
                    int off = 0;
                    try {                    
                        TreePath path = tree.getSelectionPath();
                        if ( path == null || path.getLastPathComponent() == null)
                            return;
                        DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent( );
                        line = ((NodeData) node.getUserObject()).getLine();
                        off = ((NodeData) node.getUserObject()).getOff();
                        if ( line == 0) line--;
                        text.setCaretPosition(text.getLineStartOffset(line)+off);
                        text.requestFocus();
                    } catch (BadLocationException ex) {
                        text.setCaretPosition(0);
                        text.requestFocus();
                    }
                }
            }
    
            private class MyDocumentListener implements DocumentListener
            {
    
                public void insertUpdate(DocumentEvent e)
                {
                    makeTree();
                }
    
                public void removeUpdate(DocumentEvent e)
                {
                    makeTree();
                }
    
                public void changedUpdate(DocumentEvent e)
                {
                }
                
            }
    
            public class MyReader
            {
                public MyReader(String file)
                {
                    try {
                            FileInputStream fstream = new FileInputStream( file);
                            DataInputStream in = new DataInputStream( fstream);
                            BufferedReader br = new BufferedReader( new InputStreamReader( in));
                            String strLine;
                            StringBuilder sb = new StringBuilder();
                            while ( (strLine = br.readLine()) != null) {
                                sb.append(strLine+"
    ");
                            }
                            text.setText(sb.toString());
                            in.close();
                    } catch (Exception e) {
                            e.printStackTrace();
                    }
                }
            }
    
            public class MyWriter
            {
                public MyWriter(String file)
                {
                    try {
                        FileWriter fstream = new FileWriter( file);
                        BufferedWriter out = new BufferedWriter( fstream);
                        out.write(text.getText());
                        out.close();
                    } catch ( Exception e) {
                        e.printStackTrace();
                    }
                }
            }
    
    }


<{/ForumPost}>

