001    /* BEE - Book Editing Environment for PAVLOV
002     * Copyright (C) 2004 T.J. Willis
003     * 
004     * This program is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU General Public License
006     * as published by the Free Software Foundation; either version 2
007     * of the License, or (at your option) any later version.
008     * 
009     * This program is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     * GNU General Public License for more details.
013     * 
014     * You should have received a copy of the GNU General Public License
015     * along with this program; if not, write to the Free Software
016     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
017     *
018     * $Header: /cvsroot/pavlov/net/sourceforge/bee/ChapterEditor.java,v 1.7 2004/07/01 05:50:19 tj_willis Exp $
019     */
020    package net.sourceforge.bee;
021    
022    import javax.swing.*;
023    import javax.swing.event.*;
024    import java.text.DecimalFormat;
025    import java.awt.*;
026    import java.awt.event.*;
027    import net.sourceforge.pavlov.library.*;
028    import java.util.*;
029    import java.net.URL;
030    
031    /**
032     * User interface for editing a chapter within a book.
033     *
034     * @author <a href="mailto:tj_willis@users.sourceforge.net">T.J. Willis</a>
035     * @version $Id: ChapterEditor.java,v 1.7 2004/07/01 05:50:19 tj_willis Exp $
036     */
037    public class ChapterEditor 
038        extends JInternalFrame
039        implements ActionListener, ListSelectionListener
040    {
041        //private JLabel lTitle, lAuthor, lDescription;
042        private JTextField fTitle, fAuthor;
043        private JTextArea aDescription;
044        //private Box bQuestions;
045        private ListSelectionJTable tQuestions;
046        private ChapterTableModel tmod;
047        private JButton bUpdate;
048        private JMenuItem byID,byText,byRightAnswer;
049        private JMenuItem copy, paste, insert, inserts, delete, mUndo, mNormalize, mDruid;
050        private String  cName;
051        private Object clipboard;
052        private java.util.List undo;
053        private Chapter chapter;
054        private BookEditor bookEditor;
055        private long base = 0;
056        private QuestionDruid druid;
057        private InsertMultipleFrame wiz;
058        private AbstractAction copyAction, pasteAction, insertAction, deleteAction;
059        private AbstractAction insertMultipleAction, questionDruidAction, sortByIDAction;
060        private AbstractAction undoAction, normalizeAction, smallerRowsAction;
061        private AbstractAction biggerRowsAction;
062    
063        /**
064         * Creates a new <code>ChapterEditor</code> instance, editing the given
065         * chapter and registering itself as an open editor of the given 
066         * bookEditor.
067         *
068         * @param parent a <code>BookEditor</code> value
069         * @param c a <code>Chapter</code> value
070         */
071        public ChapterEditor(BookEditor parent,Chapter c)
072        {
073            super("Chapter Editor",true,true,true);
074            bookEditor = parent;
075            chapter = c;
076            cName = c.getName();
077            super.setTitle("Chapter Editor");
078            setResizable(true);
079    
080            Container content = getContentPane();
081            content.setLayout(new BorderLayout());
082          
083            Collection<Question> col = chapter.getQuestionsCollection();
084            // guaranteed 1 question by bookeditor/create chapter
085            Question arr[] = new Question[1];
086            arr = (Question [])col.toArray(arr);  
087            tmod = new ChapterTableModel(arr);
088    
089            Box box = new Box(BoxLayout.Y_AXIS);
090          
091            JPanel pan = new JPanel();
092            pan.setLayout(new java.awt.GridLayout(2,1));
093    
094            Box b0 = new Box(BoxLayout.Y_AXIS);
095            Box b1 = new Box(BoxLayout.X_AXIS);
096            Box b2 = new Box(BoxLayout.X_AXIS);
097          
098            b1.setBorder( BorderFactory.createTitledBorder( "Title" ) );
099            b2.setBorder( BorderFactory.createTitledBorder( "Author" ) );
100    
101            //lTitle = new JLabel("Title:");
102            //lTitle.setMinimumSize(new Dimension(50,20));
103            fTitle = new JTextField();
104            fTitle.addActionListener(this);
105            b1.add(fTitle);
106            pan.add(b1);
107    
108            //lAuthor = new JLabel("Author:");
109            //lAuthor.setMinimumSize(new Dimension(50,20));
110            fAuthor = new JTextField();
111            fAuthor.addActionListener(this);
112            b2.add(fAuthor);
113    
114            pan.add(b2);
115    
116            b0.add(pan);
117    
118            Box b3 = new Box(BoxLayout.X_AXIS);
119            b3.setBorder( BorderFactory.createTitledBorder( "Description" ) );
120            aDescription = new JTextArea();
121            JScrollPane sp1 = new JScrollPane(aDescription);
122            bUpdate = new JButton("Update");
123            bUpdate.addActionListener(this);
124            b3.add(sp1);
125            b3.add(bUpdate);
126            b0.add(b3);
127            box.add(b0);
128    
129            Box b4 = new Box(BoxLayout.X_AXIS);
130            b4.setBorder( BorderFactory.createTitledBorder( "Questions" ) );
131            tQuestions = new ListSelectionJTable(tmod);
132            tQuestions.addListSelectionListener((ListSelectionListener)this);
133            tmod.addTableModelListener(tQuestions);//FIXME: might be redundant
134            tQuestions.setDragEnabled(true);
135            //String la = new String();
136            Class cl = null;
137            try {
138                cl = java.lang.Class.forName("java.lang.String");
139            } catch (Exception e) {
140            // FIXME: don't ignore exception
141            }
142            VerificationTableCellRenderer r = new VerificationTableCellRenderer(tmod);
143            // 15feb tQuestions.setDefaultRenderer(cl,r);
144            JScrollPane sp = new JScrollPane(tQuestions);
145            b4.add(sp);
146            box.add(b4);
147            //======================== test ======================
148            //TableCellEditor tce = tQuestions.getCellEditor(3,3);
149            //Component charlie =  tQuestions.prepareEditor(tce,3,3);
150            //charlie.setBackground(Color.red);
151            //charlie.setForeground(Color.yellow);
152            //======================== test ======================
153            Box b5 = new Box(BoxLayout.X_AXIS);
154            box.add(b5);
155    
156            content.add(box,BorderLayout.CENTER);
157    
158            //============================================================
159            // DEFINE ACTIONS
160    
161            copyAction = ( new AbstractAction() {
162                    public void actionPerformed(ActionEvent e) {
163                        copy(); 
164                    }
165                }
166                           );
167            copyAction.putValue(Action.NAME,"Copy");
168            copyAction.putValue(Action.SHORT_DESCRIPTION,"Copy Selected Question");
169    
170            pasteAction = ( new AbstractAction() {
171                    public void actionPerformed(ActionEvent e) {
172                        paste(); 
173                    }
174                }
175                            );
176            pasteAction.putValue(Action.NAME,"Paste");
177            pasteAction.putValue(Action.SHORT_DESCRIPTION,"Paste Question in Clipboard");
178    
179            insertAction = ( new AbstractAction() {
180                    public void actionPerformed(ActionEvent e) {
181                        insert(); 
182                    }
183                }
184                             );
185            insertAction.putValue(Action.NAME,"Insert");
186            insertAction.putValue(Action.SHORT_DESCRIPTION,"Insert Question(s)");
187        
188            deleteAction = ( new AbstractAction() {
189                    public void actionPerformed(ActionEvent e) {
190                        delete(); 
191                    }
192                }
193                             );
194            deleteAction.putValue(Action.NAME,"Delete");
195            deleteAction.putValue(Action.SHORT_DESCRIPTION,"Delete Selected Question(s)");
196            
197            insertMultipleAction = ( new AbstractAction() {
198                    public void actionPerformed(ActionEvent e) {
199                        insertWizard(); 
200                    }
201                }
202                                     );
203            insertMultipleAction.putValue(Action.NAME,"Add Blank...");
204            insertMultipleAction.putValue(Action.SHORT_DESCRIPTION,"Add Blank Questions");
205    
206            questionDruidAction = ( new AbstractAction() {
207                    public void actionPerformed(ActionEvent e) {
208                        druid(); 
209                    }
210                }
211                                    );
212            questionDruidAction.putValue(Action.NAME,"Factory...");
213            questionDruidAction.putValue(Action.SHORT_DESCRIPTION,"Generate Many Questions at Once");
214    
215            sortByIDAction = ( new AbstractAction() {
216                    public void actionPerformed(ActionEvent e) {
217                        tmod.sortByID(); 
218                    }
219                }
220                               );
221            sortByIDAction.putValue(Action.NAME,"Sort");
222            sortByIDAction.putValue(Action.SHORT_DESCRIPTION,"Sort Questions by ID");
223    
224            normalizeAction = ( new AbstractAction() {
225                    public void actionPerformed(ActionEvent e) {
226                        normalizeIDs(); 
227                    }
228                }
229                                );
230            normalizeAction.putValue(Action.NAME,"Normalize");
231            normalizeAction.putValue(Action.SHORT_DESCRIPTION,"Reassign Question ID's Sequentially");
232    
233            undoAction = ( new AbstractAction() {
234                    public void actionPerformed(ActionEvent e) {
235                        undo(); 
236                    }
237                }
238                           );
239            undoAction.putValue(Action.NAME,"Undo");
240            undoAction.putValue(Action.SHORT_DESCRIPTION,"Undo");
241    
242    
243            smallerRowsAction = ( new AbstractAction() {
244                    public void actionPerformed(ActionEvent e) {
245                        smallerRows(); 
246                    }
247                }
248                                  );
249            smallerRowsAction.putValue(Action.NAME,"Smaller Rows");
250            smallerRowsAction.putValue(Action.SHORT_DESCRIPTION,"Decrease Height of Rows");
251    
252            biggerRowsAction = ( new AbstractAction() {
253                    public void actionPerformed(ActionEvent e) {
254                        biggerRows(); 
255                    }
256                }
257                                 );
258            biggerRowsAction.putValue(Action.NAME,"Bigger Rows");
259            biggerRowsAction.putValue(Action.SHORT_DESCRIPTION,"Increase Height of Rows");
260    
261            undoAction.setEnabled(false);
262            copyAction.setEnabled(false);
263            pasteAction.setEnabled(false);
264            insertAction.setEnabled(false);
265            deleteAction.setEnabled(false);
266    
267            //============================================================
268    
269            JMenuBar menu = new JMenuBar();
270    
271            JMenu edit = new JMenu("Edit");
272            copy  =makeJMenuItem(copyAction,"resources/icons/tb_copy.jpg");
273            paste  =makeJMenuItem(pasteAction,"resources/icons/tb_paste.jpg");
274            insert=makeJMenuItem(insertAction,"resources/icons/tb_insert.jpg");
275            delete = makeJMenuItem(deleteAction,"resources/icons/tb_delete.jpg");
276            mUndo = makeJMenuItem(undoAction,"resources/icons/tb_undo.jpg");
277    
278            edit.add(copy);
279            edit.add(paste);
280            edit.add(insert);
281            edit.add(delete);
282            edit.addSeparator();
283            edit.add(mUndo);
284    
285            JMenu tools = new JMenu("Tools");
286            inserts = makeJMenuItem(insertMultipleAction,"resources/icons/tb_add_multiple.jpg");
287            //new JMenuItem("Add Blank Questions...");
288            mNormalize = makeJMenuItem(normalizeAction,"resources/icons/normalize.jpg");
289            mDruid = makeJMenuItem(questionDruidAction,"resources/icons/questiondruid.jpg");
290            tools.add(inserts);
291            tools.add(mNormalize);
292            tools.add(mDruid);
293    
294            JMenu sort = new JMenu("Sort");
295            byID = makeJMenuItem(sortByIDAction,"resources/icons/tb_sort.jpg");
296            new JMenuItem("By ID");
297            byText = new JMenuItem("By Question Text");
298            byRightAnswer = new JMenuItem("By Correct Answer");
299            sort.add(byID);
300            sort.add(byText);
301            sort.add(byRightAnswer);
302            byText.addActionListener(this);
303            byRightAnswer.addActionListener(this);
304    
305    
306            menu.add(edit);
307            menu.add(tools);
308            menu.add(sort);
309    
310            setJMenuBar(menu);
311    
312            //======================== toolbar  ======================
313            JToolBar toolbar = new JToolBar("BookEditor Tools");
314            toolbar.setRollover(true);
315    
316            JButton s1 =makeJButton(copyAction,"resources/icons/tb_copy.jpg");
317            JButton s2 =makeJButton(pasteAction,"resources/icons/tb_paste.jpg");
318            JButton s3 =makeJButton(insertAction,"resources/icons/tb_insert.jpg");
319            JButton s4 = makeJButton(deleteAction,"resources/icons/tb_delete.jpg");
320            JButton s5 = makeJButton(undoAction,"resources/icons/tb_undo.jpg");
321            JButton s6 = makeJButton(insertMultipleAction,"resources/icons/tb_add_multiple.jpg");
322            //new JMenuItem("Add Blank Questions...");
323            JButton s7= makeJButton(normalizeAction,"resources/icons/normalize.jpg");
324            JButton s8 = makeJButton(questionDruidAction,"resources/icons/questiondruid.jpg");
325            JButton s9 = makeJButton(sortByIDAction,"resources/icons/tb_sort.jpg");
326            JButton s10 = makeJButton(smallerRowsAction,"resources/icons/smaller_rows.jpg");
327            JButton s11 = makeJButton(biggerRowsAction,"resources/icons/bigger_rows.jpg");
328            toolbar.add(s1);
329            toolbar.add(s2);
330            toolbar.add(s3);
331            toolbar.add(s4);
332            toolbar.addSeparator();
333            toolbar.add(s5);
334            toolbar.add(s6);                        
335            toolbar.addSeparator();
336            toolbar.add(s7);
337            toolbar.add(s8);
338            toolbar.add(s9);
339            toolbar.add(s10);
340            toolbar.add(s11);
341    
342            content.add(toolbar,BorderLayout.PAGE_START);
343    
344            //======================== test ======================
345            TabDelimitedTransferHandler th = new TabDelimitedTransferHandler(tmod);
346    
347            setTitle(c.getName());
348            setAuthor(c.getAuthor());
349            setDescription(c.getDescription());
350            pack();
351    
352        }
353    
354        /**
355         * Sets the title of this chapter <b>not the internalframe</b>.  
356         * FIXME: change this method name.
357         * @param t a <code>String</code> value
358         */
359        public void setTitle(String t)
360        {
361            fTitle.setText(t);
362            chapter.setName(t);
363        }
364        private void setAuthor(String t)
365        {
366            fAuthor.setText(t);
367            chapter.setAuthor(t);
368        }
369        private void setDescription(String t)
370        {
371            aDescription.setText(t);
372            chapter.setDescription(t);
373        }
374    
375        private void smallerRows()
376        {
377            int x = tQuestions.getRowHeight();
378            x-=5;
379            if(x<10) x = 10;
380            tQuestions.setRowHeight(x);
381        }
382    
383        private void biggerRows()
384        {
385            int x = tQuestions.getRowHeight();
386            x+=5;
387            //if(x<10) x = 10;
388            tQuestions.setRowHeight(x);
389        }
390    
391    
392        /**
393         * Overridden to remove references to this chapter editor and closes any
394         * dependent windows.
395         *
396         */
397        public void dispose()
398        {
399            bookEditor.removeEditorKey(chapter.getName());
400            //      JOptionPane.showInternalMessageDialog(bookEditor.getDesktopPane(), 
401            //                                        "Changes to this chapter will be saved when you save this book.", 
402            //                                        "Information", 
403            //                                        JOptionPane.INFORMATION_MESSAGE);
404            if(wiz!=null) wiz.dispose();
405            if(druid!=null) druid.dispose();
406            super.dispose();
407        }
408    
409        private void copy()
410        {
411            int rc = tQuestions.getSelectedRowCount();
412            if(rc<1) return;
413            else if(rc==1)
414                { 
415                    copyOneRow();
416                    return;
417                }
418            else 
419                copyMultipleRows();
420        }
421    
422        private void copyOneRow()
423        {
424            int row = tQuestions.getSelectedRow();
425            if(row<0) return;
426            Question q = tmod.getQuestion(row);
427            clipboard = q.deepCopy();
428            clipboardActive(true);
429        }
430    
431        private void copyMultipleRows()
432        {
433            clipboard = new Vector();
434            int rs[] = tQuestions.getSelectedRows();
435            int x = java.lang.reflect.Array.getLength(rs);
436            for(int i=0;i<x;i++)
437                {
438                    Question q = tmod.getQuestion(rs[i]);
439                    Question r = q.deepCopy();
440                    r.setId(getUniqueID());
441                    ((Vector)clipboard).add(r);
442                }
443            clipboardActive(true);
444        }
445    
446    
447        // sets the chapter's questions to the tablemodel's questions
448        private void synchChapter()
449        {
450            java.util.List<Question> qs = tmod.getQuestions();
451            chapter.setQuestions(qs);
452    
453        }
454    
455        private void paste()
456        {
457            if(clipboard==null) return;
458    
459            if(clipboard instanceof Question)
460                {
461                    pasteSingleRow();
462                }
463            else if(clipboard instanceof Vector)
464                {
465                    pasteMultipleRows();
466                }
467        }
468    
469        private void pasteSingleRow()
470        {
471            int row = tQuestions.getSelectedRow();
472            if(row<0) return;
473            Question q = (Question) clipboard;
474            setUndo(true);
475            q.setId(getUniqueID());
476            tmod.setQuestion(row,q.deepCopy());
477            synchChapter();
478            clipboardActive(false);
479        }
480    
481    
482        private void pasteMultipleRows()
483        {
484            int rs[] = tQuestions.getSelectedRows();
485            int x = java.lang.reflect.Array.getLength(rs);
486            if(!(clipboard instanceof Vector))
487                return;
488            Vector c = (Vector) clipboard;
489            int y = c.size();
490            if(x!=y) return;
491    
492            setUndo(true);
493            for(int i=0;i<x;i++)
494                {
495                    Question q = (Question)c.elementAt(i);
496                    Question r = q.deepCopy();
497                    r.setId(getUniqueID());
498                    synchChapter();
499                    tmod.setQuestion(rs[i],r);
500                }
501            synchChapter();
502            clipboardActive(false);
503        }
504    
505        private void delete()
506        {
507            int rc = tQuestions.getSelectedRowCount();
508            if(rc<1) return;
509            else if(rc==1)
510                { 
511                    deleteOneRow();
512                    return;
513                }
514            else 
515                deleteMultipleRows();
516        }
517    
518        private void deleteOneRow()
519        {
520            int row = tQuestions.getSelectedRow();
521            if(row<0) return; 
522            setUndo(true);
523            tmod.deleteQuestion(row);
524            synchChapter();
525            clipboardActive(false);
526        }
527    
528        private void deleteMultipleRows()
529        {
530            int rs[] = tQuestions.getSelectedRows();
531            setUndo(true);
532            tmod.deleteQuestions(rs);
533            synchChapter();
534            clipboardActive(false);
535        }
536    
537        private void insert()
538        {
539            if(clipboard instanceof Question)
540                insertOneRow();
541            if(clipboard instanceof Vector)
542                insertMultipleRows();
543        }
544    
545    
546        private void insertOneRow()
547        {
548            Question tmp;
549            if(clipboard!=null) 
550                tmp = (Question)clipboard;
551            else { 
552                tmp = Question.makeBlankQuestion();
553            }
554            tmp = tmp.deepCopy();
555            tmp.setId(getUniqueID());
556            setUndo(true);   // much easier to duplicate this code for undos
557            int row = tQuestions.getSelectedRow();
558            if(row<0) row = 0;
559            tmod.insertQuestion(row,tmp);
560            synchChapter();
561            clipboardActive(false);
562        }
563    
564    
565        private void insert(Question q)
566        {
567            int row = tQuestions.getSelectedRow();
568            if(row<0) row = 0;
569            q.setId(getUniqueID());
570            tmod.insertQuestion(row,q.deepCopy());
571            synchChapter();
572        }
573    
574        private void insertMultipleRows()
575        {
576            int r = tQuestions.getSelectedRow();
577            if(!(clipboard instanceof Vector))
578                return;
579            Vector c = (Vector) clipboard;
580            int y = c.size();
581            setUndo(true);
582            for(int i=0;i<y;i++)
583                {
584                    Question q = (Question)c.elementAt(i);
585                    q = q.deepCopy();
586                    q.setId(getUniqueID());
587                    tmod.insertQuestion(r,q);
588                    synchChapter(); // if you don't do it here, ids wont be unique
589                }
590            clipboardActive(false);
591        }
592    
593        /**
594         * Allows other classes to add a vector of generated questions to this
595         * chapter.  Note that ID's may be changed to ensure uniqueness.
596         *
597         * @param v a <code>Vector</code> value
598         */
599        public void addGenerated(Vector<Question> v)
600        {
601            setUndo(true);
602            for(Question da: v) {
603                // insert assigns unique ID
604                insert(da);
605            }
606            synchChapter();
607        }
608    
609        private void normalizeIDs()
610        {
611            String msg = "<HTML>Normalizing IDs is not suggested for chapters<BR>" +
612                "that have already been used in Pavlov.  Question IDs are<BR>" +
613                "cross-referenced in user files.  <BR>" +
614                "Do you really want to normalize ID's?";
615            int ret = 
616                JOptionPane.showInternalConfirmDialog(getDesktopPane(), 
617                                                      msg,
618                                                      "Normalize IDs",
619                                                      JOptionPane.YES_NO_OPTION);
620            if( ret == JOptionPane.NO_OPTION) 
621                return;
622    
623            DecimalFormat nf = new DecimalFormat("00000");
624    
625            for(int i=0;i<tmod.getRowCount();i++) {
626                tmod.setValueAt(nf.format(i), i, 0);
627            }
628            synchChapter();
629        }
630    
631        private String getUniqueID()
632        {
633            DecimalFormat nf = new DecimalFormat("00000");
634        
635            for(long i=base;i<99999;i++)
636                {
637                    String x = nf.format(i);
638                    Question q = chapter.getQuestion(x);
639                    if(q==null) 
640                        {
641                            base = i;
642                            return x;
643                        }
644                }
645            return "TOOMANY";
646        }
647    
648    
649        private void insertWizard()
650        {
651            if(wiz==null){
652                wiz = new InsertMultipleFrame(this);
653                getDesktopPane().add(wiz);
654            }
655            wiz.setVisible(true);
656            try { wiz.setSelected(true); } catch (Exception e) {}
657        }
658    
659        private void druid()
660        {
661            if(druid==null){
662                druid = new QuestionDruid(this);
663                getDesktopPane().add(druid);
664            }
665            druid.setVisible(true);
666            try { druid.setSelected(true); } catch (Exception e) {}
667    
668        }
669    
670        private void setUndo(boolean state)
671        {
672            if(state==true)
673                {
674                    undoAction.setEnabled(true);
675                    undo = tmod.getQuestions();
676                }
677            else
678                {
679                    undoAction.setEnabled(false);
680                    undo = null;
681                }
682        }
683    
684        private void undo()
685        {
686            if(undo==null) return;
687            tmod.setQuestions(undo);
688            undo = null;
689            setUndo(false);
690            synchChapter();
691        }
692    
693        private void clipboardActive(boolean state)
694        {
695            pasteAction.setEnabled(state);
696        }
697    
698        /**
699         * Handles menu events.
700         *
701         * @param e an <code>ActionEvent</code> value
702         */
703        public void actionPerformed(ActionEvent e)
704        {
705            if(e.getSource().equals(byText))
706                tmod.sortByText();
707            else if(e.getSource().equals(byRightAnswer))
708                tmod.sortByRightAnswer();
709            else if(e.getSource().equals(copy))
710                copy();
711            else if(e.getSource().equals(paste))
712                paste();
713            else if(e.getSource().equals(insert))
714                insert();
715            else if(e.getSource().equals(delete))
716                delete();
717            else if(e.getSource().equals(inserts))
718                insertWizard();
719            else if(e.getSource().equals(mDruid))
720                druid();
721            else if(e.getSource().equals(fTitle))
722                editTitle();
723            else if(e.getSource().equals(fAuthor))
724                editAuthor();
725            else if(e.getSource().equals(aDescription))
726                editDescription();
727            else if(e.getSource().equals(bUpdate))
728                editDescription();
729        }
730    
731        private void editTitle()
732        {
733            // FIXME: check that it's unique
734            String t = fTitle.getText();
735            if(!validCharacters(t))
736                {
737                    // FIXME: add a convenience method for JOptionPane....
738                    JOptionPane.showInternalMessageDialog(getDesktopPane(), 
739                                                          "Invalid Characters in Title", 
740                                                          "Invalid Characters in Title", 
741                                                          JOptionPane.INFORMATION_MESSAGE);
742                    return;
743                }
744            bookEditor.changeEditorKey(t,cName);
745            cName = t; 
746            chapter.setName(t); 
747        }
748    
749        private void editAuthor()
750        {
751            String t = fAuthor.getText();
752            if(!validCharacters(t))
753                {
754                    JOptionPane.showInternalMessageDialog(getDesktopPane(), 
755                                                          "Invalid Characters in Author", 
756                                                          "Invalid Characters in Author", 
757                                                          JOptionPane.INFORMATION_MESSAGE);
758                    return;
759                }
760            chapter.setAuthor(t); 
761        }
762    
763    
764    
765        private void editDescription()
766        {
767            String t = aDescription.getText();
768            if(!validCharacters(t))
769                {
770                    JOptionPane.showInternalMessageDialog(getDesktopPane(), 
771                                                          "Invalid Characters in Description", 
772                                                          "Invalid Characters in Description", 
773                                                          JOptionPane.INFORMATION_MESSAGE);
774                    return;
775                }
776            //System.out.println("Did edit description");
777            chapter.setDescription(t); 
778        }
779    
780        private boolean validCharacters(String s)
781        {
782            if(s.indexOf('<')>0) return false;
783            if(s.indexOf('\"')>0) return false;
784            if(s.indexOf('&')>0) return false;
785            return true;
786        }
787    
788    
789        private JMenuItem makeJMenuItem(Action ac, String url)
790        {
791            JMenuItem x = new JMenuItem(ac);
792            //x.setText(ac.getProperty(Action.NAME));
793            try {
794                URL u = new URL("file:" + url);//getClass().getResource(url);
795                ImageIcon tmp = new ImageIcon(u);
796                x.setIcon(tmp  );
797            } catch (Exception e) {}
798            return x;
799        }
800    
801    
802        private JButton makeJButton(Action ac, String url)
803        {
804            JButton x = new JButton(ac);
805            //x.setText(ac.getProperty(Action.Name));
806            try {
807                URL u = new URL("file:"+url);//getClass().getResource(url);
808                ImageIcon tmp = new ImageIcon(u);
809                x.setIcon(tmp  );
810                Font g = x.getFont();
811                int style = g.getStyle();
812                String n = g.getFontName();
813                Font f = new Font(n,style,8);
814                x.setFont(f);
815                x.setVerticalTextPosition(SwingConstants.BOTTOM);
816                x.setHorizontalTextPosition(SwingConstants.CENTER);
817            } catch (Exception e) {}
818            return x;
819    
820        }
821    
822        private void noRowsSelected()
823        {
824            copyAction.setEnabled(false);
825            pasteAction.setEnabled(false);
826            insertAction.setEnabled(false);
827            deleteAction.setEnabled(false);
828        }
829    
830        private void oneRowSelected()
831        {
832            copyAction.setEnabled(true);
833            pasteAction.setEnabled(true);
834            insertAction.setEnabled(true);
835            deleteAction.setEnabled(true);
836        }
837    
838        private void multipleRowsSelected()
839        {
840            copyAction.setEnabled(true);
841            pasteAction.setEnabled(true);
842            insertAction.setEnabled(true);
843            deleteAction.setEnabled(true);
844        }
845    
846        /**
847         * Called when the row selection of the JTable has changed.
848         *
849         * @param e a <code>ListSelectionEvent</code> value
850         */
851        public void valueChanged(ListSelectionEvent e)
852        {
853            int i = tQuestions.getSelectedRowCount();
854            if(i<1)
855                noRowsSelected();
856            else if(i==1)
857                oneRowSelected();
858            else
859                multipleRowsSelected();
860        }
861    }
862    
863    
864    
865    
866