001    /*
002      Copyright (C) 2001-2003 Renaud Pawlak <renaud@aopsys.com>, 
003                              Laurent Martelli <laurent@aopsys.com>
004      
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful,
011      but WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013      GNU Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser General Public License
016      along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
018    
019    package org.objectweb.jac.aspects.gui.swing;
020    
021    import java.awt.BorderLayout;
022    import java.awt.Component;
023    import java.awt.Container;
024    import java.awt.Dialog;
025    import java.awt.Dimension;
026    import java.awt.Frame;
027    import java.awt.Rectangle;
028    import java.awt.Toolkit;
029    import java.awt.event.ActionEvent;
030    import java.awt.event.ActionListener;
031    import java.awt.event.ContainerEvent;
032    import java.awt.event.ContainerListener;
033    import java.awt.event.KeyEvent;
034    import java.awt.event.KeyListener;
035    import java.awt.event.WindowAdapter;
036    import java.awt.event.WindowEvent;
037    import java.util.Map;
038    import javax.swing.BorderFactory;
039    import javax.swing.JButton;
040    import javax.swing.JDialog;
041    import javax.swing.JLabel;
042    import javax.swing.JPanel;
043    import javax.swing.SwingConstants;
044    import org.apache.log4j.Logger;
045    import org.objectweb.jac.aspects.gui.CommitException;
046    import org.objectweb.jac.aspects.gui.DialogView;
047    import org.objectweb.jac.aspects.gui.DisplayContext;
048    import org.objectweb.jac.aspects.gui.GuiAC;
049    import org.objectweb.jac.aspects.gui.View;
050    import org.objectweb.jac.core.Collaboration;
051    import org.objectweb.jac.util.Strings;
052    
053    public class ObjectViewDialog extends JDialog 
054        implements ActionListener, KeyListener, ContainerListener
055    {
056        static Logger loggerEvents = Logger.getLogger("gui.events");
057        static Logger loggerFocus = Logger.getLogger("gui.focus");
058    
059        public boolean ok=false;
060        JButton okButton;
061        JButton cancelButton;
062        JButton closeButton;
063        View objectView;
064        protected DisplayContext context;
065    
066        /** Stores context attributes at creation time so they can be
067            restored by components when invoking methods */
068        Map attributes;
069    
070        public ObjectViewDialog(View view,
071                                String title, String header, 
072                                Frame parent,
073                                boolean okay, boolean cancel, boolean close,
074                                DisplayContext context) {
075            super(parent);
076            setModal(parent!=null);
077            context.setWindow(this);
078            init(view,title,header,okay,cancel,close,context);
079        }
080    
081        public ObjectViewDialog(View view,
082                                String title, String header, 
083                                Dialog parent,
084                                boolean okay, boolean cancel, boolean close,
085                                DisplayContext context) {
086            super(parent);
087            setModal(parent!=null);
088            context.setWindow(this);
089            init(view,title,header,okay,cancel,close,context);
090        }
091    
092    
093        public ObjectViewDialog(View view,
094                                String title, String header, 
095                                boolean okay, boolean cancel, boolean close,
096                                DisplayContext context) {
097            setModal(false);
098            context.setWindow(this);
099            init(view,title,header,okay,cancel,close,context);
100        }
101    
102        void init(View view,
103                  String title, String header, 
104                  boolean okay, boolean cancel, boolean close,
105                  DisplayContext context) 
106        {
107            this.context = context;
108            setTitle(title);
109    
110            if (okay || cancel) {
111                //((AbstractSwingDisplay)display).addDialog(this);
112                //setModal(true);
113            }
114    
115            if (header != null) {
116                JPanel p=new JPanel();
117                p.setBorder(BorderFactory.createEtchedBorder());
118                p.add(new JLabel(header,SwingConstants.LEFT));
119                getContentPane().add(p,BorderLayout.NORTH);
120            }
121            if (view != null) {
122                getContentPane().add((Component)view,BorderLayout.CENTER);
123                objectView = view;
124            }
125    
126            if (okay || cancel || close) {
127                JPanel p2 = new JPanel();
128                p2.setBorder(BorderFactory.createEtchedBorder());
129                if (okay) {
130                    okButton = addButton(p2, "Ok");
131                }
132                if (cancel) {
133                    cancelButton = addButton(p2, "Cancel");
134                }
135                if (close) {
136                    closeButton = addButton(p2,"Close");
137                }
138                getContentPane().add(p2, BorderLayout.SOUTH);
139                if (closeButton!=null) {
140                    getRootPane().setDefaultButton(closeButton);
141                } else if (okButton!=null) {
142                    getRootPane().setDefaultButton(okButton);
143                }
144            }
145            pack();
146    
147            // open the box centered in the screen...
148            Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
149            Rectangle rect = getBounds();
150            rect.width = Math.min(screenDim.width,rect.width);
151            rect.height = Math.min(screenDim.height,rect.height);
152            double left = (screenDim.getWidth()-rect.getWidth())/2;
153            double top = (screenDim.getHeight()-rect.getHeight())/2;
154            Rectangle newRect = new Rectangle(
155                (int)left,(int)top,
156                (int)rect.getWidth(),(int)rect.getHeight());
157            setBounds(newRect);
158    
159            addWindowListener( new WindowAdapter () {
160                    public void windowClosing(WindowEvent e) {
161                        loggerEvents.debug("windowClosing: "+e);
162                        if (objectView!=null)
163                            objectView.close(true);
164                    }
165                }
166            );
167    
168            java.util.List editors = context.getEditors();
169            if (!editors.isEmpty()) {
170                loggerFocus.debug("give focus to "+editors.get(0));
171                ((Component)editors.get(0)).requestFocus();
172            } else {
173                loggerFocus.debug("no editor to give focus to");
174            }
175    
176            addKeyAndContainerListenerRecursively(this);
177    
178            attributes = Collaboration.get().getAttributes();   
179    
180            setVisible(true);
181        }
182    
183        public void actionPerformed(ActionEvent evt) {
184            try {
185                Object source = evt.getSource();
186                if (source==okButton || source==closeButton) {
187                    if (objectView!=null) {
188                        objectView.close(true);
189                    }
190                    ok = true;
191                    close(true);
192                    dispose();
193                } else if (source==cancelButton) {
194                    ok = false;
195                    // ((AbstractSwingDisplay)display).removeDialog(this);
196                    close(false);
197                    dispose();
198                }
199            } catch (CommitException e) {
200                context.getDisplay().showModal(e,"Error","",context.getWindow(),false,false,true);
201            } catch (Exception e) {
202                loggerEvents.error("ObjectViewDialog.actionPerformed failed",e);
203            }
204        }
205       
206        public void close(boolean validate) {
207            if (objectView!=null)
208                objectView.close(validate);
209            objectView = null;
210        }
211       
212        public JButton addButton(Container c, String name)  {
213            JButton button = new JButton(name);
214            button.addActionListener(this);
215            c.add(button);
216            return button;
217        }
218    
219        // We should implement DialogView !!!
220        public void restoreContext() {
221            loggerEvents.debug("Restoring attributes: "+attributes.keySet());
222            Collaboration.get().setAttributes(attributes);
223        }
224    
225        // KeyListener interface
226        public void keyPressed(KeyEvent event) {
227            int code = event.getKeyCode();
228            switch (code) {
229                case KeyEvent.VK_ESCAPE:
230                    ok = false;
231                    dispose();
232                    break;
233                default:
234            }
235        }
236        public void keyTyped(KeyEvent event) {}
237        public void keyReleased(KeyEvent event) {}
238    
239        // ContainerListener interface
240        // Copied from http://www.javaworld.com/javaworld/javatips/jw-javatip69.html
241    
242        public void componentAdded(ContainerEvent event) {
243            addKeyAndContainerListenerRecursively(event.getChild());
244        }
245    
246        /**
247         * Register as a KeyListener and ContainerListener on the component
248         * and its children recursively.
249         * @param c the component
250         */
251        protected void addKeyAndContainerListenerRecursively(Component c) {
252            c.addKeyListener(this);
253            if (c instanceof Container) {
254                Container cont = (Container)c;
255                cont.addContainerListener(this);
256                Component[] children = cont.getComponents();
257                for(int i=0; i<children.length; i++){
258                    addKeyAndContainerListenerRecursively(children[i]);
259                }
260            }
261        }
262    
263        public void componentRemoved(ContainerEvent event) {
264            removeKeyAndContainerListenerRecursively(event.getChild());
265        }
266    
267        /**
268         * Unregister as a KeyListener and ContainerListener on the
269         * component and its children recursively.
270         * @param c the component 
271         */
272        protected void removeKeyAndContainerListenerRecursively(Component c) {
273            c.removeKeyListener(this);
274            if (c instanceof Container) {
275                Container cont = (Container)c;
276                cont.removeContainerListener(this);
277                Component[] children = cont.getComponents();
278                for(int i=0; i<children.length; i++){
279                    removeKeyAndContainerListenerRecursively(children[i]);
280                }
281            }
282        }
283    
284        public String toString() {
285            return Strings.hex(this);
286        }
287    }