001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: barseghian $'
006 * '$Date: 2011-02-12 02:25:44 +0000 (Sat, 12 Feb 2011) $' 
007 * '$Revision: 27102 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030
031package org.kepler.reporting.gui;
032
033import java.awt.BorderLayout;
034import java.awt.Color;
035import java.awt.Component;
036import java.awt.Cursor;
037import java.awt.Dimension;
038import java.awt.GradientPaint;
039import java.awt.Graphics;
040import java.awt.Graphics2D;
041import java.awt.Image;
042import java.awt.Point;
043import java.awt.RenderingHints;
044import java.awt.Toolkit;
045import java.awt.datatransfer.DataFlavor;
046import java.awt.datatransfer.Transferable;
047import java.awt.event.MouseAdapter;
048import java.awt.event.MouseEvent;
049import java.net.URL;
050
051import javax.swing.JComponent;
052import javax.swing.JPanel;
053import javax.swing.JRadioButton;
054import javax.swing.TransferHandler;
055import javax.swing.border.Border;
056
057import org.kepler.reporting.rio.Item;
058
059
060public class DragAndDropPanel extends JPanel implements Transferable{
061
062        private Border ovalBorderselected = new OvalBorder(3, 3, Color.blue, Color.blue);
063        protected Border ovalBorder = new OvalBorder(3, 3, Color.gray, Color.black);
064        
065        private static final int DRAG_AND_DROP_PANEL_WIDTH = 25000;
066        public static final int DRAG_AND_DROP_PANEL_HEIGHT = 40;
067
068        private Item associatedItem;
069        private JRadioButton propertiesButton;
070        private Component associatedComponent;
071        
072        private boolean selected;
073        private static Toolkit toolkit = Toolkit.getDefaultToolkit();   
074        private static URL dragcursorURL = getImageURL("movecursor", "gif");
075        private static Image dragcursorImage = toolkit.getImage(dragcursorURL);
076        private static Point dragcursorHotSpot = new Point(5,5);
077        private static Cursor dragCursor = toolkit.createCustomCursor(dragcursorImage, dragcursorHotSpot, "DragCursor");        
078
079        private ReportDesignerPanel _parentReportDesignerPanel;
080
081
082        public DragAndDropPanel(ReportDesignerPanel reportDesignerPanel) {
083                
084                _parentReportDesignerPanel = reportDesignerPanel;
085
086                this.addMouseListener(new DraggableMouseListener());
087
088                this.setLayout(new BorderLayout());
089
090                setFocusable(true);
091                
092                // Add the handler to negotiate between the drop target and this
093                // draggable panel
094                this.setTransferHandler(new DragAndDropTransferHandler());
095
096                this.setBorder(ovalBorder);
097                
098                this.setOpaque(true);  // changed this
099
100                Dimension dimension = new Dimension(DRAG_AND_DROP_PANEL_WIDTH,DRAG_AND_DROP_PANEL_HEIGHT);
101                this.setPreferredSize(dimension);
102                this.setMinimumSize(dimension);
103                
104                this.setToolTipText("Select, Drag & Drop to arrange report items");
105        }
106
107        //XXX i don't think this is ever called...?
108        public Dimension setDimensions() {
109                Dimension dim = new Dimension(500 * 25, 50);
110                return dim;
111        }
112
113        //FIXME hardcode to images dir. search for others.
114        public static URL getImageURL(String iconname, String extension) {
115                String ImageLocation = "images/" + iconname + "." + extension;
116                URL imageURL = ItemsOfInterestPanel.class.getResource(ImageLocation);
117                return imageURL;
118        }
119
120        /**
121         * 
122         * <p>
123         * One of three methods defined by the Transferable interface.
124         * </p>
125         * 
126         * <p>
127         * If multiple DataFlavor's are supported, can choose what Object to return.
128         * </p>
129         * 
130         * <p>
131         * In this case, we only support one: the actual JPanel.
132         * </p>
133         * 
134         * <p>
135         * Note we could easily support more than one. For example, if supports text
136         * and drops to a JTextField, could return the label's text or any arbitrary
137         * text.
138         * </p>
139         * 
140         * @param flavor
141         * 
142         * @return
143         */
144        public Object getTransferData(DataFlavor flavor) {
145
146                // Returning the data from the Transferable object.
147
148                // Here, the actual panel is transfered.
149
150                DataFlavor thisFlavor = null;
151
152                try {
153                        thisFlavor = ReportDesignerPanel.getDragAndDropPanelDataFlavor();
154                } catch (Exception ex) {
155
156                        System.err.println("Problem lazy loading: " + ex.getMessage());
157                        ex.printStackTrace(System.err);
158                        return null;
159                }
160
161                // For now, assume wants this class... see loadDnD
162                if (thisFlavor != null && flavor.equals(thisFlavor)) {
163                        return DragAndDropPanel.this;
164                }
165                
166                return null;
167        }
168
169        /**
170         * 
171         * <p>
172         * One of three methods defined by the Transferable interface.
173         * </p>
174         * 
175         * <p>
176         * Returns supported DataFlavor. Again, we're only supporting this actual
177         * Object within the JVM.
178         * </p>
179         * 
180         * <p>
181         * For more information, see the JavaDoc for DataFlavor.
182         * </p>
183         * 
184         * @return
185         */
186        public DataFlavor[] getTransferDataFlavors() {
187
188                DataFlavor[] flavors = { null };
189
190                // We Query for acceptable DataFlavors to determine what is available.
191
192                // DragAndDropPanel class currently only supports DragAndDropPanel
193                // DataFlavor.
194
195                try {
196                        // flavors[0] =
197                        // DragAndDropPanelsDemo.getDragAndDropPanelDataFlavor();
198                } catch (Exception ex) {
199                        System.err.println("Problem lazy loading: " + ex.getMessage());
200                        ex.printStackTrace(System.err);
201                        return null;
202                }
203
204                return flavors;
205
206        }
207
208        /**
209         * 
210         * <p>
211         * One of three methods defined by the Transferable interface.
212         * </p>
213         * 
214         * <p>
215         * Determines whether this object supports the DataFlavor.
216         * 
217         * In this case, only one is supported: for this object itself.
218         * </p>
219         * 
220         * @param flavor
221         * 
222         * @return True if DataFlavor is supported, otherwise false.
223         */
224        public boolean isDataFlavorSupported(DataFlavor flavor) {
225
226                DataFlavor[] flavors = { null };
227
228                try {
229                        flavors[0] = ReportDesignerPanel.getDragAndDropPanelDataFlavor();
230                } catch (Exception ex) {
231                        // System.err.println("Problem lazy loading: " + ex.getMessage());
232                        // ex.printStackTrace(System.err);
233                        return false;
234                }
235
236                for (DataFlavor f : flavors) {
237                        if (f.equals(flavor)) {
238                                return true;
239                        }
240                }
241
242                return false;
243        }
244        
245
246        class DraggableMouseListener extends MouseAdapter {
247
248                @Override()
249                public void mousePressed(MouseEvent e) {
250                
251                        JComponent c = (JComponent) e.getSource();
252
253                        //c.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
254                        
255                        c.setCursor(dragCursor);
256
257                        TransferHandler handler = c.getTransferHandler();
258                        handler.exportAsDrag(c, e, TransferHandler.COPY);
259                        
260                        DragAndDropPanel clickedDnDPanel = (DragAndDropPanel) e.getSource();
261                        DragAndDropPanel prevPanel = _parentReportDesignerPanel.getPrevPanel();
262
263                        Item thecurrentitem = clickedDnDPanel.getAssociatedItem();
264                        Item theprevitem = prevPanel.getAssociatedItem();
265
266                        if (!thecurrentitem.equals(theprevitem)) {
267                                
268                                prevPanel.deselectPanel();
269                                theprevitem.setSelected(false);
270                                
271                                _parentReportDesignerPanel.setCurrPanel(clickedDnDPanel);
272                                clickedDnDPanel.selectPanel();
273                                thecurrentitem.setSelected(true);
274                                _parentReportDesignerPanel.setPrevPanel(clickedDnDPanel);
275
276                        }
277
278                        // System.out.println("The current item is: " + thecurrentitem);
279                        // System.out.println("The prev item is: " + theprevitem);
280                        
281                        requestFocusInWindow();
282                }
283
284                public void mouseReleased(MouseEvent e) {
285                        DragAndDropPanel releasedDnDPanel = (DragAndDropPanel) e.getSource();
286                        _parentReportDesignerPanel.setPrevPanel(releasedDnDPanel);
287                        
288                }
289                
290                public void mouseEntered(MouseEvent e) {
291                        DragAndDropPanel enteredDnDPanel = (DragAndDropPanel) e.getSource();
292                        enteredDnDPanel.setCursor(dragCursor);
293                }
294                
295                
296                public void mouseExited(MouseEvent e) {
297                        DragAndDropPanel exitedDnDPanel = (DragAndDropPanel) e.getSource();
298                        exitedDnDPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
299                }
300
301        }
302
303        /**
304         * setAssociatedItem - important method that associates a report Item with a
305         * specific DragAndDropPanel.
306         * @param associatedItem
307         */
308        public void setAssociatedItem(Item associatedItem) {
309                this.associatedItem = associatedItem;
310        }
311
312        public Item getAssociatedItem() {
313                return associatedItem;
314        }
315        
316        public void setPropertiesButton(JRadioButton propertiesButton) {
317                this.propertiesButton = propertiesButton;
318        }
319
320        public void setAssociatedComponent(Component associatedComponent) {
321                this.associatedComponent = associatedComponent;
322        }
323
324        public Component getAssociatedComponent() {
325                return associatedComponent;
326        }
327
328        /**
329         * 
330         * selects the drag and drop panel
331         * 
332         * in the default manner by the source which originated it.
333         */
334        public void selectPanel() {
335                
336                setSelected(true);
337                setBorder(ovalBorderselected);
338                setOpaque(false);
339                setBackground(new Color(6, 128, 255, 129).darker()); 
340                
341                propertiesButton.doClick();
342        }
343        
344        public void setSelected(boolean s){
345                selected = s;
346        }
347
348        public void deselectPanel() {
349                setSelected(false);
350                setBorder(ovalBorder);
351                setBackground(Color.white);
352        }
353
354        public boolean isSelected() {
355                return selected;
356        }
357        
358        
359        // @Override
360            protected void paintComponent(Graphics g) {
361                 
362                 Color color1 = getBackground( );
363                 Color color2 = color1.brighter();
364                 
365                Graphics2D g2d = (Graphics2D)g;
366                
367                int w = getWidth( );
368                int h = getHeight( );
369                 
370                // Paint a gradient from top to bottom
371                GradientPaint gp = new GradientPaint(
372                    0, 0, color1,
373                    0, h, color2 );
374
375                g2d.setPaint( gp );
376                //g2d.fillRect( 0, 0, w, h );
377                
378                g2d.fillRoundRect(0, 0, w, h, 20, 20);
379                //case ROUNDRECT:
380          // g.drawRoundRect(x, y, w, h, 20, 20);
381          //  break;
382
383                // Paint a gradient for the button
384                GradientPaint background = new GradientPaint(0f, 0f, (new Color(6, 128, 255, 129)),
385                        0f, (float)getHeight(), new Color(6, 128, 255, 129));
386                g2d.setPaint(background);
387                g2d.fillRoundRect(0, 0, getWidth(), 5*getHeight()/5, 20, 20);
388                
389                g2d.setColor(new Color(6, 128, 255, 129));
390                
391                // Paint a gradient
392                background = new GradientPaint(0f, (float)4*getHeight()/8, 
393                                new Color(128, 255, 128, 56),
394                        0f, (float)getHeight(), new Color(6, 128, 255, 129));
395                g2d.setPaint(background);
396                g2d.fillRoundRect(0, 4*getHeight()/5, getWidth(), getHeight()/5, 20, 20);
397                
398                // Enable anti-aliasing to get smooth outlines
399                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
400                        RenderingHints.VALUE_ANTIALIAS_ON);
401            }
402        
403        
404}
405