1    /*
2    Copyright 2000 by Ralph Hartley
3    This software is licenced under the terms of the
4    Gnu Public Licence
5    */
6    
7    import javax.swing.*;
8    import java.awt.event.*;
9    import java.awt.*;
10   import java.util.*;
11   import java.io.*;
12   import javax.swing.event.*;
13   
14   public class Help  implements ActionListener,ListSelectionListener,FocusListener {
15   
16     static String OK ="Close";
17     static String ABOUT ="about";
18     static String HELP ="help";
19     static String NEW ="New";
20     static String ADDIMAGE ="Add image";
21     static String DELSEC ="Del section";
22     static String DEL ="Del entry";
23     static String SAVE ="Save";
24     static String READ ="Read text";
25   
26     transient JFrame dial;
27     transient Container pane;
28     transient JScrollPane scroller;
29     transient JScrollPane listscroller;
30     transient JList list;
31     transient Vector contents = new Vector();
32     transient Vector viewers = new Vector();
33     transient String curname;
34     transient JFileChooser chooser;
35     transient int focusindex = -1;
36     transient int cursor = -1;
37   
38     TreeSet entries = new TreeSet();
39   
40     public Help() {
41       entries.add(ABOUT);
42       String[] names = (new File(HELP)).list();
43       if (names==null) return;
44       for (int i=0;i<names.length;i++) {
45         if (names[i].endsWith(".str")) {
46           entries.add(names[i].substring(0,names[i].lastIndexOf(".")));
47         }
48       }
49     }
50   
51     public void show() {
52       dial = new JFrame();
53       dial.setTitle("Help");
54       pane = dial.getContentPane();
55       pane.setLayout(new BorderLayout());
56       list = new JList(entries.toArray());
57       list.addListSelectionListener(this);
58       listscroller = new JScrollPane(list);
59       pane.add(listscroller,BorderLayout.WEST);
60       JPanel actions = new JPanel();
61       JButton button = new JButton(OK);
62       button.addActionListener(this);
63       actions.add(button);
64       button = new JButton(NEW);
65       button.addActionListener(this);
66       actions.add(button);
67   //    button = new JButton(DEL);
68   //    button.addActionListener(this);
69   //    actions.add(button);
70       button = new JButton(READ);
71       button.addActionListener(this);
72       actions.add(button);
73       button = new JButton(SAVE);
74       button.addActionListener(this);
75       actions.add(button);
76       button = new JButton(ADDIMAGE);
77       button.addActionListener(this);
78       actions.add(button);
79       button = new JButton(DELSEC);
80       button.addActionListener(this);
81       actions.add(button);
82       pane.add(actions,BorderLayout.SOUTH);
83   
84       contents.add(Carto.runversion.getAbout());
85       pane.add(scroller=getView(),BorderLayout.CENTER);
86   
87       dial.setSize(new Dimension(700,700));
88       dial.show();
89       list.setSelectedValue(ABOUT,true);
90     }
91   
92     public JScrollPane getView() {
93       Container viewbox = new JPanel();
94       viewbox.setLayout(new BoxLayout(viewbox,BoxLayout.Y_AXIS));
95       viewbox.setBackground(Color.white);
96       viewers.clear();
97       JComponent field=null;
98       for (Iterator it = contents.iterator();it.hasNext();) {
99         Object item = it.next();
100        if (item instanceof String)
101          field = new JTextArea((String)item);
102        else if (item instanceof File) {
103          File myfile = new File(HELP+"/"+((File)item).getName());
104          field = new JLabel(new ImageIcon(myfile.getPath()));
105        }
106        field.setAlignmentX(0);
107        field.addFocusListener(this);
108        viewers.add(field);
109        viewbox.add(field);
110      }
111      return(new JScrollPane(viewbox));
112    }
113  
114    public void valueChanged(ListSelectionEvent e) {
115      if (list.getSelectedValue()==null) return;
116      curname = (String)list.getSelectedValue();
117      Object content = read(curname);
118      dial.setTitle("Help - "+curname);
119      edit(content);
120    }
121  
122    public void edit(Object content) {
123  
124      if (content instanceof String) {
125        contents.clear();
126        contents.add(content);
127      }
128      else if (content instanceof Vector)
129        contents = (Vector)content;
130  
131      pane.remove(scroller);
132      scroller = getView();
133      pane.add(scroller,BorderLayout.CENTER);
134      pane.validate();
135    }
136  
137    public Object read(String name) {
138      if (name == ABOUT) return(Carto.runversion.getAbout());
139  
140      try {
141        FileInputStream istream = new FileInputStream(HELP+"/"+name+".str");
142        Object ob = (new ObjectInputStream(istream)).readObject();
143        
144        if (ob instanceof String ||
145            ob instanceof Vector) {
146          return(ob);
147        } else throw new IOException();
148  
149      } catch (Throwable e) {
150        return("No help for "+name);
151      }
152    }
153  
154    public void actionPerformed(ActionEvent e) {
155      if (e.getSource() instanceof AbstractButton) {
156        String command = ((AbstractButton)e.getSource()).getActionCommand();
157        if (command==NEW) {
158          String name = JOptionPane.showInputDialog("Name of new help subject");
159          entries.add(name);
160          pane.remove(listscroller);
161          list = new JList(entries.toArray());
162          list.addListSelectionListener(this);
163          listscroller = new JScrollPane(list);
164          pane.add(listscroller,BorderLayout.WEST);
165          list.setSelectedValue(name,true);
166          dial.validate();
167        }
168        else if (command==SAVE) {
169  //        String content = text.getText();
170          String name = HELP+"/"+curname+".str";
171          toContents();
172          try {
173            OutputStream ostream = new FileOutputStream(name);
174            (new ObjectOutputStream(ostream)).writeObject(contents);
175          } catch (IOException ex) {
176            ErrorLog.exception(ex,"Couldn't write help file:"+name);
177          }
178        }
179        else if (command==DELSEC) {
180          toContents();
181          if (focusindex>=0) contents.removeElementAt(focusindex);
182          edit(contents);
183        }
184        else if (command==READ) {
185          toContents();
186          try {
187            JFileChooser choose = Persist.current.getFileChooser();
188            choose.setFileFilter(new FileTypes(FileTypes.ANY));
189            choose.rescanCurrentDirectory();
190            if (choose.showOpenDialog(dial)!=choose.APPROVE_OPTION) return;
191            File f = choose.getSelectedFile();
192  
193            byte[] bytes = new byte[(int)f.length()];
194            (new FileInputStream(f)).read(bytes);
195            if (focusindex>=0&&cursor!=-1) {
196              String old = (String)contents.elementAt(focusindex);
197              contents.setElementAt(old.substring(0,cursor) +
198          			  new String(bytes) +
199          			  old.substring(cursor,old.length()),
200          			  focusindex);
201              edit(contents);
202            }
203            else edit(new String(bytes));
204          } catch (IOException ex) {ErrorLog.exception(ex);}
205        }
206        else if (command==OK) {
207          dial.dispose();
208        }
209        else if (command==ADDIMAGE) {
210  
211          JFileChooser choose = new JFileChooser();
212          choose.setFileFilter(new FileTypes(FileTypes.IMAGE));
213          choose.rescanCurrentDirectory();
214          if (choose.showOpenDialog(dial)!=choose.APPROVE_OPTION) return;
215          File f = choose.getSelectedFile();
216  
217          if (!f.getParentFile().equals(new File(HELP))) {
218            File newname = new File(HELP+"/"+f.getName());
219            f.renameTo(newname);
220            f = newname;
221          }
222          toContents();
223          if (focusindex>=0) {
224            contents.add(focusindex+1,f);
225            if (cursor!=-1) {
226              String old = (String)contents.elementAt(focusindex);
227              contents.setElementAt(old.substring(0,cursor),focusindex);
228              contents.add(focusindex+2,old.substring(cursor,old.length()));
229            }
230          }
231          else {
232            contents.add(f);
233            contents.add("  ");
234          }
235          edit(contents);
236        }
237      }
238    }
239  
240    public void focusGained(FocusEvent e) {
241      if (viewers.contains(e.getComponent()))
242        focusindex = viewers.indexOf(e.getComponent());
243    }
244  
245    public void focusLost(FocusEvent e) {
246    }
247  
248    void toContents() {
249      JComponent item = null;
250      for (int i=0;i<viewers.size();i++) {
251        item = (JComponent) viewers.elementAt(i);
252        if (item instanceof JTextArea) {
253          contents.setElementAt(((JTextArea)item).getText(),i);
254        }
255      }
256        
257      if (focusindex>=0 && (viewers.elementAt(focusindex) instanceof JTextArea))
258        cursor = ((JTextArea)viewers.elementAt(focusindex)).getCaretPosition();
259      else cursor = -1;
260    }
261  
262    public static void showFile(Component parent,String name,String title) {
263      try {
264        File f = new File(name);
265        byte[] bytes = new byte[(int)f.length()];
266        JTextArea text;
267        (new FileInputStream(f)).read(bytes);
268        JScrollPane pane = new JScrollPane(text = new JTextArea(new String(bytes)));
269        pane.setSize(new Dimension(700,700));
270        pane.setPreferredSize(new Dimension(700,700));
271        pane.getVerticalScrollBar().setValue(0);
272        text.setCaretPosition(0);
273        JOptionPane.showMessageDialog(parent,pane,
274          			    title,JOptionPane.PLAIN_MESSAGE);
275      } catch (IOException e) {
276        ErrorLog.exception(e,"Could not read "+name);
277      }
278    }
279  
280    public static void about(Component parent) {
281      JOptionPane.showMessageDialog(parent,Carto.runversion.getAbout(),"About Carto",JOptionPane.PLAIN_MESSAGE);
282    }
283  
284  }
285  
286  
287