001    /* PAVLOV -- Multiple Choice Study System
002     * Copyright (C) 2000 - 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/pavlov/pluglets/feedback/random/RandomImage.java,v 1.9 2004/07/01 05:50:20 tj_willis Exp $
019     */ 
020    package net.sourceforge.pavlov.pluglets.feedback.random;
021    
022    
023    import javax.swing.*;
024    import java.awt.Dimension;
025    import java.awt.event.*;
026    import java.net.URL;
027    
028    import net.sourceforge.pavlov.event.*;
029    import net.sourceforge.pavlov.randommedia.RandomImageFactory;
030    import net.sourceforge.pavlov.randommedia.ImageIconUtilities;
031    import net.sourceforge.pavlov.feedback.old.*;
032    //import net.sourceforge.pavlov.user.Bookmark;
033    import net.sourceforge.pavlov.user.User;
034    import net.sourceforge.pavlov.randommedia.CacheObject;
035    import net.sourceforge.pavlov.event.MediaRootChangedListener;
036    import net.sourceforge.pavlov.zipUtilities.DirectoryJarFileFilter;
037    import net.sourceforge.pavlov.swing.HashtableJRadioButtonMenu;
038    import org.apache.log4j.*;
039    
040    /**
041     * <code>RandomImage</code> is a concrete example of a user feedback module.
042     * @author <a href="mailto:"></a>
043     * @version $Revision: 1.9 $
044     */
045    public class RandomImage extends AbstractFeedbackPanel
046        implements AnswerListener, ActionListener, MediaRootChangedListener {
047        //protected JLabel txt;
048        public static final String PLUGLET_FEEDBACK_IMAGE_RANDOM = "pluglet.feedback.image.random";
049        public static final String PLUGLET_FEEDBACK_IMAGE_RANDOM_DESCRIPTION = "pluglet.feedback.image.random.description";
050    
051        /**
052         * Describe variable <code>size</code> here.
053         *
054         */
055        protected int size = -1;
056        /**
057         * Describe variable <code>logo</code> here.
058         *
059         */
060        protected Icon logo;
061        /**
062         * Describe variable <code>rights</code> here.
063         *
064         */
065        protected  int rights = 0; 
066        /**
067         * Describe variable <code>ifac</code> here.
068         *
069         */
070        protected  RandomImageFactory ifac;
071        /**
072         * Describe variable <code>mode</code> here.
073         *
074         */
075        protected DefaultVisualFeedbackMode mode;
076        /**
077         * Describe variable <code>beginner</code> here.
078         *
079         */
080        protected  BeginnerFeedbackMode beginner;
081        /**
082         * Describe variable <code>intermed</code> here.
083         *
084         */
085        protected IntermediateFeedbackMode intermed;
086        /**
087         * Describe variable <code>expert</code> here.
088         *
089         */
090        protected ExpertFeedbackMode expert;
091        /**
092         * Describe variable <code>cacheObject</code> here.
093         *
094         */
095        protected CacheObject cacheObject;
096        /**
097         * Describe variable <code>screenSize</code> here.
098         *
099         */
100        protected Dimension screenSize;
101        /**
102         * Describe variable <code>scroller</code> here.
103         *
104         */
105        protected JScrollPane scroller;
106        /**
107         * Describe variable <code>refreshItem</code> here.
108         *
109         */
110        protected JMenuItem refreshItem;
111        /**
112         * Describe variable <code>chooseItem</code> here.
113         *
114         */
115        protected JMenuItem chooseItem;
116        /**
117         * Describe variable <code>begin</code> here.
118         *
119         */
120        protected JMenuItem begin;
121        /**
122         * Describe variable <code>inter</code> here.
123         *
124         */
125        protected JMenuItem inter;
126        /**
127         * Describe variable <code>adv</code> here.
128         *
129         */
130        protected JMenuItem adv;
131        /**
132         * Describe variable <code>pix</code> here.
133         *
134         */
135        protected HashtableJRadioButtonMenu pix;
136        /**
137         * Describe variable <code>menu</code> here.
138         *
139         */
140        protected JMenuBar menu;
141        // FIXME: minimize access
142        ButtonGroup bg;
143    
144        private Category cat
145            = Category.getInstance(RandomImage.class.getName());
146    
147        // FIXME: I ported this class in a hurry and it's crap-tastic.
148        /**
149         * Describe <code>setFeedbackMode</code> method here.
150         *
151         * @param i an <code>int</code> value
152         * @deprecated
153         */
154        @Deprecated public void setFeedbackMode(int i) {
155            if (i == 1) mode = intermed;
156            else if (i == 2) mode = expert;
157            else mode = beginner;
158            
159            makeTitle();
160            
161            if (size != -1) mode.setSize(size);
162            else size = mode.getSize();
163        }
164    
165        /**
166         * Describe <code>setFeedbackMode</code> method here.
167         *
168         * @param m a <code>DefaultVisualFeedbackMode</code> value
169         */
170        public void setFeedbackMode(DefaultVisualFeedbackMode m)
171        {
172            mode = m;
173            makeTitle();
174        
175            if (size != -1) mode.setSize(size);
176            else size = mode.getSize();
177        }
178    
179        /**
180         * Creates a new <code>RandomImage</code> instance.
181         *
182         */
183        public RandomImage() {
184            super();
185    
186            beginner = new BeginnerFeedbackMode();
187            intermed = new IntermediateFeedbackMode();
188            expert = new ExpertFeedbackMode();
189            setFeedbackMode(0);
190    
191            imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
192            imageLabel.setVerticalAlignment(SwingConstants.CENTER);
193            //ImageIcon la = ImageIconUtilities.getNamedImageIcon("file:resources/visualFeedback.jpg");
194            //imageLabel.setIcon(la);
195    
196            //enableEvents(java.awt.Event.WINDOW_DESTROY);
197    
198            setBackground(java.awt.Color.white);
199            super.setImageSize(mode.getSize());
200            screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
201    
202    
203            menu = new JMenuBar();
204            setJMenuBar(menu);
205            makeModeMenu();
206    
207            pack();
208        }
209    
210        /**
211         * Describe <code>getName</code> method here.
212         *
213         * @return a <code>String</code> value
214         */
215     
216        public String getName(){ return rb.getString(PLUGLET_FEEDBACK_IMAGE_RANDOM,"Random Images"); }
217        /**
218         * Describe <code>getDescription</code> method here.
219         *
220         * @return a <code>String</code> value
221         */
222        public String getDescription(){ return rb.getString(PLUGLET_FEEDBACK_IMAGE_RANDOM_DESCRIPTION,"Shows random pictures, which get bigger when you answer correctly"); }
223        /**
224         * Describe <code>getDirectoryName</code> method here.
225         *
226         * @return a <code>String</code> value
227         */
228        public String getDirectoryName() { return "/resources/images";}
229    
230    
231    
232        /**
233         * Describe <code>start</code> method here.
234         *
235         */
236        public void start()
237        {
238            if(ifac==null)
239                {
240                    ifac = new RandomImageFactory( getDirectoryName());
241                    ifac.addMediaRootChangedListener(this);
242                }
243            setNumberOfActiveItems(ifac.getNumberOfEnabledItems());
244            if(pix==null) makeImageBaseMenu();
245        }
246    
247        /**
248         * Describe <code>resetPicture</code> method here.
249         *
250         */
251        protected void resetPicture() {
252    
253            if(!jCheckBox1.isSelected() || cacheObject==null)
254                cacheObject = ifac.getRandomCacheObject();
255    
256            if(cacheObject==null) return;
257            ImageIcon tmp2 = (ImageIcon)cacheObject.object;
258            ImageIcon tmp = ImageIconUtilities.formatImage(tmp2, size);
259    
260            if(tmp!=null)
261                {
262                    imageLabel.setIcon(tmp);
263                    makeTitle();
264                }
265        }
266    
267        /**
268         * Sets the window title to "mode: filename"
269         *
270         */
271        protected void makeTitle() {
272            String x = null;
273            if(cacheObject!=null)
274                x = cacheObject.getFileShortName();
275    
276            if (x != null)
277                super.setTitle(mode.getShortName() + " : " + x);
278            else
279                super.setTitle(mode.getShortName());
280        }
281    
282        /**
283         * Describe <code>answerEvent</code> method here.
284         *
285         * @param e an <code>AnswerEvent</code> value
286         */
287        public void answerEvent(AnswerEvent e) {
288            if(!isVisible()) return;
289    
290            if (e.isCorrect()) mode.rightEvent();
291            else mode.wrongEvent();
292            size = mode.getSize();
293    
294            setImageSize(size);
295            resetPicture();
296    
297            String msg = "<HTML>";
298            msg += mode.getMessage();
299            setMessage(msg);
300            if(cacheObject!=null)
301                {
302                    setDirectoryName(cacheObject.getDirectoryName());
303                }
304            pack();
305        }
306    
307        /**
308         * Describe <code>setMessage</code> method here.
309         *
310         * @param pre a <code>String</code> value
311         */
312        protected void setMessage(String pre)
313        {
314            String msg = "";
315            msg += pre;
316            if(cacheObject!=null)
317                msg += "From : " + cacheObject.getDirectoryName() +"<BR>\n";;
318    
319            setImageSize(size);
320        }
321    
322        /**
323         * Describe <code>actionPerformed</code> method here.
324         *
325         * @param e a <code>java.awt.event.ActionEvent</code> value
326         */
327        public void actionPerformed(java.awt.event.ActionEvent e) {
328            if (e.getSource().equals(refreshItem)) {
329                ifac.refresh();
330            } else if (e.getSource().equals(chooseItem)) {
331                JFileChooser chooser = new JFileChooser(ifac.getRootDirectory());
332                chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
333                DirectoryJarFileFilter filt = new DirectoryJarFileFilter();
334                chooser.setFileFilter(filt);
335                int returnVal = chooser.showOpenDialog(this);
336                if(returnVal == JFileChooser.APPROVE_OPTION) {
337                    ifac.setRootDirectory(chooser.getSelectedFile() );
338                    makeImageBaseMenu();
339                }
340                ifac.refresh();
341            } else if (e.getSource().equals(begin)){
342                setFeedbackMode(0);
343            } else if (e.getSource().equals(inter)){
344                setFeedbackMode(1);
345            } else if (e.getSource().equals(adv)){
346                setFeedbackMode(2);
347            } else {
348                super.actionPerformed(e);
349            }
350        }
351      
352        /**
353         * Called when user selects a new base directory/JAR for images.
354         *
355         */
356        public void mediaRootChanged()
357        {
358            cat.debug("rand: Got mediarootchanged event");
359            setNumberOfActiveItems(ifac.getNumberOfEnabledItems());  
360        }
361    
362        /**
363         * Creates the Beginner/Intermediate/Advanced mode Menu.
364         *
365         */
366        protected void makeModeMenu()
367        {
368            JMenu modes = new JMenu("Mode");
369            begin = new JRadioButtonMenuItem("Beginner",true);
370            inter = new JRadioButtonMenuItem("Intermediate");
371            adv   = new JRadioButtonMenuItem("Advanced");
372            bg = new ButtonGroup();
373            bg.add(begin);
374            bg.add(inter);
375            bg.add(adv);
376            modes.add(begin);
377            modes.add(inter);
378            modes.add(adv);
379            begin.addActionListener(this);
380            inter.addActionListener(this);
381            adv.addActionListener(this);
382            menu.add(modes);
383        }
384    
385        /**
386         * Creates a menu allowing the user to select or refresh the base directory     * or JAR file for images.
387         *
388         */
389        protected void makeImageBaseMenu()
390        {
391            assert ifac!=null: "Image Factory is null";
392            if(menu!=null && pix!=null)
393                menu.remove(pix);
394    
395            pix = new HashtableJRadioButtonMenu("Images",true);
396            refreshItem = new JMenuItem("Refresh ImageBase");
397            refreshItem.addActionListener(this);
398            pix.add(refreshItem);
399    
400            chooseItem = new JMenuItem("Choose ImageBase...");
401            chooseItem.addActionListener(this);
402            pix.add(chooseItem);
403    
404            pix.addSeparator();
405    
406            String opts[] = ifac.getSubDirectoryNames();
407    
408            pix.addAllAsJRadioButtonMenuItems(opts, ifac);
409    
410            int sz = java.lang.reflect.Array.getLength(opts);
411    
412            for (int i = 0; i < sz; i++) {
413                if (ifac.isDirectoryEnabled(opts[i])) pix.setSelected(opts[i], true);
414            }
415            menu.add(pix);
416        }
417    
418    
419        /**
420         * Describe <code>getResourcePath</code> method here.
421         *
422         * @param in a <code>String</code> value
423         * @return a <code>String</code> value
424         */
425        public String getResourcePath(String in)
426        {
427            Class cl = this.getClass();
428            URL tst = cl.getResource(in);
429            cat.debug("base resource dir is" + tst);
430            if(tst==null) return null;
431            return tst.getPath();
432        }
433    
434        /**
435         * Describe <code>setSticky</code> method here.
436         *
437         * FIXME: broke sticky images in 1.0 push.
438         * @param s a <code>boolean</code> value
439         */
440        public void setSticky(boolean s) {
441            //sticky = s;
442        }    
443    }
444    
445    
446    
447    
448    
449    
450    
451    
452    
453    
454    
455