001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-08-09 21:27:41 +0000 (Thu, 09 Aug 2012) $' 
007 * '$Revision: 30392 $'
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
030package org.kepler.reporting.gui;
031
032import java.awt.BorderLayout;
033import java.awt.Color;
034import java.awt.Component;
035import java.awt.Cursor;
036import java.awt.Dimension;
037import java.awt.Font;
038import java.awt.GridBagConstraints;
039import java.awt.GridBagLayout;
040import java.awt.Image;
041import java.awt.Insets;
042import java.awt.Rectangle;
043import java.awt.Toolkit;
044import java.awt.datatransfer.DataFlavor;
045import java.awt.datatransfer.Transferable;
046import java.awt.dnd.DnDConstants;
047import java.awt.dnd.DropTarget;
048import java.awt.dnd.DropTargetDragEvent;
049import java.awt.dnd.DropTargetDropEvent;
050import java.awt.dnd.DropTargetEvent;
051import java.awt.dnd.DropTargetListener;
052import java.awt.event.ActionEvent;
053import java.awt.event.ActionListener;
054import java.awt.event.MouseEvent;
055import java.awt.event.MouseListener;
056import java.awt.event.WindowAdapter;
057import java.awt.event.WindowEvent;
058import java.awt.event.WindowFocusListener;
059import java.io.ByteArrayInputStream;
060import java.io.File;
061import java.io.IOException;
062import java.net.URL;
063import java.util.ArrayList;
064import java.util.HashMap;
065import java.util.List;
066import java.util.Map;
067import java.util.TreeMap;
068
069import javax.imageio.ImageIO;
070import javax.swing.AbstractAction;
071import javax.swing.Box;
072import javax.swing.ImageIcon;
073import javax.swing.JCheckBox;
074import javax.swing.JFileChooser;
075import javax.swing.JLabel;
076import javax.swing.JOptionPane;
077import javax.swing.JPanel;
078import javax.swing.JRadioButton;
079import javax.swing.JScrollPane;
080import javax.swing.JSplitPane;
081import javax.swing.JTextField;
082import javax.swing.JToolBar;
083import javax.swing.event.DocumentEvent;
084import javax.swing.event.DocumentListener;
085import javax.swing.text.BadLocationException;
086
087import org.kepler.gui.KeplerGraphFrame;
088import org.kepler.gui.TabManager;
089import org.kepler.gui.TabPane;
090import org.kepler.gui.TabPaneFactory;
091import org.kepler.gui.state.ReportingStateChangeEvent;
092import org.kepler.gui.state.StateChangeEvent;
093import org.kepler.gui.state.StateChangeListener;
094import org.kepler.gui.state.StateChangeMonitor;
095import org.kepler.moml.NamedObjId;
096import org.kepler.objectmanager.lsid.KeplerLSID;
097import org.kepler.reporting.rio.DynamicReportItem;
098import org.kepler.reporting.rio.Item;
099import org.kepler.reporting.rio.ItemValue;
100import org.kepler.reporting.rio.StaticReportItem;
101import org.kepler.reporting.rio.StaticReportItemHR;
102import org.kepler.reporting.rio.StaticReportItemImage;
103import org.kepler.reporting.rio.StaticReportItemSection;
104import org.kepler.reporting.rio.StaticReportItemText;
105import org.kepler.reporting.rio.fop.ReportRenderer;
106import org.kepler.reporting.rio.test.ReportTest;
107import org.kepler.reporting.rio.util.ImageUtil;
108import org.kepler.reporting.rio.util.ProvenanceUtil;
109import org.kepler.reporting.roml.ReportLayout;
110import org.kepler.util.WorkflowRun;
111import org.kepler.workflow.WorkflowManager;
112
113import ptolemy.actor.gui.PtolemyFrame;
114import ptolemy.actor.gui.TableauFrame;
115import ptolemy.data.StringToken;
116import ptolemy.data.expr.Parameter;
117import ptolemy.gui.ExtensionFilenameFilter;
118import ptolemy.gui.PtFileChooser;
119import ptolemy.kernel.Port;
120import ptolemy.kernel.util.IllegalActionException;
121import ptolemy.kernel.util.NameDuplicationException;
122import ptolemy.kernel.util.NamedObj;
123import ptolemy.vergil.toolbox.PtolemyTransferable;
124
125/**
126 * This class creates a gui pane the allows users to create a report layout for
127 * a Kepler Workflow. It implements TabPane, which is an extension point for
128 * additional tabbed contents in the Kepler gui. See TabPane for more details.
129 * 
130 * 
131 * @author staggs created January 7, 2009
132 * 
133 * 
134 */
135
136public class ReportDesignerPanel extends JPanel implements TabPane,
137                ActionListener, DropTargetListener, StateChangeListener, WindowFocusListener {
138
139        private final ReportDesignerPanel ref = this;
140        
141        public static final String IMAGES_DIR = "images/";
142
143        private static int LAYOUT_PANEL_WIDTH = 700;
144        // XXX LAYOUT_PANEL_HEIGHT isn't really used, we dynamically 
145        // set height in redrawView.setPreferredSize
146        private static int LAYOUT_PANEL_HEIGHT = 700;
147        private static int HEADER_PANEL_WIDTH = 100;
148        private static int HEADER_PANEL_HEIGHT = 30;
149        private static int DESIGNER_PANE_WIDTH = 700;
150        private static int DESIGNER_PANE_HEIGHT = 200;
151
152        // extra empty space so user can distinguish end of layout
153        private static int PANEL_HEIGHT_DEADSPACE = 50;
154
155        // empty space around panels to facilitate drag n drop
156        private static int PANEL_INSET_TOP = 0;
157        private static int PANEL_INSET_LEFT = 10;
158        private static int PANEL_INSET_BOTTOM = 20;
159        private static int PANEL_INSET_RIGHT = 30;
160        
161        private final static String TITLETEXT = "Title: ";
162        private TableauFrame _frame;
163        private String _title;
164        private ReportLayout reportLayout = null;
165        private Item selectedItem; // this is for getting the properties, not for
166                                                           // the DragAndDropPanels
167        private JPanel layoutpanel, headerpanel;
168        
169        private Item prevSelectedItem;  
170        private Item thecurrentitem;
171
172        private JRadioButton getimagebtn;
173        
174        private JSplitPane designersplitpane;
175        private final List<DragAndDropPanel> reportitemPanels;
176        private static DataFlavor dragAndDropPanelDataFlavor = null;
177        
178        private DragAndDropPanel prevSelectedPanel;
179        private DragAndDropPanel currSelectedPanel;
180        
181        private Color transparentblue = new Color(6, 128, 255, 129);  // transparent blue
182        //private Color bluenoalpha = new Color(91, 169, 248);  // non-alpha blue
183
184        public static final DataFlavor jlabelFlavor = new DataFlavor(JLabel.class,
185                        "Swing JLabel");
186        
187        private String layoutDiscardWarning =  "Discard current report layout and load old report layout?";
188        private JCheckBox dontShowDialogCheckBox = new JCheckBox("Do not show this message again.");
189                
190        private static Cursor droppableCursor = Cursor
191                        .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
192
193        public ReportDesignerPanel(String title, String workflowName) {
194
195                super(new BorderLayout());
196                _title = title;
197                
198                reportitemPanels = new ArrayList<DragAndDropPanel>();
199                this.setTransferHandler(new DragAndDropTransferHandler());
200                
201                //set up listeners
202                StateChangeMonitor.getInstance().addStateChangeListener(ReportingStateChangeEvent.REPORT_LAYOUT_CHANGED, this);
203                StateChangeMonitor.getInstance().addStateChangeListener(WorkflowRun.WORKFLOWRUN_SELECTED, this);
204                
205                //TODO on windowClosed we should remove this ReportDesignerPanel from listening to the above
206        }
207
208        /**
209         * getSelectedItem and setSelectedItem are currently used to create the
210         * properties table that appears in the 'Items of Interest' panel.
211         * 
212         * @return selectedItem for setting the items' properties in the properties
213         *         table in the ItemsOfInterestPanel.
214         */
215        public Item getSelectedItem() { // IMPORTANT Note: this is not for the
216                                                                        // panels, it is for the
217                return selectedItem;            // item properties selection.
218        }
219
220        public void setSelectedItem(Item selectedItem) {
221                this.selectedItem = selectedItem;
222        }
223
224        /**
225         * Initializes the tab for this TabPane in which the Report Designer is
226         * displayed.
227         */
228        public void initializeTab() throws Exception { 
229
230                // We query the report layouts and if there is one we will use it
231                // and if not we will add a blank one.
232                
233                NamedObj reference = ((PtolemyFrame) _frame).getModel();
234                KeplerLSID lsid = NamedObjId.getIdFor(reference);
235                
236                // need to setRankingTableauFrame here so the ReportLayoutKAREntryHandler gets the new frame
237                // on an open, because it hasn't been set via windowGainedFocus
238                WorkflowManager.setRankingTableauFrame(_frame);
239
240                //do this whether the reportLayout is null or not:
241                reportLayout = WorkflowManager.getInstance().getWorkflow(_frame, lsid).getReportLayout(_frame);
242                        
243                if (reportLayout == null){
244                        reportLayout = new ReportLayout();
245                        // associate the layout with the workflow
246                        reportLayout.setWorkflowLSID(lsid);
247                        WorkflowManager.getInstance().getWorkflow(_frame, lsid).addReportLayout(_frame, reportLayout);
248                }
249
250                createTabContents();
251                
252                renderReportLayout();
253                
254                WindowFocusListener[] wfl = _frame.getWindowFocusListeners();
255                boolean add = true;
256                for (int i=0; i<wfl.length; i++){
257                        if (wfl[i] == this){
258                                add = false;
259                        }
260                }
261                if (add){
262                        _frame.addWindowFocusListener(this);
263                }
264                
265                // clean up the listener when the frame closes
266                   final StateChangeListener listenerReference = this;
267                    _frame.addWindowListener(new WindowAdapter() {
268                                public void windowClosed(WindowEvent e) {
269                                        StateChangeMonitor.getInstance().removeStateChangeListener(ReportingStateChangeEvent.REPORT_LAYOUT_CHANGED, listenerReference);
270                                        StateChangeMonitor.getInstance().removeStateChangeListener(WorkflowRun.WORKFLOWRUN_SELECTED, listenerReference);
271                                }
272                        });
273                
274        }
275        
276
277        /**
278         * createTabContents() - You can modify this to change what appears in the report designer tab.
279         * This is used to create the layout and contents of the report designer GUI.
280         */
281        private void createTabContents() {
282                
283                /**
284                 * The header panel and the layout panel are both inside of a split pane
285                 * that is inside of the Report Designer Panel.  The header panel
286                 * holds the title of the report, and the layout panel is where
287                 * the user will drop the report items to create the report layout.
288                 */
289
290                /**
291                 * Create the header panel
292                 */
293                headerpanel = new JPanel();
294                headerpanel.setLayout(new BorderLayout());
295                headerpanel.setBackground(Color.white);
296                headerpanel.setMaximumSize(new Dimension(HEADER_PANEL_WIDTH, HEADER_PANEL_HEIGHT));
297                headerpanel.setMinimumSize(new Dimension(HEADER_PANEL_WIDTH, HEADER_PANEL_HEIGHT));
298                headerpanel.setPreferredSize(new Dimension(HEADER_PANEL_WIDTH, HEADER_PANEL_HEIGHT));
299                                
300
301                /**
302                 * Set up the text fields and their corresponding labels inside of the
303                 * header panel
304                 */
305                JTextField titletxt = new JTextField("");
306                titletxt.setText(reportLayout.getTitle());
307                Font titlefont = new Font("SansSerif", Font.BOLD, 16);
308                titletxt.setFont(titlefont);
309                
310                // Listen for changes to text
311                titletxt.getDocument().addDocumentListener(new TitleDocumentListener());
312                
313                JLabel lbltitle = new JLabel(TITLETEXT);
314                
315            headerpanel.add(lbltitle, BorderLayout.WEST);
316                headerpanel.add(titletxt, BorderLayout.CENTER);
317
318                /**
319                 * Create the layout panel.
320                 * 
321                 * The general idea of the layout panel is that each individual element 
322                 * of a report called a "report item" is represented by its own type of 
323                 * component, in this case a JPanel (DragAndDropPanel extends JPanel)
324                 * with an appropriate icon, etc. 
325                 * Since a report item object (Item class) is associated with each of the panels.
326                 * the user controls the order of the report items by adding, deleting,
327                 * and re-arranging the report item panels.
328                 *
329                 * So... when the user re-arranges the panels, the order of the
330                 * report items is also re-arranged temporarily (in memory), and then
331                 * written out to the Report model.
332                 * 
333                 * 
334                 */
335                
336                //The lines below show the 'drag to create a report' background in the report layout area.
337                // A small dot is also used, which replaces the graphic of the 'drag to here' image
338                // after the first report item is dropped into the report layout area.
339                URL placeholderdotURL = getIconURL("placeholderdot", "png");
340                URL paperURL = getIconURL("papertrans","png");
341                if (reportitemPanels.isEmpty()){
342                        layoutpanel = new ImagePanel(new ImageIcon(paperURL).getImage());
343                } else {
344                        layoutpanel = new ImagePanel(new ImageIcon(placeholderdotURL).getImage());
345                }
346                
347                layoutpanel.setLayout(new GridBagLayout());
348                layoutpanel.setBackground(Color.white);
349                
350                layoutpanel.scrollRectToVisible(getVisibleRect());              
351                
352                layoutpanel.setMinimumSize(new Dimension(LAYOUT_PANEL_WIDTH, LAYOUT_PANEL_HEIGHT));
353                layoutpanel.setPreferredSize(new Dimension(LAYOUT_PANEL_WIDTH, LAYOUT_PANEL_HEIGHT));
354
355                layoutpanel.setDropTarget(new DropTarget(layoutpanel,
356                                DnDConstants.ACTION_COPY_OR_MOVE, this, true, null));
357                layoutpanel.setTransferHandler(new DragAndDropTransferHandler());
358                layoutpanel.setCursor(Cursor.getDefaultCursor());
359                
360                
361
362                /**
363                 * Create the split pane and put the header panel and layout panel
364                 * inside of scroll pane and add to the ReportDesignerPanel.
365                 */
366                designersplitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
367                                add(headerpanel), add(new JScrollPane(layoutpanel)));
368
369                designersplitpane.setBackground(Color.white);
370                designersplitpane.setMinimumSize(new Dimension(DESIGNER_PANE_WIDTH, DESIGNER_PANE_HEIGHT));
371                designersplitpane.setPreferredSize(new Dimension(DESIGNER_PANE_WIDTH, DESIGNER_PANE_HEIGHT));
372
373                add(designersplitpane);
374        }
375
376
377        /**
378         * Method that sets the location for the images directory for the icons and
379         * appends ".gif" or ".png", etc. to the name of the file if you pass it the name of the
380         * image that you would like to use.
381         * 
382         * @param iconname
383         * @param extension
384         * 
385         * @return the URL for the icon.
386         * 
387         * 
388         */
389        public URL getIconURL(String iconname, String extension) {
390
391                String IconLocation = IMAGES_DIR + iconname + "." + extension;
392                URL iconURL = ItemsOfInterestPanel.class.getResource(IconLocation);
393
394                return iconURL;
395        }
396
397        
398
399        /**
400         * creates a generic Drag and Drop Panel these are the panels that you can
401         * drag around and re-order a new panel is created when the user drops any
402         * item of interest onto the report layout canvas. This method also adds the
403         * newly created panel to the ReportItemPanels list.
404         * 
405         * @return DragAndDropPanel panel
406         */
407        private DragAndDropPanel createDragAndDropPanel() {
408                DragAndDropPanel panel = new DragAndDropPanel(this);
409
410                panel.setBounds(200, 200, 400, 500); // this sets the size of the draggable  ## SET SIZE
411                                                                                        // area
412
413                getReportItemPanels().add(panel);
414
415                return panel;
416        }
417
418        /**
419         * creates a Drag and Drop Panel that represents a Dynamic Report Item.
420         * a Dynamic Report Item represents something that is from the
421         * workflow and is recorded by the Provenance recorder.
422         * 
423         * @param tmpItem
424         * @param dynamicreportItemButton
425         * 
426         * @return DragAndDropPanel panel
427         */
428        private DragAndDropPanel createDynamicReportItemView(Item tmpItem,
429                        ReportItemButton dynamicreportItemButton) {
430          
431                String strItemFullName = tmpItem.getName(); 
432                dynamicreportItemButton.setToolTipText(strItemFullName);
433                DeleteItemButton deleteitembutton = makeDynamicItemDeleteButton("delete", "delete", tmpItem, "Delete", "Delete");
434                //deleteitembutton.setBackground(transparentblue);  //##
435
436                DynamicReportItemPanel panel = new DynamicReportItemPanel(this, tmpItem,
437                                dynamicreportItemButton, deleteitembutton, strItemFullName, reportLayout, _frame);
438                
439                deleteitembutton.setAssociatedPanel(panel);
440
441                panel.setBounds(0, 0, 500, 550); // this sets the size of the draggable  // area
442                
443                panel.setBackground(Color.white);
444
445                getReportItemPanels().add(panel);
446        
447
448                return panel;
449        }
450
451        /**
452         * get ReportItemPanels() gets the ReportItemPanels in general, the panels are laid out directly
453         * from the report model, but this is used for the GUI to re-arrange the
454         * panels and access report items that are associated with them.
455         * 
456         * @return reportitemPanels
457         */
458        public List<DragAndDropPanel> getReportItemPanels() {
459                
460                return reportitemPanels;
461        }
462
463        /**
464         * redrawView() redraws the view, from getReportItemPanels 
465         * using GridBagConstraints
466         */
467        protected void redrawView() {
468        
469                // Create the GridBag constraints, and set the ones that
470                // don't change.
471
472                final GridBagConstraints gbc = new GridBagConstraints();
473                gbc.gridwidth = GridBagConstraints.REMAINDER;
474                gbc.gridx = 0;
475                gbc.anchor = GridBagConstraints.NORTH;
476                gbc.weighty = 0.0;
477                gbc.fill = GridBagConstraints.NONE;
478
479                int row = 0;
480
481                // Clear out all (and I do mean ALL, not just the DnD Panels) components
482                // from the ReportDesignerPanel.
483
484                removeAll();
485                // _frame.pack();
486
487                // At this point, just sets up the Report Designer Panel titled border..
488                createTabContents();
489
490                // Put some room around the panels so the user can drag and
491                // drop them easily. 
492                gbc.insets = new Insets(PANEL_INSET_TOP, 
493                                PANEL_INSET_LEFT, PANEL_INSET_BOTTOM, PANEL_INSET_RIGHT);
494
495                // dynamically resize layoutpanel based on sum of heights of
496                // contained DragAndDropPanels, + some deads space for distinguishing 
497                // the end of layout + space between panels
498                int newLayoutPanelHeight = PANEL_HEIGHT_DEADSPACE+
499                        (getReportItemPanels().size()*(PANEL_INSET_BOTTOM+PANEL_INSET_TOP));
500                
501                for (DragAndDropPanel dragAndDropPanel : getReportItemPanels()) {
502                        gbc.gridy = row++;
503
504                        Item item = dragAndDropPanel.getAssociatedItem();
505
506                        if (item.isSelected()) {
507                                dragAndDropPanel.selectPanel();
508                        } else {
509                                dragAndDropPanel.deselectPanel();
510                        }
511                        
512                        // FIXME seems like it would make more sense to call 
513                        // dragAndDropPanel.getHeight(), but these are returning heights
514                        // larger than I expect, so:
515                        if (dragAndDropPanel instanceof DynamicReportItemPanel){
516                                newLayoutPanelHeight += DynamicReportItemPanel.DYNAMIC_REPORT_ITEM_VIEW_HEIGHT;
517                        }
518                        else {
519                                newLayoutPanelHeight += DragAndDropPanel.DRAG_AND_DROP_PANEL_HEIGHT;
520                        }
521
522                        layoutpanel.add(dragAndDropPanel, gbc);
523                }
524
525                gbc.weighty = 1.0;
526                gbc.weightx = 1.0;
527                gbc.fill = GridBagConstraints.BOTH;
528                gbc.gridy = row++;
529                Component strut = Box.createVerticalStrut(1);
530                layoutpanel.add(strut, gbc);
531                
532                layoutpanel.setPreferredSize(new Dimension(LAYOUT_PANEL_WIDTH, newLayoutPanelHeight));
533
534                
535                validate();
536                repaint();
537        }
538
539        /**
540         * addDeleteButton() adds the delete button to the toolbar.
541         * there is also an 'Open ROML' button that is commented out, but can be uncommented
542         * if necessary for testing purposes.  Note: 'Open ROMl' works with a test class located in
543         * org.kepler.reporting.rio.test  ReportTest.java
544         * 
545         * @param toolBar
546         * @param associtem
547         * @param panel
548         * 
549         */
550        protected void addDeleteButton(JToolBar toolBar, Item associtem, DragAndDropPanel panel) {
551
552                DeleteItemButton btndeleteitem = null;
553
554                btndeleteitem = makeDeleteButton("delete", "delete",
555                                associtem, panel, "Delete", "Delete");
556                
557                if (!isWindows()){
558                        btndeleteitem.setBackground(transparentblue);
559                }
560                
561                btndeleteitem.setBorderPainted(false);
562                btndeleteitem.setText("Delete");
563                toolBar.add(btndeleteitem);
564        }
565        
566        
567        /**
568         * makeDeleteButton() creates the Delete Button for the Static Items.
569         * 
570         * @param imageName
571         * @parma actionCommand
572         * @param associtem
573         * @param panel
574         * @param toolTipText
575         * @param altText
576         * 
577         * @return DeleteItemButton deletebutton
578         * 
579         */
580        protected DeleteItemButton makeDeleteButton(String imageName,
581                        String actionCommand, Item associtem, DragAndDropPanel panel, String toolTipText, String altText) {
582                
583                DeleteItemButton deletebutton = new DeleteItemButton();
584                // Look for the image.
585                String imgLocation = IMAGES_DIR + imageName + ".png";
586                URL imageURL = ReportDesignerPanel.class.getResource(imgLocation);
587
588                // Create and initialize the button.
589                deletebutton.setActionCommand(actionCommand);
590                deletebutton.setToolTipText(toolTipText);
591                deletebutton.addActionListener(this);
592        //      deletebutton.setBackground(buttonbackgroundcolor2);
593                
594                deletebutton.setAssociatedItem(associtem);
595                deletebutton.setAssociatedPanel(panel);
596
597                if (imageURL != null) { // image found
598                        deletebutton.setIcon(new ImageIcon(imageURL, altText));
599                } else { // no image found
600                        deletebutton.setText(altText);
601                        System.err.println("Resource not found: " + imgLocation);
602                }
603                
604                deletebutton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
605                deletebutton.setToolTipText("Delete this report item");
606                return deletebutton;
607        }
608
609        
610        /**
611         * makeDynamicItemDeleteButton() creates the Delete Button for the Dynamic Items.
612         * 
613         * @param imageName
614         * @parma actionCommand
615         * @param associtem
616         * @param toolTipText
617         * @param altText
618         * 
619         * @return DeleteItemButton deletebutton
620         * 
621         */
622        protected DeleteItemButton makeDynamicItemDeleteButton(String imageName,
623                        String actionCommand, Item associtem, String toolTipText, String altText) {
624                
625                DeleteItemButton deletebutton = new DeleteItemButton();
626                // Look for the image.
627                String imgLocation = IMAGES_DIR + imageName + ".png";
628                URL imageURL = ReportDesignerPanel.class.getResource(imgLocation);
629
630                // Create and initialize the button.
631                deletebutton.setActionCommand(actionCommand);
632                deletebutton.setToolTipText(toolTipText);
633                deletebutton.addActionListener(this);
634                
635                if (!isWindows()){
636                        deletebutton.setBackground(transparentblue);
637                }
638                
639                deletebutton.setAssociatedItem(associtem);
640
641                if (imageURL != null) { // image found
642                        //deletebutton.setIcon(new ImageIcon(imageURL, altText));
643                        deletebutton.setIcon(new ImageIcon(imageURL));
644                } else { // no image found
645                        deletebutton.setText(altText);
646                        System.err.println("Resource not found: " + imgLocation);
647                }
648                
649                deletebutton.setText(altText);
650                deletebutton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
651                deletebutton.setToolTipText("Delete this report item");
652                return deletebutton;
653        }
654        
655        
656        public static boolean isWindows() {
657                String os = System.getProperty("os.name").toLowerCase();
658                return (os.indexOf("win") >= 0);
659                
660        }
661        
662        public static boolean isMac() {
663                String os = System.getProperty("os.name").toLowerCase();
664                return (os.indexOf("mac") >=0);
665        }
666        
667        public static boolean isUnix() {
668                String os = System.getProperty("os.name").toLowerCase();
669                return (os.indexOf("nix") >=0 || os.indexOf("nux") >=0);
670        }
671
672        public void actionPerformed(ActionEvent e) {
673                String cmd = e.getActionCommand();
674                String delete = "delete";
675                String addsection = "add";
676                String openroml = "open";
677                String openimagefile = "openimagefile";
678                                
679                if (delete.equals(cmd)) {
680
681                        if (!getReportItemPanels().isEmpty()) {
682                                
683                                DeleteItemButton deleteButton = (DeleteItemButton) e.getSource();
684                                Item itemtodelete = deleteButton.getAssociatedItem();
685                                DragAndDropPanel clickedDnDPanel = deleteButton.getAssociatedPanel();
686                                DragAndDropPanel prevPanel = getPrevPanel();
687
688                                if (!clickedDnDPanel.equals(prevPanel)) {
689                                        prevPanel.deselectPanel();
690                                        clickedDnDPanel.selectPanel();
691                                        setCurrPanel(clickedDnDPanel);
692                                }
693
694                                requestFocusInWindow();
695                                
696                                setPrevPanel(clickedDnDPanel);
697                                
698                                clickedDnDPanel.selectPanel();
699                
700                                deleteItemFromLayout(itemtodelete);
701                                
702                                // XXX no need to redraw here, since redraw also called 
703                                // from renderReportLayout, right?
704                                //redrawView();
705                                renderReportLayout();
706                                
707                                // XXX find suitable replacement for hardcode 100
708                                //System.out.println("delete occurred, scroll to "+(clickedDnDPanel.getY()+100));
709                                Rectangle visibleRect = new Rectangle(0, clickedDnDPanel.getY()+100, 0, 0);
710                                layoutpanel.scrollRectToVisible(visibleRect);
711                        }
712
713
714                } else if (addsection.equals(cmd)) {
715                        // System.out.println("Add A Section");
716
717                } else if (openroml.equals(cmd)) {
718
719                        this.reportLayout = ReportTest.makeReportLayout();
720                        this.renderReportLayout();
721
722                } else if (openimagefile.equals(cmd)) {
723                        
724                        //TODO it would probably be better to check if the Image ( see
725                        // setImageButtonIconfromFile) has changed before rolling revision:
726                        reportLayout.setModified(_frame);
727                        
728                        JRadioButton imageButton = (JRadioButton) e.getSource();
729                        DragAndDropPanel imagePanel = (DragAndDropPanel) imageButton
730                                .getParent();
731                        Item imageitem = imagePanel.getAssociatedItem();
732                        imageitem.getValues().clear();
733                        JRadioButton button = (JRadioButton) imagePanel.getComponent(0);
734                        setImageButtonIconfromFile(button, imageitem);
735                }       
736        }
737        
738        
739        /**
740         * setImageButtonIconfromFile() creates a new icon for a static report item
741         * of the type image.  When the user selects an image file from the filesystem,
742         * this method creates a new icon using that image.
743         * 
744         * @param button
745         * @parma imageitem
746         * 
747         */
748        private void setImageButtonIconfromFile(JRadioButton button, Item imageitem) {
749                
750                PtFileChooser fc = new PtFileChooser(_frame, "Choose image", JFileChooser.OPEN_DIALOG);
751                String extensions[] = {"gif", "jpg", "jpeg", "png"};
752                ExtensionFilenameFilter filter = new ExtensionFilenameFilter(extensions, "images");
753                fc.addChoosableFileFilter(filter);
754        
755                int status = fc.showDialog(_frame, "Open");
756
757                if (status == JFileChooser.APPROVE_OPTION) {
758                        File file = fc.getSelectedFile();
759
760                        String imagefilepath = file.getAbsolutePath();
761
762                        ItemValue imageitemvalue = new ItemValue();
763                        imageitemvalue.setValue(new StringToken(imagefilepath));
764                        imageitem.getValues().add(imageitemvalue);
765
766                        Image image = Toolkit.getDefaultToolkit().getImage(
767                                        file.getPath());
768
769                        image = new ImageIcon(image).getImage();
770
771                        image = image.getScaledInstance(42, 42, Image.SCALE_SMOOTH);
772                        ImageIcon newicon = new ImageIcon(image);
773
774                        button.setIcon(newicon);
775
776                } else {
777                        // System.out.println("Open command cancelled by the user");
778                }
779        }
780
781        
782
783        /**
784         * 
785         * clearReportLayout() as it says ... Clears the report Layout object model.
786         * 
787         */
788        private void clearReportLayout() {
789
790                reportLayout.getSections().get(0).getColumns().get(0).getItems()
791                                .clear();
792        }
793
794        /**
795         * 
796         * Renders the GUI view of the Report Layout, where each report item
797         * is represented by a DragAndDropPanel that contains a reference to it's
798         * report item, and that report item's associated values, labels,
799         * and properties.  Report items can be Dynamic or Static.
800         * Dynamic report items are items that come from the workflow ports
801         * or parameters.  Static report items are used for entering static
802         * text, images, section headers, and horizontal rules.
803         * 
804         */
805        private void renderReportLayout() {
806                
807                ///String newtitle = reportLayout.getTitle();
808                ///titletxt.setText(newtitle);
809
810                List<Item> inMemoryItemList = null;
811        
812                getReportItemPanels().clear();
813                
814                // Get a list of report items from the reportLayout
815                inMemoryItemList = reportLayout.getSections().get(0).getColumns()
816                                .get(0).getItems();
817
818                for (int i = 0; i < inMemoryItemList.size(); i++) {                     
819                        final Item tmpItem = inMemoryItemList.get(i);
820
821                        if (tmpItem instanceof DynamicReportItem) {
822                                renderDynamicReportItem(tmpItem);
823                        } else if (tmpItem instanceof StaticReportItem) {
824                                renderStaticReportItem(tmpItem);
825                        }
826                }
827
828                redrawView();
829        }
830        
831        //validate();   //These were not needed here, but leaving them in case they are needed at some point in the future.
832        //repaint();
833        
834        /**
835         * 
836         * renderStaticReportItem() - Renders the Static Report Items
837         * 
838         *  @param tmpItem
839         *  
840         *  @return DragAndDropPanel columnPanel
841         *  
842         *  Note: there is a reason that these are called 'columPanel', this is because
843         *  in the Report model these panels represent the last nested element in the
844         *  report that represents a 'column'.  Even though we don't have multiple column
845         *  layouts in this release.
846         *  
847         * 
848         */
849        public DragAndDropPanel renderStaticReportItem(Item tmpItem){
850                
851                // Note: A panel is added to the list of Panels at the time it
852                // is created.
853                DragAndDropPanel columnPanel = createDragAndDropPanel();
854                columnPanel = createStaticReportItemView(tmpItem, columnPanel);
855                columnPanel.setAssociatedItem(tmpItem);
856                
857                JToolBar toolbar = new JToolBar();
858                
859                if (!isWindows()){
860                        toolbar.setBackground(transparentblue);
861                }
862                
863                toolbar.setFloatable(false);
864                toolbar.setBorderPainted(false);
865
866                addDeleteButton(toolbar, tmpItem, columnPanel);
867                
868                columnPanel.add(BorderLayout.EAST,toolbar);
869
870                DragAndDropPanel prevSelectedPanel = getPrevPanel();
871
872                if (prevSelectedPanel != null) {
873                        
874                        prevSelectedPanel.deselectPanel();
875                        Item itemtodeselect = prevSelectedPanel.getAssociatedItem();
876                        itemtodeselect.setSelected(false);
877                        setPrevPanel(columnPanel);
878                        tmpItem.setSelected(true);
879                        columnPanel.selectPanel();
880                        setPrevPanel(columnPanel);
881                } else {
882
883                        setPrevPanel(columnPanel);
884                        tmpItem.setSelected(true);
885                        columnPanel.selectPanel();      
886                        setPrevPanel(columnPanel);
887                }
888        
889                return columnPanel;
890        }
891        
892        
893        /**
894         *  createStaticReportItemView - Creates the Views for the Static Report Items.
895         *  
896         *  @param Item tmpItem
897         *  @param DragAndDropPanel columnPanel
898         *  
899         *  @return DragAndDropPanel columnPanel
900         *  
901         */
902        public DragAndDropPanel createStaticReportItemView(final Item tmpItem,
903                        DragAndDropPanel columnPanel) {
904
905                JLabel staticreportItemLabel = new JLabel();
906                // staticreportItemLabel.setBackground(buttonbackgroundcolor);
907                ReportItemButton staticreportItemButton = new ReportItemButton();
908                // staticreportItemButton.setBackground(buttonbackgroundcolor);
909                columnPanel.setPropertiesButton(staticreportItemButton);
910                staticreportItemButton.setAssociatedPanel(columnPanel);
911                ReportItemButtonListener statlistener = new ReportItemButtonListener();
912                
913                staticreportItemButton.addMouseListener(statlistener);
914
915                List<ItemValue> inMemoryValuesList = null; // init values
916                inMemoryValuesList = tmpItem.getValues();
917                
918                // associates the static report item with its properties
919                // that are set from the properties panel.
920                staticreportItemButton.setAction(new AbstractAction(tmpItem.getName()) {
921                        public void actionPerformed(ActionEvent e) {
922                                ref.setSelectedItem(tmpItem);
923                                TabManager.getInstance().tabEvent(ref.getParentFrame(),
924                                                new ActionEvent(ref, 0, "Properties"));
925                        }
926                        
927                });
928                
929                
930                if (tmpItem instanceof StaticReportItemText) {
931                        
932                        // Text items may have a list of values.
933                        // Typically at this point it is just one value, in a list.
934
935                        if (inMemoryValuesList.size() == 0) {
936                                List<ItemValue> initval = new ArrayList<ItemValue>();
937                                ItemValue val = new ItemValue();
938                                StringToken strvaluetoken = new StringToken();
939
940                                val.setValue(strvaluetoken);
941                                initval.add(val);
942                                tmpItem.setValues(initval);
943                                String strvalue = strvaluetoken.stringValue();
944                                columnPanel.setAssociatedItem(tmpItem); 
945
946                                columnPanel = renderTextPanel(columnPanel,
947                                                staticreportItemLabel, staticreportItemButton, strvalue);
948
949                        } else {
950                                StringToken strtoken = (StringToken) inMemoryValuesList.get(0)
951                                                .getValue();
952                                String strvalue = strtoken.stringValue();
953                                tmpItem.getItemProperties();
954                                columnPanel.setAssociatedItem(tmpItem);
955
956                                columnPanel = renderTextPanel(columnPanel,
957                                                staticreportItemLabel, staticreportItemButton, strvalue);
958                        }
959
960                        columnPanel.setAssociatedItem((StaticReportItemText) tmpItem);
961
962                } else if (tmpItem instanceof StaticReportItemHR) {
963
964                        columnPanel = renderHRPanel(columnPanel, staticreportItemLabel,
965                                        staticreportItemButton);
966                        columnPanel.setAssociatedItem((StaticReportItemHR) tmpItem);
967
968                } else if (tmpItem instanceof StaticReportItemImage) {
969
970                        columnPanel.setAssociatedItem((StaticReportItemImage) tmpItem);
971                        columnPanel = renderImagePanel(tmpItem, columnPanel, staticreportItemLabel,
972                                        staticreportItemButton);
973                        
974                } else if (tmpItem instanceof StaticReportItemSection) {
975
976                        columnPanel.setAssociatedItem((StaticReportItemSection) tmpItem);
977
978                        if (inMemoryValuesList.size() == 0) {
979                                List<ItemValue> initval = new ArrayList<ItemValue>();
980                                ItemValue val = new ItemValue();
981                                StringToken strvaluetoken = new StringToken();
982                                val.setValue(strvaluetoken);
983                                initval.add(val);
984                                tmpItem.setValues(initval);
985                                String strvalue = strvaluetoken.stringValue();
986                                columnPanel = renderSectionPanel(columnPanel,
987                                                staticreportItemLabel, staticreportItemButton, strvalue);
988
989                        } else {
990                                StringToken strtoken = (StringToken) inMemoryValuesList.get(0)
991                                                .getValue();
992                                String strvalue = strtoken.stringValue();
993                                tmpItem.getItemProperties();
994                                columnPanel = renderSectionPanel(columnPanel,
995                                                staticreportItemLabel, staticreportItemButton, strvalue);
996                                columnPanel = renderSectionPanel(columnPanel,
997                                                staticreportItemLabel, staticreportItemButton, strvalue);
998
999                        }
1000
1001                }
1002
1003                if (tmpItem.isSelected()) {
1004                        columnPanel.selectPanel();
1005                
1006                }
1007
1008                return columnPanel;
1009
1010        }
1011        
1012        
1013        
1014
1015        
1016        /**
1017         * Data Flavor for the Drag and Drop Data Transfer Handler.
1018         * 
1019         * @return dragAndDropPanelDataFlavor
1020         * 
1021         */
1022        public static DataFlavor getDragAndDropPanelDataFlavor() throws Exception {
1023                if (dragAndDropPanelDataFlavor == null) {
1024                        dragAndDropPanelDataFlavor = new DataFlavor(
1025                                        DataFlavor.javaJVMLocalObjectMimeType
1026                                                        + "; class = org.kepler.reporting.gui.DragAndDropPanel");
1027                }
1028
1029                return dragAndDropPanelDataFlavor;
1030
1031        }
1032
1033        
1034        /**
1035         * Adds an item to the Report Layout model.
1036         * Used when you add a report item panel.
1037         * 
1038         * @param item
1039         * 
1040         */
1041        public void addItemToLayout(Item item) {
1042                
1043                reportLayout.getSections().get(0).getColumns().get(0).getItems().add(
1044                                item);
1045                
1046                /// don't call setModified here since everytime a DnD panel
1047                // is dragged, the entire layout is cleared and rebuilt.        
1048        }
1049        
1050        
1051        /**
1052         * Removes an item from the Report Layout.
1053         * Used when you delete a report item panel.
1054         * 
1055         * @param item
1056         * 
1057         */
1058        public void deleteItemFromLayout(Item item) {
1059
1060                reportLayout.getSections().get(0).getColumns().get(0).getItems()
1061                                .remove(item);
1062                reportLayout.setModified(_frame);
1063        }
1064
1065        
1066        /**
1067         * ArrangePanels is used to re-order the existing panels when you drag and drop them.
1068         * 
1069         * This is also used to translate the order of the panels in the GUI to the order of
1070         * the items in the report model. 
1071         * 
1072         * @param columnPanel
1073         * @param dropYLoc
1074         * 
1075         */
1076        public void arrangePanels(DragAndDropPanel columnPanel, int dropYLoc) {
1077                
1078                Item varitem = columnPanel.getAssociatedItem();
1079                varitem.setSelected(true);
1080
1081                TreeMap<Integer, DragAndDropPanel> yLocMapForPanels = new TreeMap<Integer, DragAndDropPanel>();
1082                yLocMapForPanels.put(dropYLoc, columnPanel);
1083                
1084                for (DragAndDropPanel dragAndDropPanel : getReportItemPanels()) {
1085                        // get the y value
1086                        int y = dragAndDropPanel.getY();
1087
1088                        // if it is the dropped panel, then skip it
1089                        if (!dragAndDropPanel.equals(columnPanel)) {
1090                                yLocMapForPanels.put(y, dragAndDropPanel);
1091                        }
1092                }
1093                
1094                // clear the previous reportLayout
1095                clearReportLayout();
1096
1097                // get the associated report items for each drag and drop panel and
1098                // create a newly re-ordered list of report items that reflects the 
1099                // order of the panels. This bit is important because it is what 
1100                // generates the model.
1101                for (int i: yLocMapForPanels.keySet()){
1102                        DragAndDropPanel dragAndDropPanel = yLocMapForPanels.get(i);
1103                        Item item = dragAndDropPanel.getAssociatedItem();
1104                        addItemToLayout(item);
1105                }
1106
1107                renderReportLayout();
1108                
1109                // XXX find suitable replacement for hardcode 100
1110                // dropYLoc alone wasn't high enough. 
1111                Rectangle visibleRect = new Rectangle(0, dropYLoc+100, 0, 0);
1112                layoutpanel.scrollRectToVisible(visibleRect);
1113        }
1114        
1115
1116        // View classes
1117        
1118        /**
1119         * renderTextPanel() - Renders the view for the StaticReportItemText
1120         * 
1121         * @param columnPanel
1122         * @param staticreprotItemLabel
1123         * @param staticreportItemButton
1124         * @param strtoken
1125         * 
1126         */
1127        public DragAndDropPanel renderTextPanel(DragAndDropPanel columnPanel,
1128                        JLabel staticreportItemLabel, JRadioButton staticreportItemButton,
1129                        String strtoken) {
1130
1131                staticreportItemButton.setText("");
1132
1133                URL texticonURL = getIconURL("text3", "png");
1134                ImageIcon texticon = new ImageIcon(texticonURL);
1135
1136                staticreportItemButton.setIcon(texticon);
1137                staticreportItemButton.setCursor(Cursor
1138                                .getPredefinedCursor(Cursor.HAND_CURSOR));
1139
1140                TextAreaReporting textPanelTextArea = new TextAreaReporting("", 15, 50);
1141                textPanelTextArea.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
1142
1143                Item columnpanelitem = columnPanel.getAssociatedItem();
1144                textPanelTextArea.setAssociatedItem(columnpanelitem);
1145        textPanelTextArea.setAssociatedPanel(columnPanel);
1146        
1147                textPanelTextArea.setLineWrap(true);
1148                textPanelTextArea.setText(strtoken);
1149                //textPanelTextArea.setEditable(false);
1150
1151                TextAreaItemMouseListener textareaMouseListener = new TextAreaItemMouseListener();
1152                textPanelTextArea.addMouseListener(textareaMouseListener);
1153                
1154                TextAreaDocumentListener textAreaDocumentListener = new TextAreaDocumentListener();
1155                textPanelTextArea.getDocument().addDocumentListener(textAreaDocumentListener);
1156                //TODO: putting the textPanelTextArea in as a property seems poor:
1157                textPanelTextArea.getDocument().putProperty("TextAreaReporting", textPanelTextArea);
1158
1159                textPanelTextArea.setVisible(true);
1160                JScrollPane txtscroll = new JScrollPane(textPanelTextArea);
1161
1162                ItemValue textpanelItemValue = new ItemValue();
1163                List<ItemValue> textpanelItemValuesList = new ArrayList<ItemValue>();
1164                String textareastring = textPanelTextArea.getText();
1165                textpanelItemValue.setValue(new StringToken(textareastring));
1166                textpanelItemValuesList.add(textpanelItemValue);
1167
1168                columnPanel.add(staticreportItemButton, BorderLayout.WEST);
1169                columnPanel.add(txtscroll);
1170
1171                return columnPanel;
1172        }
1173        
1174        
1175        /**
1176         * Renders the view for the StaticReportItemHR (Horizontal Rule)
1177         * 
1178         * @param columnPanel
1179         * @param staticreprotItemLabel
1180         * @param staticreportItemButton
1181         * 
1182         * @return columnPanel;
1183         * 
1184         */
1185        public DragAndDropPanel renderHRPanel(DragAndDropPanel columnPanel,
1186                        JLabel staticreportItemLabel, JRadioButton staticreportItemButton) {
1187
1188                staticreportItemLabel.setText("Horizontal Rule");
1189                staticreportItemButton.setText("");
1190
1191                URL horizontalruleURL = getIconURL("horizontalrule3", "png");
1192                ImageIcon horzruleicon = new ImageIcon(horizontalruleURL);
1193
1194                staticreportItemButton.setIcon(horzruleicon);
1195                staticreportItemButton.setCursor(Cursor
1196                                .getPredefinedCursor(Cursor.HAND_CURSOR));
1197
1198                columnPanel.add(staticreportItemButton);
1199                return columnPanel;
1200        }
1201        
1202        
1203        /**
1204         * Renders the view for the StaticReportItemSection (Section)
1205         * 
1206         * @param dragAndDropPanel
1207         * @param staticreprotItemLabel
1208         * @param staticreportItemButton
1209         * @param strtoken
1210         * 
1211         * @return columnPanel;
1212         * 
1213         */
1214        public DragAndDropPanel renderSectionPanel(DragAndDropPanel dragAndDropPanel,
1215                        JLabel staticreportItemLabel, JRadioButton staticreportItemButton,
1216                        String strtoken) {
1217                staticreportItemLabel.setText("Section");
1218                Font sectiontitlefont = new Font("SansSerif", Font.BOLD, 14);
1219
1220                staticreportItemButton.setText("");
1221                URL sectionURL = getIconURL("sectionheader3", "png");
1222                ImageIcon sectionheadericon = new ImageIcon(sectionURL);
1223                staticreportItemButton.setIcon(sectionheadericon);
1224
1225                staticreportItemButton.setCursor(Cursor
1226                                .getPredefinedCursor(Cursor.HAND_CURSOR));
1227
1228                SectionTextReporting sectionheadertext = new SectionTextReporting();
1229                sectionheadertext.setAssociatedPanel(dragAndDropPanel);
1230                sectionheadertext.setFont(sectiontitlefont);
1231                sectionheadertext.setText(strtoken);
1232
1233                SectionHeaderListener sectionheaderlistener = new SectionHeaderListener();
1234                sectionheadertext.addMouseListener(sectionheaderlistener);
1235                
1236                SectionHeaderDocumentListener sectionHeaderDocumentListener = 
1237                        new SectionHeaderDocumentListener();
1238                sectionheadertext.getDocument().addDocumentListener(sectionHeaderDocumentListener);
1239                //TODO putting sectionheadertext as property seems poor:
1240                sectionheadertext.getDocument().putProperty("SectionTextReporting", sectionheadertext);
1241        
1242                ItemValue sectionheaderitemvalue = new ItemValue();
1243                List<ItemValue> sectionItemValuesList = new ArrayList<ItemValue>();
1244                String textareastring = sectionheadertext.getText();
1245                sectionheaderitemvalue.setValue(new StringToken(textareastring));
1246                sectionItemValuesList.add(sectionheaderitemvalue);
1247                
1248                dragAndDropPanel.add(staticreportItemButton, BorderLayout.WEST);
1249                dragAndDropPanel.add(sectionheadertext);
1250                dragAndDropPanel.setPropertiesButton(staticreportItemButton);
1251
1252                sectionheadertext.setVisible(true);
1253                sectionheadertext.requestFocus();  // doesn't do anything
1254
1255
1256                return dragAndDropPanel;
1257        }
1258        
1259        
1260        /**
1261         * Renders the view for the StaticReportItemImage (static image)
1262         *
1263         * @param dragAndDropPanel
1264         * @param staticreprotItemLabel
1265         * @param staticreportItemButton
1266         *
1267         * 
1268         * @return columnPanel;
1269         */
1270        public DragAndDropPanel renderImagePanel(Item tmpItem, DragAndDropPanel dragAndDropPanel,
1271                        JLabel staticreportItemLabel, JRadioButton staticreportItemButton) {
1272                
1273                // when we get here if it had a value, then the static reportItemButton
1274                // already has it's icon, if not, then we use the generic icon for an image
1275                // static report item.
1276                
1277                staticreportItemLabel.setText("Image");
1278                staticreportItemButton.setText("");
1279                
1280
1281                List<ItemValue> tmpURLvalues = tmpItem.getValues();
1282                
1283                if (tmpURLvalues.size() != 0) {
1284
1285                        ItemValue itemValue = tmpURLvalues.get(0);
1286                        StringToken urlStrToken = (StringToken) itemValue.getValue();
1287                        String urlStr = urlStrToken.stringValue();
1288
1289                        Image userassignedimage = null;
1290                        URL errorURL = getIconURL("error", "png");
1291
1292                        try {
1293                                userassignedimage = ImageIO.read(new File(urlStr));
1294
1295                        } catch (IOException e) {
1296                                System.out
1297                                                .println("ReportDesignerPanel renderImagePanel can't read file:"
1298                                                                + urlStr);
1299                                try {
1300                                        urlStr = ImageUtil.decodeToFile(itemValue.getBase64data());
1301                                        userassignedimage = ImageIO.read(new File(urlStr));
1302
1303                                } catch (IOException e1) {
1304                                        try {
1305                                                userassignedimage = ImageIO.read(errorURL);
1306                                        } catch (IOException e2) {
1307                                                // TODO Auto-generated catch block
1308                                                e2.printStackTrace();
1309                                        }
1310                                        e1.printStackTrace();
1311                                }
1312                        }
1313
1314                        userassignedimage = userassignedimage.getScaledInstance(30, 30,
1315                                        Image.SCALE_SMOOTH);
1316                        userassignedimage = new ImageIcon(userassignedimage).getImage();
1317
1318                        userassignedimage = userassignedimage.getScaledInstance(30, 30,
1319                                        Image.SCALE_SMOOTH);
1320                        ImageIcon userassignedicon = new ImageIcon(userassignedimage);
1321
1322                        staticreportItemButton.setIcon(userassignedicon);
1323
1324                        getimagebtn = new JRadioButton();
1325                        getimagebtn.setText("Get new image...");
1326
1327                        URL addfileURL = getIconURL("add3", "png");
1328                        ImageIcon addicon = new ImageIcon(addfileURL);
1329
1330                        getimagebtn.setIcon(addicon);
1331
1332                        getimagebtn.setCursor(Cursor
1333                                        .getPredefinedCursor(Cursor.HAND_CURSOR));
1334                        getimagebtn.setActionCommand("openimagefile");
1335                        getimagebtn.addActionListener(this);
1336                        // getimagebtn.setBackground(buttonbackgroundcolor); // This is for
1337                        // the PC
1338                        getimagebtn.setToolTipText("Browse for image");
1339
1340                        staticreportItemButton.setCursor(Cursor
1341                                        .getPredefinedCursor(Cursor.HAND_CURSOR));
1342                        staticreportItemButton.setToolTipText("View Item Properties");
1343                        dragAndDropPanel.add(staticreportItemButton, BorderLayout.WEST);
1344                        dragAndDropPanel.add(getimagebtn);
1345                } 
1346                else {
1347                
1348                        URL staticimageURL = getIconURL("image3", "png");
1349                        ImageIcon staticimageicon = new ImageIcon(staticimageURL);
1350                        staticreportItemButton.setIcon(staticimageicon);
1351
1352                        getimagebtn = new JRadioButton();
1353                        getimagebtn.setText("Get image...");
1354
1355                        URL addfileURL = getIconURL("add3", "png");
1356                        ImageIcon addicon = new ImageIcon(addfileURL);
1357
1358                        getimagebtn.setIcon(addicon);
1359
1360                        getimagebtn.setCursor(Cursor
1361                                        .getPredefinedCursor(Cursor.HAND_CURSOR));
1362                        getimagebtn.setActionCommand("openimagefile");
1363                        getimagebtn.addActionListener(this);
1364
1365                        staticreportItemButton.setCursor(Cursor
1366                                        .getPredefinedCursor(Cursor.HAND_CURSOR));
1367                        dragAndDropPanel.add(staticreportItemButton, BorderLayout.WEST);
1368                        dragAndDropPanel.add(getimagebtn);
1369                }
1370        
1371                return dragAndDropPanel;
1372                
1373        }
1374        
1375        
1376        // Listener classes
1377        
1378        public class SectionHeaderDocumentListener implements DocumentListener{
1379
1380                public void changedUpdate(DocumentEvent e) {                    
1381                }
1382
1383                public void insertUpdate(DocumentEvent e) {
1384                        SectionTextReporting sectiontext = (SectionTextReporting) 
1385                                e.getDocument().getProperty("SectionTextReporting");
1386                        StringToken strtoken = new StringToken(sectiontext.getText());
1387                        ItemValue sectionheadertextvalue = new ItemValue(strtoken);
1388                        List<ItemValue> sectionheadertextvaluelist = new ArrayList<ItemValue>();
1389                        sectionheadertextvaluelist.add(sectionheadertextvalue);
1390
1391                        DragAndDropPanel sectionPanel = (DragAndDropPanel) sectiontext
1392                                        .getParent();
1393
1394                        Item item = sectionPanel.getAssociatedItem();
1395
1396                        item.setValues(sectionheadertextvaluelist);
1397                        reportLayout.setModified(_frame);
1398                }
1399
1400                public void removeUpdate(DocumentEvent e) {
1401                        SectionTextReporting sectiontext = (SectionTextReporting) 
1402                        e.getDocument().getProperty("SectionTextReporting");
1403                        StringToken strtoken = new StringToken(sectiontext.getText());
1404                        ItemValue sectionheadertextvalue = new ItemValue(strtoken);
1405                        List<ItemValue> sectionheadertextvaluelist = new ArrayList<ItemValue>();
1406                        sectionheadertextvaluelist.add(sectionheadertextvalue);
1407
1408                        DragAndDropPanel sectionPanel = (DragAndDropPanel) sectiontext
1409                        .getParent();
1410
1411                        Item item = sectionPanel.getAssociatedItem();
1412
1413                        item.setValues(sectionheadertextvaluelist);
1414                        reportLayout.setModified(_frame);
1415                }
1416                
1417        }
1418        
1419        
1420        /**
1421         * SectionHeaderListener - Mouse Listener for the Section static report item
1422         */
1423        public class SectionHeaderListener implements MouseListener {
1424
1425                public void mouseClicked(MouseEvent e) {
1426                        
1427                        SectionTextReporting sectiontext = (SectionTextReporting) e.getSource();
1428                        
1429                        DragAndDropPanel sectiontextpanel = sectiontext.getAssociatedPanel();                   
1430                        DragAndDropPanel prevPanel = getPrevPanel();
1431                        prevPanel.deselectPanel();
1432                        sectiontextpanel.selectPanel();
1433                        sectiontextpanel.getAssociatedItem().setSelected(true);
1434                        sectiontextpanel.setBorder(new OvalBorder(3, 3, Color.blue, Color.blue));
1435                        sectiontextpanel.setOpaque(false);
1436                        sectiontextpanel.setBackground(new Color(6, 128, 255, 129).darker());
1437                        setCurrPanel(sectiontextpanel);
1438                        setPrevPanel(sectiontextpanel);
1439                }
1440        
1441                public void mousePressed(MouseEvent e) {
1442                        
1443                        SectionTextReporting sectiontext = (SectionTextReporting) e.getSource();
1444                        DragAndDropPanel clickedDnDPanel = (DragAndDropPanel) sectiontext.getAssociatedPanel();
1445                        DragAndDropPanel prevPanel = getPrevPanel();
1446                        
1447                        if (!clickedDnDPanel.equals(prevPanel)) {
1448
1449                                        prevPanel.deselectPanel();
1450                                        
1451                                        ///clickedDnDPanel.selected = true;
1452                                        clickedDnDPanel.setBorder(new OvalBorder(3, 3, Color.blue, Color.blue));
1453                                        clickedDnDPanel.setOpaque(false);
1454                                        clickedDnDPanel.setBackground(new Color(6, 128, 255, 129).darker()); 
1455                                        setCurrPanel(clickedDnDPanel);
1456                                        setPrevPanel(clickedDnDPanel);
1457                                }
1458                }
1459
1460                public void mouseReleased(MouseEvent e) {
1461                }
1462                public void mouseEntered(MouseEvent e) {
1463                }
1464                public void mouseExited(MouseEvent e) {
1465                }
1466                
1467        }
1468        
1469        
1470        public class TitleDocumentListener implements DocumentListener {
1471
1472                public void changedUpdate(DocumentEvent e) {
1473                }
1474                public void removeUpdate(DocumentEvent e) {
1475                        try {
1476                                reportLayout.setTitle(e.getDocument().getText(0, e.getDocument().getLength()));
1477                                reportLayout.setModified(_frame);
1478                        } catch (BadLocationException e1) {
1479                                // TODO Auto-generated catch block
1480                                e1.printStackTrace();
1481                        }
1482                }
1483                public void insertUpdate(DocumentEvent e) {
1484                        try {
1485                                reportLayout.setTitle(e.getDocument().getText(0, e.getDocument().getLength()));
1486                                reportLayout.setModified(_frame);
1487                        } catch (BadLocationException e1) {
1488                                // TODO Auto-generated catch block
1489                                e1.printStackTrace();
1490                        }
1491                }
1492        }
1493        
1494
1495        /**
1496         * Mouse Listener for the Text area static report item
1497         */
1498        public class TextAreaItemMouseListener implements MouseListener {
1499
1500                public void mouseClicked(MouseEvent e) {
1501
1502                        TextAreaReporting textareatext = (TextAreaReporting) e.getSource();
1503                        DragAndDropPanel clickedDnDPanel = (DragAndDropPanel) textareatext.getAssociatedPanel();
1504                        DragAndDropPanel prevPanel = getPrevPanel();
1505                        
1506                        if (!clickedDnDPanel.equals(prevPanel)) {
1507
1508                                        prevPanel.deselectPanel();
1509                                        
1510                                        clickedDnDPanel.getAssociatedItem().setSelected(true);
1511                                        clickedDnDPanel.selectPanel();
1512                                        clickedDnDPanel.setBorder(new OvalBorder(3, 3, Color.blue, Color.blue));
1513                                        clickedDnDPanel.setOpaque(false);
1514                                        clickedDnDPanel.setBackground(new Color(6, 128, 255, 129).darker()); 
1515                                        setCurrPanel(clickedDnDPanel);
1516                                        setPrevPanel(clickedDnDPanel);
1517                                }
1518                }
1519
1520                public void mouseEntered(MouseEvent e) {
1521                }
1522                public void mouseExited(MouseEvent e) {
1523                }
1524                public void mousePressed(MouseEvent e) {
1525                }
1526                public void mouseReleased(MouseEvent e) {
1527                }
1528                
1529        }
1530
1531        public class TextAreaDocumentListener implements DocumentListener{
1532
1533                public void changedUpdate(DocumentEvent e) {
1534                }
1535
1536                public void insertUpdate(DocumentEvent e) {
1537                        
1538                        TextAreaReporting textareatext = 
1539                                (TextAreaReporting) e.getDocument().getProperty("TextAreaReporting");
1540                        ///textareatext.setEditable(true);
1541                        String textFromTextArea = textareatext.getText();
1542
1543                        if (textFromTextArea.equals("")) {
1544                                StringToken strtoken = new StringToken("");
1545                                ItemValue exittext = new ItemValue(strtoken);
1546                                List<ItemValue> exittextlist = new ArrayList<ItemValue>();
1547                                exittextlist.add(exittext);
1548                                Item item = textareatext.getAssociatedItem();
1549                                item.setValues(exittextlist);
1550                                reportLayout.setModified(_frame);
1551
1552                        } else {
1553                                StringToken strtoken = new StringToken(textFromTextArea);
1554                                ItemValue exittext = new ItemValue(strtoken);
1555                                List<ItemValue> exittextlist = new ArrayList<ItemValue>();
1556                                exittextlist.add(exittext);
1557                                Item item = textareatext.getAssociatedItem();
1558                                // item.getValues().clear();
1559                                item.setValues(exittextlist);
1560                                reportLayout.setModified(_frame);
1561                        }
1562                                
1563                }
1564
1565                public void removeUpdate(DocumentEvent e) {
1566                        
1567                        TextAreaReporting textareatext = 
1568                                (TextAreaReporting) e.getDocument().getProperty("TextAreaReporting");
1569                        ///textareatext.setEditable(true);
1570                        String textFromTextArea = textareatext.getText();
1571
1572                        if (textFromTextArea.equals("")) {
1573                                StringToken strtoken = new StringToken("");
1574                                ItemValue exittext = new ItemValue(strtoken);
1575                                List<ItemValue> exittextlist = new ArrayList<ItemValue>();
1576                                exittextlist.add(exittext);
1577                                Item item = textareatext.getAssociatedItem();
1578                                item.setValues(exittextlist);
1579                                reportLayout.setModified(_frame);
1580
1581                        } else {
1582                                StringToken strtoken = new StringToken(textFromTextArea);
1583                                ItemValue exittext = new ItemValue(strtoken);
1584                                List<ItemValue> exittextlist = new ArrayList<ItemValue>();
1585                                exittextlist.add(exittext);
1586                                Item item = textareatext.getAssociatedItem();
1587                                // item.getValues().clear();
1588                                item.setValues(exittextlist);
1589                                reportLayout.setModified(_frame);
1590                        }
1591                        
1592                }
1593                
1594        }
1595        
1596        
1597        /**
1598         * DeletePanel - deletes a panel when the 'delete panel' button is pressed.
1599         * 
1600         * @param deletedPanel
1601         * @param deletedYLoc
1602         * 
1603         */
1604        public void deletePanel(DragAndDropPanel deletedPanel, int deletedYLoc) {
1605                
1606                Map<Integer, DragAndDropPanel> yLocMapForPanels = new HashMap<Integer, DragAndDropPanel>();
1607                yLocMapForPanels.put(deletedYLoc, deletedPanel);
1608
1609                for (DragAndDropPanel dragAndDropPanel : getReportItemPanels()) {
1610
1611                        // if it is the dropped panel, then skip it
1612                        if (!dragAndDropPanel.equals(deletedPanel)) {
1613                                // get the y value
1614                                int y = dragAndDropPanel.getY();
1615                                yLocMapForPanels.remove(y);
1616                        }
1617                }
1618
1619        }
1620        
1621        /**
1622         * getPrevSelectedPanel - figures out which panel was previously selected, so that we
1623         * can de-select it, and change the colors, etc.
1624         * 
1625         * @param List<DragAndDropPanel> reportpanelslist
1626         * 
1627         * @return DragAndDropPanel prevSelectedPanel
1628         * 
1629         */
1630        public DragAndDropPanel getPrevSelectedPanel(
1631                        List<DragAndDropPanel> reportpanelslist) {
1632
1633                if (reportpanelslist.size() != 0) {
1634                        for (int i = 0; i < (reportpanelslist.size()); i++) {
1635
1636                                DragAndDropPanel panel = reportpanelslist.get(i);
1637
1638                                if (panel.isSelected()) {
1639                                        prevSelectedPanel = panel;
1640                                        currSelectedPanel = panel;
1641                                        panel.selectPanel();
1642                                }
1643
1644                        }
1645                }
1646
1647                return prevSelectedPanel;
1648        }
1649        
1650        
1651        /**
1652         * getSelectedPanel - figures out which panel is currently selected, so that we
1653         * can see if it is the same as the previously selected one, and if it isn't the
1654         * same -- then change the colors, etc.
1655         * 
1656         * @param List<DragAndDropPanel> reportpanelslist
1657         * 
1658         * @return DragAndDropPanel currSelectedPanel
1659         * 
1660         */
1661        public DragAndDropPanel getSelectedPanel(
1662                        List<DragAndDropPanel> reportpanelslist) {
1663
1664                if (!reportpanelslist.isEmpty()) {
1665                        for (DragAndDropPanel panel: reportpanelslist) {                                
1666                                if (panel.isSelected()) {
1667                                        currSelectedPanel = panel;
1668                                }
1669                        }
1670                }
1671
1672                return currSelectedPanel;
1673        }
1674
1675
1676        public void setPrevPanel(DragAndDropPanel prevpanel) {
1677                prevSelectedPanel = prevpanel;
1678        }
1679
1680        public void setPrevSelectedItem(Item prevItem) {
1681                prevSelectedItem = prevItem;
1682        }
1683
1684        public Item getPrevSelectedItem() {
1685                return prevSelectedItem;
1686        }
1687
1688        public void setCurrPanel(DragAndDropPanel currpanel) {
1689                currSelectedPanel = currpanel;
1690        }
1691        
1692        public void setCurrSelectedItem(Item currItem) {
1693                thecurrentitem = currItem;
1694        }
1695
1696        public Item getCurrSelectedItem() {
1697                return thecurrentitem;
1698        }
1699        
1700        public DragAndDropPanel getPrevPanel() {
1701                return prevSelectedPanel;
1702        }
1703        
1704        
1705        public void dragEnter(DropTargetDragEvent dtde) {
1706
1707        }
1708
1709        public void dragExit(DropTargetEvent dte) {
1710
1711        }
1712
1713        public void dragOver(DropTargetDragEvent dtde) {
1714                if (!this.getCursor().equals(droppableCursor)) {
1715                        this.setCursor(droppableCursor);    // droppableCursor
1716                }
1717        
1718        }
1719
1720        public void drop(DropTargetDropEvent dtde) {
1721                
1722                final int dropYLoc = dtde.getLocation().y;
1723                
1724                try {
1725
1726                        // First we get the transferable proxy from the drop event.
1727
1728                        Transferable tr = dtde.getTransferable();   // The transfer object is not actually transferring any text, only the JPanel itself is being transferred.
1729
1730                        // get the named object from the outline
1731                        NamedObj droppedObj = null;
1732                        try {
1733                                List droppedObjects = (List) tr
1734                                                .getTransferData(PtolemyTransferable.namedObjFlavor);
1735                                if (droppedObjects != null && droppedObjects.size() > 0) {
1736                                        droppedObj = (NamedObj) droppedObjects.get(0);
1737                                        List children = droppedObj.attributeList();
1738                                        
1739                                        if (!children.isEmpty()) {
1740                                                if (
1741                                                                !(droppedObj instanceof Parameter)
1742                                                                &&
1743                                                                !(droppedObj instanceof Port)
1744                                                                // FIXME if Provenance records the CompositeActor tokens, then we can report on them.
1745                                                                // see: http://bugzilla.ecoinformatics.org/show_bug.cgi?id=4436
1746                                                                //&&
1747                                                                //!(droppedObj.getContainer() instanceof CompositeActor)
1748                                                                
1749                                                ) {
1750                                                        dtde.rejectDrop();
1751                                                        return;
1752                                                }
1753                                        }
1754                                }
1755                        } catch (Exception e) {
1756                                // ignore this - just unsupported data
1757                        }
1758
1759                        
1760                        // mark here to avoid marking on rejectDrop
1761                        reportLayout.setModified(_frame);
1762                        
1763                        
1764                        ///DropTargetContext c = dtde.getDropTargetContext();
1765                        
1766                        // Here it is already a Report Item Panel, and we 
1767                        // don't need to create a new panel, we just need to re-arrange the
1768                        // order.
1769                        
1770                        if (tr.isDataFlavorSupported(dragAndDropPanelDataFlavor)) {
1771
1772                                DragAndDropPanel droppedPanel = (DragAndDropPanel) tr
1773                                                .getTransferData(dragAndDropPanelDataFlavor);
1774                                getPrevPanel().getAssociatedItem().setSelected(false);
1775                                getPrevPanel().deselectPanel();
1776                                droppedPanel.selectPanel();
1777                                setCurrPanel(droppedPanel);
1778                                
1779                                Item anitem = droppedPanel.getAssociatedItem();
1780                                anitem.setSelected(true);
1781                                arrangePanels(droppedPanel, dropYLoc);   // renders the report layout
1782                                dtde.dropComplete(true);
1783                                
1784                                return;
1785                                
1786                        } else if (!tr.isDataFlavorSupported(dragAndDropPanelDataFlavor)
1787                                        && (!tr.isDataFlavorSupported(jlabelFlavor))) {
1788                                // Here it is a NEW Dynamic Item
1789
1790                                DynamicReportItem dynamicreportItem = new DynamicReportItem();
1791
1792                                String strItemFullName = (String) tr
1793                                                .getTransferData(DataFlavor.stringFlavor);
1794
1795                                if (droppedObj != null) {
1796                                        strItemFullName = droppedObj.getFullName();
1797                                }
1798
1799                                dynamicreportItem.setName(strItemFullName);
1800                                DragAndDropPanel columnPanel = renderDynamicReportItem(dynamicreportItem);
1801                                
1802                            layoutpanel.repaint();
1803                            
1804                                getPrevPanel().getAssociatedItem().setSelected(false);
1805                                getPrevPanel().deselectPanel();
1806                                columnPanel.selectPanel();
1807                                arrangePanels(columnPanel, dropYLoc);  // renders the report layout
1808                                dtde.dropComplete(true);
1809
1810                                return;
1811
1812                        } else if (!tr.isDataFlavorSupported(dragAndDropPanelDataFlavor)
1813                                        && (tr.isDataFlavorSupported(jlabelFlavor))) {
1814                                 // Here it is not a panel, and it is jlabelFlavor, so it must be
1815                                 // a static item.
1816                                
1817                                /** first we get the transferable in jlabelFlavor */
1818                                tr.getTransferData(jlabelFlavor);
1819
1820                                /** get the label that you transferred */
1821                                JLabel staticreportItemLabel = (JLabel) tr
1822                                                .getTransferData(jlabelFlavor);
1823
1824                                /**
1825                                 * Instantiate a new StaticReportItem for the type that was
1826                                 * dropped, and then add it to the report layout
1827                                 */
1828                                String staticitemname = (String) staticreportItemLabel
1829                                                .getText();
1830                                
1831
1832                                if (staticitemname.equals(StaticReportItemText.TEXT)) {
1833        
1834                                        StaticReportItem staticreportItemText = new StaticReportItemText();
1835                                        DragAndDropPanel columnPanel = renderStaticReportItem(staticreportItemText);
1836                                        arrangePanels(columnPanel, dropYLoc); // renders the report layout
1837                                
1838                                } else if (staticitemname.equals(StaticReportItemHR.HR)) {
1839                                        
1840                                        StaticReportItem staticreportItemHR = new StaticReportItemHR();
1841                                        DragAndDropPanel columnPanel = renderStaticReportItem(staticreportItemHR);
1842                                        arrangePanels(columnPanel, dropYLoc); // renders the report layout
1843
1844                                } else if (staticitemname.equals(StaticReportItemImage.IMAGE)) {
1845                                        
1846                                        StaticReportItem staticreportItemImage = new StaticReportItemImage();
1847                                        DragAndDropPanel columnPanel = renderStaticReportItem(staticreportItemImage);
1848                                        arrangePanels(columnPanel, dropYLoc); // renders the report layout
1849                                
1850                                } else if (staticitemname.equals(StaticReportItemSection.SECTION)) {
1851                                        
1852                                        StaticReportItem staticreportItemSection = new StaticReportItemSection();
1853                                        DragAndDropPanel columnPanel = renderStaticReportItem(staticreportItemSection); 
1854                                        arrangePanels(columnPanel, dropYLoc); // renders the report layout
1855                                }               
1856                                
1857                                //renderReportLayout();  not needed here, is already done in arrangePanels.
1858                                // leaving it here temporarily for future use if necessary.
1859                        
1860                                dtde.dropComplete(true);
1861                                
1862                                return;
1863                        }
1864
1865                } catch (Exception e) {
1866                        e.printStackTrace();
1867                        dtde.rejectDrop();
1868                }
1869                
1870        }
1871
1872
1873        public void dropActionChanged(DropTargetDragEvent dtde) {
1874                // don't do anything
1875        }
1876        
1877        
1878        /**
1879         * renders a Dynamic Report Item.
1880         * a Dynamic Report Item represents something that is from the
1881         * workflow and is recorded by the Provenance recorder.
1882         * 
1883         * @param tmpItem
1884         * 
1885         * @return DragAndDropPanel columnPanel
1886         */
1887        public DragAndDropPanel renderDynamicReportItem(final Item tmpItem) {
1888                
1889                // get Dynamic Report Item icon
1890                URL portIconURL = getIconURL("actor", "gif");
1891                ImageIcon portIcon = new ImageIcon(portIconURL);
1892                tmpItem.setIcon(portIcon);
1893
1894                JLabel dynamicreportItemCenterLabel = new JLabel(tmpItem
1895                                .getIcon());
1896                dynamicreportItemCenterLabel.setCursor(Cursor
1897                                .getPredefinedCursor(Cursor.HAND_CURSOR));
1898                        
1899                final String strItemFullName = tmpItem.getName(); 
1900                
1901                dynamicreportItemCenterLabel.setToolTipText(strItemFullName);                           
1902                String strItemShortName = tmpItem.getShortName();
1903
1904                
1905                // We are using a radio button here because it
1906                // provides a 'button' functionality without making us
1907                // show a square button.
1908                final ReportItemButton dynamicReportItemButton = new ReportItemButton(
1909                                strItemShortName, dynamicreportItemCenterLabel.getIcon(), strItemFullName);
1910                
1911                dynamicReportItemButton.setToolTipText(strItemFullName);
1912                
1913                ReportItemButtonListener dybuttlistener = new ReportItemButtonListener();
1914                dynamicReportItemButton.addMouseListener(dybuttlistener);
1915                
1916                // This creates the panel that represents a dynamic report item.
1917                DragAndDropPanel dragAndDropPanel = createDynamicReportItemView(
1918                                tmpItem, dynamicReportItemButton);
1919                dragAndDropPanel.setAssociatedItem(tmpItem);
1920                
1921                dynamicReportItemButton.setAssociatedPanel(dragAndDropPanel);
1922                
1923                // This is important because it associates a report item
1924                // with its properties, that are set from the 'properties panel'                
1925                dynamicReportItemButton.setAction(new AbstractAction(
1926                                strItemShortName) {
1927                        public void actionPerformed(ActionEvent e) {
1928                                ref.setSelectedItem(tmpItem);
1929                                TabManager.getInstance().tabEvent(ref.getParentFrame(),
1930                                                new ActionEvent(ref, 0, "Properties"));
1931                                dynamicReportItemButton.setToolTipText(strItemFullName);
1932                                dynamicReportItemButton.setBackground(Color.white);
1933                        }
1934                });
1935
1936                
1937                dragAndDropPanel.setPropertiesButton(dynamicReportItemButton);
1938                
1939                
1940                requestFocusInWindow();
1941
1942                // This is used so that we know what to de-select, when
1943                // the user clicks on a new panel.
1944                DragAndDropPanel prevSelectedPanel = getPrevPanel();
1945                if (prevSelectedPanel != null) {
1946                        prevSelectedPanel.deselectPanel();
1947                        Item itemtodeselect = prevSelectedPanel.getAssociatedItem();
1948                        itemtodeselect.setSelected(false);
1949                        setPrevPanel(dragAndDropPanel);
1950                        tmpItem.setSelected(true);
1951                        
1952                        dragAndDropPanel.selectPanel();
1953                        setPrevPanel(dragAndDropPanel);
1954
1955                } else {
1956
1957                        setPrevPanel(dragAndDropPanel);
1958                        tmpItem.setSelected(true);
1959                        dragAndDropPanel.selectPanel();
1960                }
1961        
1962                
1963                return dragAndDropPanel;
1964        }
1965        
1966        
1967        /**
1968         * Mouse Listener for the Report Item Buttons
1969         */
1970        public class ReportItemButtonListener implements MouseListener {
1971
1972                public void mouseClicked(MouseEvent e) {
1973
1974                        ReportItemButton staticbutton = (ReportItemButton) e.getSource();
1975                        DragAndDropPanel clickedDnDPanel = (DragAndDropPanel) staticbutton.getAssociatedPanel();
1976                        DragAndDropPanel prevPanel = getPrevPanel();
1977                        
1978                        if (!clickedDnDPanel.equals(prevPanel)) {
1979
1980                                        prevPanel.deselectPanel();
1981                                        
1982                                        clickedDnDPanel.setSelected(true);
1983                                        clickedDnDPanel.setBorder(new OvalBorder(3, 3, Color.blue, Color.blue));
1984                                        clickedDnDPanel.setOpaque(false);
1985                                        clickedDnDPanel.setBackground(new Color(6, 128, 255, 129).darker()); 
1986                                        setCurrPanel(clickedDnDPanel);
1987                                        setPrevPanel(clickedDnDPanel);
1988                                }
1989
1990                        requestFocusInWindow();
1991                        
1992                        //redrawView();                         These are not used, but leaving them in just
1993                        //renderReportLayout();     in case they become necessary.
1994                }
1995
1996                public void mouseEntered(MouseEvent e) {
1997                        // nothing to do
1998                }
1999                public void mouseExited(MouseEvent e) {
2000                        // nothing to do
2001                }
2002                public void mousePressed(MouseEvent e) {
2003                        // nothing to do
2004                }
2005                public void mouseReleased(MouseEvent e) {
2006                        // nothing to do        
2007                }
2008        }
2009        
2010
2011
2012        /* Below are all of the methods for the Tab Pane implementation */
2013
2014        /**
2015         * Implementation of TabPane getName()
2016         */
2017        public String getTabName() {
2018                return _title;
2019        }
2020
2021        /**
2022         * Implementation of TabPane setParentFrame(TableauFrame)
2023         */
2024        public void setParentFrame(TableauFrame parent) {
2025                _frame = parent;
2026        }
2027
2028        /**
2029         * Implementation of getParentFrame getName()
2030         */
2031        public TableauFrame getParentFrame() {
2032                return _frame;
2033        }
2034
2035        /**
2036         * A factory that creates the library panel for the editors.
2037         * 
2038         *@author aaron
2039         */
2040        public static class Factory extends TabPaneFactory {
2041                /**
2042                 * Create a factory with the given name and container.
2043                 * 
2044                 *@param container
2045                 *            The container.
2046                 *@param name
2047                 *            The name of the entity.
2048                 *@exception IllegalActionException
2049                 *                If the container is incompatible with this attribute.
2050                 *@exception NameDuplicationException
2051                 *                If the name coincides with an attribute already in the
2052                 *                container.
2053                 */
2054                public Factory(NamedObj container, String name)
2055                                throws IllegalActionException, NameDuplicationException {
2056                        super(container, name);
2057                }
2058
2059                /**
2060                 * Create a library pane that displays the given library of actors.
2061                 * 
2062                 * @return A new LibraryPaneTab that displays the library
2063                 */
2064                public TabPane createTabPane(TableauFrame parent) {
2065                        
2066                        ReportDesignerPanel rdp = new ReportDesignerPanel(this.getName(),
2067                                        ((PtolemyFrame) parent).getModel().getName());
2068                        return rdp;
2069                }
2070        }
2071
2072        
2073        /**
2074         * 
2075         */
2076        public void handleStateChange(StateChangeEvent event) {
2077                NamedObj model = ((PtolemyFrame)_frame).getModel();
2078                if (event instanceof ReportingStateChangeEvent) {
2079                        ReportingStateChangeEvent reportingEvent = (ReportingStateChangeEvent) event;
2080                        if (reportingEvent.getChangedState().equals(ReportingStateChangeEvent.REPORT_LAYOUT_CHANGED)) {
2081                                //System.out.println("report layout changed");
2082                                
2083                                NamedObj eventReference = reportingEvent.getReference();
2084                                KeplerLSID eventRefLSID = NamedObjId.getIdFor(eventReference);
2085                                KeplerLSID refLSID = NamedObjId.getIdFor(model);
2086                                
2087                                if (eventRefLSID.toStringWithoutRevision().equals(refLSID.toStringWithoutRevision())) {
2088                                        try {
2089                                                this.initializeTab();
2090                                        } catch (Exception e) {
2091                                                // TODO Auto-generated catch block
2092                                                e.printStackTrace();
2093                                        }
2094                                }
2095                        }
2096                }
2097                
2098                
2099                if (event.getChangedState().equals(WorkflowRun.WORKFLOWRUN_SELECTED)) {
2100
2101                        // only show msg if event is from this window
2102                        if (event.getSource() == (KeplerGraphFrame) this._frame) {
2103
2104                                if (dontShowDialogCheckBox.isSelected() || 
2105                                                reportLayout == null || reportLayout.isBlank()) {
2106                                        showRun(event, model);
2107                                } else {
2108                                        int _reply = showDiscardWarning(layoutDiscardWarning);
2109                                        if (_reply == 0) {
2110                                                showRun(event, model);
2111                                        }
2112                                }
2113                        }
2114
2115                }
2116        }
2117        
2118        
2119        /**
2120         * 
2121         * @param event
2122         * @param reference
2123         */
2124        public void showRun(StateChangeEvent event, NamedObj reference) {
2125                NamedObj namedObj = event.getReference();
2126                if (namedObj instanceof WorkflowRun) {
2127                        WorkflowRun wfRun = (WorkflowRun) namedObj;
2128                        KeplerLSID referenceLSID = NamedObjId.getIdFor(reference);
2129                        //only change if the event is from this window
2130                        if (event.getSource() == (KeplerGraphFrame) this._frame){
2131                                final Integer execId = wfRun.getExecId();
2132                                //look up the ROML as it was at this execution
2133                                try {
2134                                        ReportLayout rl = this.lookupReportLayout(execId);
2135                                        //if (rl != null) {
2136                                                WorkflowManager.getInstance().getWorkflow(_frame, referenceLSID).addReportLayout(_frame, rl);
2137                                                initializeTab();
2138                                        //}
2139                                        /*
2140                                        else{
2141                                                ////reportitemPanels.clear();
2142                                                ////redrawView();
2143                                        }
2144                                        */
2145                                } catch (Exception e) {
2146                                        // TODO Auto-generated catch block
2147                                        e.printStackTrace();
2148                                }
2149                        }
2150                }
2151        }
2152        
2153        public int showDiscardWarning(String message) {
2154                Object[] params = { message, dontShowDialogCheckBox };
2155                int reply = JOptionPane.showConfirmDialog(this._frame, params,
2156                                "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
2157                return reply;
2158        }
2159
2160                
2161        public ReportLayout lookupReportLayout(Integer execId) throws Exception {
2162                
2163                ReportLayout rl = null;
2164                
2165                // look up the the workflow LSID
2166                NamedObj reference = ((PtolemyFrame)_frame).getModel();
2167                KeplerLSID lsid = NamedObjId.getIdFor(reference);
2168                
2169                // get the latest execution if there was none given
2170                if (execId == null) {
2171                        System.out.println("ReportDesignerPanel lookupReportLayout execId == null ----- does this ever happen????????");
2172                        execId = ProvenanceUtil.getQueryable(lsid, _frame).getLastExecutionForWorkflow(lsid);
2173                }
2174                if (execId == null) {
2175                        if (_frame != null){
2176                                String warnMessage = "ReportDesignerPanel lookupReportLayout - No execution history found for this workflow. Please run the workflow.";
2177                                JOptionPane.showMessageDialog(_frame, warnMessage, "Error",
2178                        JOptionPane.ERROR_MESSAGE);
2179                }
2180                        return rl;
2181                }
2182                
2183                // look up the ROML instance XML in provenance
2184                Map<String, String> metadataMap = new HashMap<String, String>();
2185                metadataMap.put("type", ReportLayout.class.getName());
2186                List<byte[]> dataList = ProvenanceUtil.getQueryable(lsid, _frame).getAssociatedDataForExecution(execId, metadataMap, false);
2187                if (dataList != null && !dataList.isEmpty()) {
2188                        rl = ReportRenderer.convertXML2Report(new ByteArrayInputStream(dataList.get(0)));
2189                }
2190                return rl;
2191        }
2192        
2193        
2194        public void windowGainedFocus(WindowEvent e) {
2195                WorkflowManager.setRankingTableauFrame(_frame);
2196        }
2197
2198        public void windowLostFocus(WindowEvent e) {
2199        }
2200
2201}