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