001    package sale;
002    
003    import javax.swing.*;
004    
005    import java.awt.event.*;
006    
007    /**
008     * A MenuSheetItem that has a label and an associated action.
009     *
010     * @see Action
011     * @see MenuSheet
012     * @see MenuSheetSeparator
013     *
014     * @author Steffen Zschaler
015     * @version 2.0 20/05/1999
016     * @since v1.0
017     */
018    public class MenuSheetItem extends MenuSheetObject implements ActionListener {
019    
020        /**
021             * ID for serialization.
022             */
023            private static final long serialVersionUID = 6809127518902187252L;
024    
025            /**
026         * The JMenuItem peer.
027         */
028        protected transient JMenuItem m_jmiPeer = null;
029    
030        /**
031         * The JMenu peer.
032         */
033        protected transient JMenu m_jmMenuPeer = null;
034    
035        /**
036         * The monitor synchronizing access to the peers.
037         */
038        private transient Object m_oPeerLock;
039        /**
040         * Return the monitor used to synchronized access to the peers.
041         *
042         * @override Never
043         */
044        protected Object getPeerLock() {
045            if (m_oPeerLock == null) {
046                m_oPeerLock = new Object();
047            }
048    
049            return m_oPeerLock;
050        }
051    
052        /**
053         * The action associated with this MenuSheetItem.
054         *
055         * @serial
056         */
057        protected Action m_aAction;
058        /**
059         * The monitor synchronizing accesses to m_aAction.
060         */
061        private transient Object m_oActionLock;
062        /**
063         * Return the monitor used to synchronized access to the m_aAction.
064         *
065         * @override Never
066         */
067        protected Object getActionLock() {
068            if (m_oActionLock == null) {
069                m_oActionLock = new Object();
070            }
071    
072            return m_oActionLock;
073        }
074    
075        /**
076         * Can this MenuSheetItem be clicked?
077         *
078         * @serial
079         */
080        private boolean m_fEnabled = true;
081    
082        /**
083         * The Images associated with the icons of this MenuSheetItem( [0]:DefaultImage, [1]:PressedImage,
084         * [2]:DisabledImage, [3]:PressedDiabledImage ).
085         *
086         * @serial
087         */
088        protected ImageIcon m_aiImages[] = null;
089    
090        /**
091         * The Mnemonic of this MenuSheetItem.
092         *
093         * @serial
094         */
095        protected char m_cMnemonic;
096    
097        /**
098         * The KeyStroke of this MenuSheetItem.
099         *
100         * @serial
101         */
102        protected KeyStroke m_ksKeyStroke;
103    
104        /**
105         * The ToolTip of this MenuSheeItemt.
106         *
107         * @serial
108         */
109        protected String m_sToolTip = "";
110    
111        private void writeObject(java.io.ObjectOutputStream oos) throws java.io.IOException {
112            util.Debug.print("Starting to write menu sheet item: \"" + getCaption() + "\" <" + getTag() + ">", -1);
113    
114            oos.defaultWriteObject();
115    
116            util.Debug.print("Done writing menu sheet item: \"" + getCaption() + "\" <" + getTag() + ">", -1);
117        }
118    
119        /**
120         * Creates a new MenuSheetItem with caption, tag, an action and a mnemonic.
121         *
122         * @param sCaption the caption of the new MenuSheetItem.
123         * @param sTag the tag that will identify this MenuSheetItem.
124         * @param aAction the action to perform when this MenuSheetItem is selected.
125         * @param cMnemonic the mnemonic of the new MenuSheetItem
126         */
127        public MenuSheetItem(String sCaption, String sTag, Action aAction, char cMnemonic) {
128            super(sCaption, sTag);
129            m_cMnemonic = cMnemonic;
130    
131            m_aAction = aAction;
132        }
133    
134        /**
135         * Creates a new MenuSheetItem with caption, tag and action; initially enabled.
136         *
137         * @param sCaption the caption of the new MenuSheetItem.
138         * @param sTag the tag that will identify this MenuSheetItem.
139         * @param aAction the action to perform when this MenuSheetItem is selected.
140         */
141        public MenuSheetItem(String sCaption, String sTag, Action aAction) {
142            this(sCaption, sTag, aAction, '\0');
143        }
144    
145        /**
146         * Creates a new MenuSheetItem with caption and action. The MenuSheetItem will have
147         * a default, unique tag.
148         *
149         * @param sCaption the caption of the new MenuSheetItem.
150         * @param aAction the action to perform when this MenuSheetItem is selected.
151         */
152        public MenuSheetItem(String sCaption, Action aAction) {
153            this(sCaption, null, aAction, '\0');
154        }
155    
156        // Helpmethod for setting an ImageIcon
157        private void setIcon(ImageIcon iiImageIcon, int nIndex) {
158            if (m_aiImages == null) {
159                m_aiImages = new ImageIcon[4];
160    
161            }
162            m_aiImages[nIndex] = iiImageIcon;
163    
164            synchronized (getPeerLock()) {
165                if (m_jmiPeer != null) {
166                    switch (nIndex) {
167                        case DEFAULT_IMAGE:
168                            m_jmiPeer.setIcon(iiImageIcon);
169                            break;
170                        case SELECTED_IMAGE: {
171                            m_jmiPeer.setSelectedIcon(iiImageIcon);
172                            break;
173                        }
174                        case DISABLED_IMAGE:
175                            m_jmiPeer.setDisabledIcon(iiImageIcon);
176                            break;
177                        case DISABLED_SELECTED_IMAGE:
178                            m_jmiPeer.setDisabledSelectedIcon(iiImageIcon);
179                            break;
180                    }
181                }
182    
183                if (m_jmMenuPeer != null) {
184                    switch (nIndex) {
185                        case DEFAULT_IMAGE:
186                            m_jmMenuPeer.getItem(0).setIcon(iiImageIcon);
187                            break;
188                        case SELECTED_IMAGE:
189                            m_jmMenuPeer.getItem(0).setSelectedIcon(iiImageIcon);
190                            break;
191                        case DISABLED_IMAGE:
192                            m_jmMenuPeer.getItem(0).setDisabledIcon(iiImageIcon);
193                            break;
194                        case DISABLED_SELECTED_IMAGE:
195                            m_jmMenuPeer.getItem(0).setDisabledSelectedIcon(iiImageIcon);
196                            break;
197                    }
198                }
199            }
200        }
201    
202        /**
203         * Set the caption of this MenuSheetItem. If the MenuSheetItem is already on display,
204         * also the peer's caption is set.
205         *
206         * @override Never
207         *
208         * @param sCaption the new caption.
209         */
210        public void setCaption(String sCaption) {
211    
212            synchronized (getPeerLock()) {
213                if (m_jmiPeer != null) {
214                    m_jmiPeer.setText(sCaption);
215                }
216    
217                if (m_jmMenuPeer != null) {
218                    m_jmMenuPeer.setText(sCaption);
219                    m_jmMenuPeer.getItem(0).setText(sCaption);
220                }
221            }
222    
223            super.setCaption(sCaption);
224        }
225    
226        /**
227         * Set the enabled state of this MenuSheetItem. If the MenuSheetItem is already on
228         * display, also the peer's enabled state is set.
229         *
230         * @override Never
231         *
232         * @param fEnabled the new enabled state.
233         */
234        public void setEnabled(boolean fEnabled) {
235            m_fEnabled = fEnabled;
236    
237            synchronized (getPeerLock()) {
238                if (m_jmiPeer != null) {
239                    m_jmiPeer.setEnabled(fEnabled);
240                }
241    
242                if (m_jmMenuPeer != null) {
243                    m_jmMenuPeer.getItem(0).setEnabled(fEnabled);
244                }
245            }
246        }
247    
248        /**
249         * Return the current enabled state of this MenuSheetItem.
250         *
251         * @override Never
252         */
253        public boolean isEnabled() {
254            return m_fEnabled;
255        }
256    
257        /**
258         * Mark the item visible or invisible.
259         *
260         * @override Never
261         */
262        public void setVisible(boolean fVisible) {
263            super.setVisible(fVisible);
264    
265            if (!fVisible) {
266                synchronized (getPeerLock()) {
267                    m_jmiPeer = null;
268                    m_jmMenuPeer = null;
269                }
270            }
271        }
272    
273        /**
274         * Set the action to perform when this item is selected.
275         *
276         * @override Never
277         *
278         * @param aAction the action to perform when this item is selected.
279         *
280         * @return the previously set action, if any.
281         */
282        public Action setAction(Action aAction) {
283            Action aOld = null;
284    
285            synchronized (getActionLock()) {
286                aOld = m_aAction;
287    
288                m_aAction = aAction;
289            }
290    
291            return aOld;
292        }
293    
294        /**
295         * Set the mnemonic of this MenuSheetItem.
296         *
297         * <p>If there is a peer it will reflect the changes immediately.</p>
298         *
299         * @override Never
300         *
301         * @param sMnemonic the new mnemonic.
302         */
303        public void setMnemonic(char cMnemonic) {
304            m_cMnemonic = cMnemonic;
305    
306            synchronized (getPeerLock()) {
307                if (m_jmiPeer != null) {
308                    m_jmiPeer.setMnemonic(cMnemonic);
309                }
310    
311                if (m_jmMenuPeer != null) {
312                    m_jmMenuPeer.getItem(0).setMnemonic(cMnemonic);
313                }
314            }
315        }
316    
317        /**
318         * Set the accelerator of this MenuSheetItem.
319         *
320         * <p>If there is a peer it will reflect the changes immediately.</p>
321         *
322         * @override Never
323         *
324         * @param ks the new keystroke.
325         */
326        public void setAccelerator(KeyStroke ks) {
327            m_ksKeyStroke = ks;
328    
329            synchronized (getPeerLock()) {
330                if (m_jmiPeer != null) {
331                    m_jmiPeer.setAccelerator(ks);
332                }
333    
334                if (m_jmMenuPeer != null) {
335                    m_jmMenuPeer.getItem(0).setAccelerator(ks);
336                }
337            }
338        }
339    
340        /**
341         * Set the ToolTip of this MenuSheetItem.
342         *
343         * <p>If there is a peer it will reflect the changes immediately.</p>
344         *
345         * @override Never
346         *
347         * @param s the new ToolTip-Text.
348         */
349        public void setToolTipText(String s) {
350            m_sToolTip = s;
351    
352            synchronized (getPeerLock()) {
353                if (m_jmiPeer != null) {
354                    m_jmiPeer.setToolTipText(s);
355                    m_jmiPeer.validate();
356                }
357            }
358        }
359    
360        /**
361         * Set the default icon of this MenuSheetItem.
362         *
363         * <p>If there is a peer it will reflect the changes immediately.</p>
364         *
365         * @override Never
366         *
367         * @param iiImageIcon the new icon.
368         */
369        public void setDefaultIcon(ImageIcon iiImageIcon) {
370            setIcon(iiImageIcon, DEFAULT_IMAGE);
371        }
372    
373        /**
374         * Set the selected icon of this MenuSheetItem.
375         *
376         * <p>If there is a peer it will reflect the changes immediately.</p>
377         *
378         * @override Never
379         *
380         * @param iiImageIcon the new icon.
381         */
382        public void setSelectedIcon(ImageIcon iiImageIcon) {
383            setIcon(iiImageIcon, SELECTED_IMAGE);
384        }
385    
386        /**
387         * Set the disabled icon of this MenuSheetItem.
388         *
389         * <p>If there is a peer it will reflect the changes immediately.</p>
390         *
391         * @override Never
392         *
393         * @param iiImageIcon the new icon.
394         */
395        public void setDisabledIcon(ImageIcon iiImageIcon) {
396            setIcon(iiImageIcon, DISABLED_IMAGE);
397        }
398    
399        /**
400         * Set the disabled selected icon of this MenuSheetItem.
401         *
402         * <p>If there is a peer it will reflect the changes immediately.</p>
403         *
404         * @override Never
405         *
406         * @param iiImageIcon the new icon.
407         */
408        public void setDisabledSelectedIcon(ImageIcon iiImageIcon) {
409            setIcon(iiImageIcon, DISABLED_SELECTED_IMAGE);
410        }
411    
412        /**
413         * Get the JMenuItem peer of the MenuSheetItem. The JMenuItem peer is a JMenuItem
414         * with the same caption as this MenuSheetItem. Selecting this JMenuItem will invoke
415         * the action associated to this MenuSheetItem.
416         *
417         * @override Never
418         */
419        public JMenuItem getPeer() {
420            synchronized (getPeerLock()) {
421                if (m_jmiPeer == null) {
422                    m_jmiPeer = new JMenuItem(getCaption());
423                    m_jmiPeer.addActionListener(this);
424    
425                    // add Mnemonic to JMenuItem if exists
426                    if (m_cMnemonic != '\0') {
427                        m_jmiPeer.setMnemonic(m_cMnemonic);
428    
429                        // add Accelerator to JMenuItem if exists
430                    }
431                    if (m_ksKeyStroke != null) {
432                        m_jmiPeer.setAccelerator(m_ksKeyStroke);
433    
434                    }
435                    if (m_sToolTip.compareTo("") != 0) {
436                        m_jmiPeer.setToolTipText(m_sToolTip);
437                    }
438    
439                    if (m_aiImages != null) {
440                        // add DefaultIcon, if any
441                        if (m_aiImages[DEFAULT_IMAGE] != null) {
442                            m_jmiPeer.setIcon(m_aiImages[DEFAULT_IMAGE]);
443                            // add PressedIcon, if any
444                        }
445                        if (m_aiImages[SELECTED_IMAGE] != null) {
446                            System.out.println("Selected Icon - getPeer(): " + m_aiImages[SELECTED_IMAGE]);
447                            m_jmiPeer.setSelectedIcon(m_aiImages[SELECTED_IMAGE]);
448                            System.out.println("Peer hat Selected Icon: " + m_jmiPeer.getSelectedIcon());
449                        }
450                        // add DisabledIcon, if any
451                        if (m_aiImages[DISABLED_IMAGE] != null) {
452                            m_jmiPeer.setDisabledIcon(m_aiImages[DISABLED_IMAGE]);
453                            // add DisabledSelectedIcon, if any
454                        }
455                        if (m_aiImages[DISABLED_SELECTED_IMAGE] != null) {
456                            m_jmiPeer.setDisabledSelectedIcon(m_aiImages[DISABLED_SELECTED_IMAGE]);
457                        }
458                    }
459    
460                    m_jmiPeer.setEnabled(m_fEnabled);
461                }
462            }
463    
464            return m_jmiPeer;
465        }
466    
467        /**
468         * Return the JMenu peer for this MenuSheetItem. The JMenu peer is a JMenu with the
469         * same caption as this MenuSheetItem, containing just one JMenuItem, which is
470         * equivalent to the JMenuItem peer of the MenuSheetItem.
471         *
472         * @override Never
473         */
474        public JMenu getMenuPeer() {
475            synchronized (getPeerLock()) {
476                if (m_jmMenuPeer == null) {
477                    m_jmMenuPeer = new JMenu(getCaption());
478                    JMenuItem jmi = m_jmMenuPeer.add(getCaption());
479                    jmi.addActionListener(this);
480    
481                    // add Mnemonic to JMenuItem if exists
482                    if (m_cMnemonic != '\0') {
483                        jmi.setMnemonic(m_cMnemonic);
484    
485                        // add Accelerator to JMenuItem if exists
486                    }
487                    if (m_ksKeyStroke != null) {
488                        jmi.setAccelerator(m_ksKeyStroke);
489    
490                    }
491                    if (m_aiImages != null) {
492                        // add DefaultIcon, if any
493                        if (m_aiImages[DEFAULT_IMAGE] != null) {
494                            jmi.setIcon(m_aiImages[DEFAULT_IMAGE]);
495                            // add SelectedIcon, if any
496                        }
497                        if (m_aiImages[SELECTED_IMAGE] != null) {
498                            System.out.println("Selected Icon - getMenuPeer(): " + m_aiImages[SELECTED_IMAGE]);
499                            jmi.setSelectedIcon(m_aiImages[SELECTED_IMAGE]);
500                        }
501                        // add DisabledIcon, if any
502                        if (m_aiImages[DISABLED_IMAGE] != null) {
503                            jmi.setDisabledIcon(m_aiImages[DISABLED_IMAGE]);
504                            // add DisabledSelectedIcon, if any
505                        }
506                        if (m_aiImages[DISABLED_SELECTED_IMAGE] != null) {
507                            jmi.setDisabledSelectedIcon(m_aiImages[DISABLED_SELECTED_IMAGE]);
508                        }
509                    }
510    
511                    jmi.setEnabled(m_fEnabled);
512                }
513            }
514    
515            return m_jmMenuPeer;
516        }
517    
518        /**
519         * Hook method called whenever the user selects the MenuSheetItem. As a default
520         * invokes the action currently associated with the MenuSheetItem, handing it the
521         * currently attached SalesPoint and SaleProcess.
522         *
523         * @override Never
524         *
525         * @see #setAction
526         * @see SalesPoint
527         * @see SaleProcess
528         */
529        public void actionPerformed(ActionEvent e) {
530            final Action[] aaTemp = new Action[1];
531    
532            synchronized (getActionLock()) {
533                aaTemp[0] = m_aAction;
534            }
535    
536            if (aaTemp[0] != null) {
537                new Thread("ActionPerfomer: MenuSheetItem: \"" + getCaption() + "\"") {
538                    public void run() {
539                        try {
540                            aaTemp[0].doAction(m_pAttached, m_spAttached);
541                        }
542                        catch (ThreadDeath td) {
543                            throw td;
544                        }
545                        catch (Throwable t) {
546                            System.err.println("Exception occured during event dispatching: MenuSheetItem \"" +
547                                    getCaption() + "\":");
548                            t.printStackTrace();
549                        }
550                    }
551                }
552    
553                .start();
554            }
555        }
556    
557        /**
558         * Get the Mnemonic of this MenuSheetItem.
559         *
560         * @override Never
561         *
562         * @return the mnemonic of this MenuSheetItem.
563         */
564        public char getMnemonic() {
565            return m_cMnemonic;
566        }
567    
568        /**
569         * Get the accelerator of this MenuSheetItem.
570         *
571         * @override Never
572         *
573         * @return the keystroke associated with the accelerator of this MenuSheetItem.
574         */
575        public KeyStroke getAccelerator() {
576            return m_ksKeyStroke;
577        }
578    
579        /**
580         * Get the ToolTip of this MenuSheetItem.
581         *
582         * @override Never
583         *
584         * @return the ToolTip-String of this MenuSheetItem.
585         */
586        public String getToolTipText() {
587            return m_sToolTip;
588        }
589    
590        /**
591         * Get the default icon of this MenuSheetItem.
592         *
593         * @override Never
594         *
595         * @return the default icon of this MenuSheetItem.
596         */
597        public ImageIcon getDefaultIcon() {
598            return (m_aiImages != null) ? (m_aiImages[DEFAULT_IMAGE]) : (null);
599        }
600    
601        /**
602         * Get the selected icon of this MenuSheetItem.
603         *
604         * @override Never
605         *
606         * @return the pressed icon of this MenuSheetItem.
607         */
608        public ImageIcon getSelectedIcon() {
609            return (m_aiImages != null) ? (m_aiImages[SELECTED_IMAGE]) : (null);
610        }
611    
612        /**
613         * Get the disabled item of this MenuSheetItem.
614         *
615         * @override Never
616         *
617         * @return the disabled icon of this MenuSheetItem.
618         */
619        public ImageIcon getDisabledIcon() {
620            return (m_aiImages != null) ? (m_aiImages[DISABLED_IMAGE]) : (null);
621        }
622    
623        /**
624         * Get the disabled selected item of this MenuSheetItem.
625         *
626         * @override Never
627         *
628         * @return the disabled selected icon of this MenuSheetItem.
629         */
630        public ImageIcon getDisabledSelectedIcon() {
631            return (m_aiImages != null) ? (m_aiImages[DISABLED_SELECTED_IMAGE]) : (null);
632        }
633    
634        // A Tag that will identify the Image for the DefaultIcon
635        private final static int DEFAULT_IMAGE = 0;
636        // A Tag that will identify the Image for the SelectedIcon
637        private final static int SELECTED_IMAGE = 1;
638        // A Tag that will identify the Image for the DisabledIcon
639        private final static int DISABLED_IMAGE = 2;
640        // A Tag that will identify the Image for the DisabledSelectedIcon
641        private final static int DISABLED_SELECTED_IMAGE = 3;
642    }