zapocet 25_01_2011

Předmět zaměřený na praktické programování v jazyku a prostředí Java
nnn

zapocet 25_01_2011

Příspěvek od nnn »

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)

Kód: Vybrat vše

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();
                }
            }
        }

}
Odpovědět

Zpět na „PGR013 Java“