/******************************************************************************** * * * (c) Copyright 2010 Verizon Communications USA and The Open University UK * * * * This software is freely distributed in accordance with * * the GNU Lesser General Public (LGPL) license, version 3 or later * * as published by the Free Software Foundation. * * For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html * * and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html * * * * This software is provided by the copyright holders and contributors "as is" * * and any express or implied warranties, including, but not limited to, the * * implied warranties of merchantability and fitness for a particular purpose * * are disclaimed. In no event shall the copyright owner or contributors be * * liable for any direct, indirect, incidental, special, exemplary, or * * consequential damages (including, but not limited to, procurement of * * substitute goods or services; loss of use, data, or profits; or business * * interruption) however caused and on any theory of liability, whether in * * contract, strict liability, or tort (including negligence or otherwise) * * arising in any way out of the use of this software, even if advised of the * * possibility of such damage. * * * ********************************************************************************/ package com.compendium.ui.dialogs; import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Vector; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JRadioButton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.compendium.LanguageProperties; import com.compendium.ProjectCompendium; import com.compendium.core.ICoreConstants; import com.compendium.core.datamodel.INodePosition; import com.compendium.core.datamodel.INodeSummary; import com.compendium.core.datamodel.IView; import com.compendium.core.datamodel.LinkProperties; import com.compendium.core.datamodel.NodePosition; import com.compendium.ui.UIButton; import com.compendium.ui.UIList; import com.compendium.ui.UINode; import com.compendium.ui.UIUtilities; import com.compendium.ui.UIViewPane; import com.compendium.ui.plaf.ListUI; import com.compendium.ui.plaf.ViewPaneUI; /** * UIDropSelectionDialog defines the drag and drop dialog, that allows * the user to select the drag origin, and therefore the type of drop processing to perform * * @author Michelle Bachler */ public class UIDropSelectionDialog extends UIDialog implements ActionListener { /** * class's own logger */ final Logger log = LoggerFactory.getLogger(getClass()); /** The pane to put the dialog's contents in.*/ private Container oContentPane = null; /** The parent frame for this dialog.*/ private JFrame oParent = null; /** The button to process the drop.*/ private JButton pbProcess = null; /** The button to cancel the drop and close the dialog.*/ private JButton pbCancel = null; /** The button to process the drop as Word text - NOT IMPLEMENTED YET.*/ private JRadioButton rbWord = null; /** The button to process the drop as Excel text - SPECIFIC FORMAT ONLY, SEE HELP DOCS.*/ private JRadioButton rbExcel = null; /** The button to process the drop as Excel text - SPECIFIC FORMAT ONLY, SEE HELP DOCS - with submaps.*/ private JRadioButton rbExcelSubmaps = null; /** The button to process the text as a note node.*/ private JRadioButton rbPlain = null; /** The title for this dialog.*/ private String sTitle = LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.dndSelectionTitle"); //$NON-NLS-1$ /** The String of data being dropped.*/ private String dropData = ""; //$NON-NLS-1$ /** The UIViewPane instance if the target view is a map.*/ private UIViewPane uiViewPane = null; /** The ViewPaneUI instance if the target view is a map.*/ private ViewPaneUI viewPaneUI = null; /** The UIList instance if the target view is a list.*/ private UIList uiList = null; /** The ListUI instance if the target view is a list.*/ private ListUI listUI = null; /** The x position of the drop.*/ private int nX = 0; /** The y position of the drop.*/ private int nY = 0; /** The current author used for any newly created nodes.*/ private String author = null; /** * Initializes and sets up the dialog. Used when the drop target is a map view. * * @param parent, the parent frame for this dialog. * @param pane com.compendium.ui.UIViewPane, the drop target view. * @param x, the x position for the drop. * @param y, the y position for the drop. */ public UIDropSelectionDialog(JFrame parent, UIViewPane pane, String data, int x, int y) { super(parent, true); oParent = parent; uiViewPane = pane; viewPaneUI = pane.getUI(); dropData = data; nX = x; nY = y; setTitle(sTitle); drawDialog(); } /** * Initializes and sets up the dialog. Used when the drop target is a list view. * * @param parent, the parent frame for this dialog. * @param list com.compendium.ui.UIList, the drop target view. * @param x, the x position for the drop. * @param y, the y position for the drop. */ public UIDropSelectionDialog(JFrame parent, UIList list, String data, int x, int y) { super(parent, true); oParent = parent; uiList = list; listUI = list.getListUI(); dropData = data; nX = x; nY = y; setTitle(sTitle); drawDialog(); } /** * Draws the contents of this dialog. */ public void drawDialog() { author = ProjectCompendium.APP.getModel().getUserProfile().getUserName(); oContentPane = getContentPane(); GridBagLayout gb = new GridBagLayout(); GridBagConstraints gc = new GridBagConstraints(); oContentPane .setLayout(gb); gc.insets = new Insets(5,10,5,5); gc.anchor = GridBagConstraints.WEST; gc.gridwidth=2; int y=0; rbPlain = new JRadioButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processPlainRadio")); //$NON-NLS-1$ rbPlain.setSelected(true); gc.gridy = y; y++; gb.setConstraints(rbPlain, gc); oContentPane .add(rbPlain); rbExcel = new JRadioButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processExcelRadio")); //$NON-NLS-1$ rbExcel.setSelected(false); gc.gridy = y; y++; gb.setConstraints(rbExcel, gc); oContentPane .add(rbExcel); rbExcelSubmaps = new JRadioButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processExcelSubmapsRadio")); //$NON-NLS-1$ rbExcelSubmaps.setSelected(false); gc.gridy = y; y++; gb.setConstraints(rbExcelSubmaps, gc); oContentPane .add(rbExcelSubmaps); rbWord = new JRadioButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processWordRadio")); //$NON-NLS-1$ rbWord.setSelected(false); rbWord.setEnabled(false); gc.gridy = y; y++; gb.setConstraints(rbWord, gc); oContentPane .add(rbWord); ButtonGroup group1 = new ButtonGroup(); group1.add(rbPlain); group1.add(rbExcel); group1.add(rbExcelSubmaps); group1.add(rbWord); gc.insets = new Insets(15,10,5,5); // Add export button pbProcess = new UIButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processDropButton")); //$NON-NLS-1$ pbProcess.setMnemonic(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.processDropButtonMnemonic").charAt(0)); pbProcess.addActionListener(this); pbProcess.requestFocus(); getRootPane().setDefaultButton(pbProcess); gc.gridy = y; gc.gridwidth=1; gc.anchor = GridBagConstraints.WEST; gb.setConstraints(pbProcess, gc); oContentPane .add(pbProcess); // Add close button pbCancel = new UIButton(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.cancelButton")); //$NON-NLS-1$ pbCancel.setMnemonic(LanguageProperties.getString(LanguageProperties.DIALOGS_BUNDLE, "UIDropSelectionDialog.cancelButtonMnemonic").charAt(0)); pbCancel.addActionListener(this); gc.gridy = y; gc.anchor = GridBagConstraints.EAST; gc.gridwidth=1; gb.setConstraints(pbCancel, gc); oContentPane .add(pbCancel); pack(); setResizable(false); } /** * Handle button push events. * @param evt, the associated ActionEvent. */ public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); if (source instanceof JButton) { if (source == pbProcess) { onProcessDrop(); } else if (source == pbCancel) { onCancel(); } } } /** * Handle the drop of text from an external application. */ public void onProcessDrop() { if (rbWord.isSelected()) processAsWord(); else if (rbExcel.isSelected()) processAsExcel(); else if (rbExcelSubmaps.isSelected()) processAsExcelSubmaps(); else processAsPlain(); onCancel(); } /** * Process the dropped text as plain text and just create a note node. */ public void processAsPlain() { if (viewPaneUI != null) { UINode node = addNodeToMap(viewPaneUI, dropData, ICoreConstants.NOTE, nX, nY); } else if (listUI != null) { String detail = ""; //$NON-NLS-1$ //if (dropData.length() > 100) { // detail = dropData.substring(100); // dropData = dropData.substring(0, 100); //} NodePosition node = listUI.createNode(ICoreConstants.NOTE, "", //$NON-NLS-1$ ProjectCompendium.APP.getModel().getUserProfile().getUserName(), dropData, detail, nX, nY ); uiList.updateTable(); uiList.selectNode(uiList.getNumberOfNodes() - 1, ICoreConstants.MULTISELECT); } } /** * Processes a line of dropped text as an Excel spreadsheet row. */ private Vector parseExcelRow(String line) { Vector row = new Vector(10); while(line.length() > 0) { log.info("line = "+line); int inner = line.indexOf("\t"); //$NON-NLS-1$ if (inner != -1) { String item = line.substring(0, inner); if (inner < line.length()) line = line.substring(inner+1); row.addElement(item.trim()); log.info("item = "+item.trim()); } else { log.info("item = "+line.trim()); row.addElement(line.trim()); line = ""; //$NON-NLS-1$ } line.trim(); } return row; } /** * Parses the dropped text as Excel data. */ private Vector parseExcelData() { String data = dropData; Vector table = new Vector(10); Vector row = null; int maxLength = 0; while (data.length() > 0) { int index = data.indexOf("\n"); //$NON-NLS-1$ if (index == -1) { index = data.indexOf("\r"); //$NON-NLS-1$ if (index != -1) { String line = data.substring(0, index); //log.info("row: "+line); //$NON-NLS-1$ row = parseExcelRow(line); table.addElement(row); if (index < data.length()) data = data.substring(index+1); } else { String line = data.trim(); data = ""; //$NON-NLS-1$ //log.info("row: "+line); row = parseExcelRow(line); table.addElement(row); } } else { String line = data.substring(0, index); //log.info("row: "+line); row = parseExcelRow(line); table.addElement(row); if (index < data.length()) data = data.substring(index+1); } data.trim(); } // PAD ROWS IF REQUIRED return table; } /** * Process the dropped text as Excel text and process as per specified rules. * See Compendium help files for details. */ private void processAsExcel() { Vector table = parseExcelData(); Vector topRow = (Vector)table.elementAt(0); if (viewPaneUI != null) { int firstLevelCount = table.size()-1; int secondLevelCount = topRow.size()-1; int ySpacer = 80; int xSpacer = 300; int x2 = 10 + (xSpacer*2); int y2 = 0; int x1 = 10 + xSpacer; int x0 = 10; int y1 = ((firstLevelCount * secondLevelCount * ySpacer) / 2) - ((firstLevelCount*ySpacer)/2); if (secondLevelCount == 0) { y1 = 0; } int y0 = y1 + ( ((firstLevelCount*ySpacer)/2) - (ySpacer/2)); int x3 = 10 + (xSpacer*3); try { String rootLabel = (String)topRow.elementAt(0); UINode rootMap = addNodeToMap(viewPaneUI, rootLabel, ICoreConstants.MAPVIEW, nX, nY); IView rootView = (IView)rootMap.getNode(); NodePosition rootQuestion = addNodeToView(rootView, rootLabel, ICoreConstants.ISSUE, x0, y0); INodeSummary rootNode = rootQuestion.getNode(); for (int i=1; i<= firstLevelCount; i++) { Vector row = (Vector)table.elementAt(i); String label = (String)row.elementAt(0); INodePosition nodePos1 = addNodeToView(rootView, label, ICoreConstants.ISSUE, x1, y1); INodeSummary nodeSum1 = nodePos1.getNode(); LinkProperties props = UIUtilities.getLinkProperties(ICoreConstants.DEFAULT_LINK); props.setArrowType(ICoreConstants.ARROW_TO); rootView.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeSum1, rootNode, props); //$NON-NLS-1$ for (int j=1; j<=secondLevelCount; j++) { String label2 = (String)topRow.elementAt(j); INodePosition nodePos2 = addNodeToView(rootView, label2, ICoreConstants.ISSUE, x2, y2); INodeSummary nodeSum2 = nodePos2.getNode(); rootView.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeSum2, nodeSum1, props); //$NON-NLS-1$ String label3 = (String)row.elementAt(j); INodePosition nodePos3 = addNodeToView(rootView, label3, ICoreConstants.POSITION, x3, y2); INodeSummary nodeSum3 = nodePos3.getNode(); rootView.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeSum3, nodeSum2, props); //$NON-NLS-1$ y2 += ySpacer; } y1 += ySpacer; } } catch(Exception ex) { log.error("Error...", ex); } } else if (listUI != null) { } } /** * Process the dropped text as Excel text and process as per specified rules. * With submaps for second level data * See Compendium help files for details. */ private void processAsExcelSubmaps() { Vector table = parseExcelData(); Vector topRow = (Vector)table.elementAt(0); if (viewPaneUI != null) { int firstLevelCount = table.size()-1; int secondLevelCount = topRow.size()-1; int ySpacer = 80; int xSpacer = 150; int x0 = 10; int x1 = 10 + xSpacer; int x2 = 10 + xSpacer; int x3 = 10 + (xSpacer*2); int y1 = 10; if (secondLevelCount == 0) { y1 = 0; } int y2 = 10; int y0 = y1 + ( ((firstLevelCount*ySpacer)/2) - (ySpacer/2)); int y4 = y1 + ( ((secondLevelCount*ySpacer)/2) - (ySpacer/2)); try { String rootLabel = (String)topRow.elementAt(0); int type = ICoreConstants.MAPVIEW; if (firstLevelCount > 40) { type = ICoreConstants.LISTVIEW; } UINode rootMap = addNodeToMap(viewPaneUI, rootLabel, type, nX, nY); IView rootView = (IView)rootMap.getNode(); INodeSummary rootNode = null; if (type == ICoreConstants.MAPVIEW) { NodePosition rootQuestion = addNodeToView(rootView, rootLabel, ICoreConstants.ISSUE, x0, y0); rootNode = rootQuestion.getNode(); } else { x1=0; y1=0; } for (int i=1; i<= firstLevelCount; i++) { Vector row = (Vector)table.elementAt(i); String label = (String)row.elementAt(0); INodePosition nodePosView1 = addNodeToView(rootView, label, ICoreConstants.MAPVIEW, x1, y1); INodeSummary nodeview1 = nodePosView1.getNode(); IView rootView2 = (IView)nodeview1; LinkProperties props = UIUtilities.getLinkProperties(ICoreConstants.DEFAULT_LINK); props.setArrowType(ICoreConstants.ARROW_TO); if (rootNode != null && type == ICoreConstants.MAPVIEW) { rootView.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeview1, rootNode, props); //$NON-NLS-1$ } INodePosition nodePos1 = addNodeToView(rootView2, label, ICoreConstants.ISSUE, x0, y4); INodeSummary nodeSum1 = nodePos1.getNode(); y2 = 10; for (int j=1; j<=secondLevelCount; j++) { String label2 = (String)topRow.elementAt(j); INodePosition nodePos2 = addNodeToView(rootView2, label2, ICoreConstants.ISSUE, x2, y2); INodeSummary nodeSum2 = nodePos2.getNode(); rootView2.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeSum2, nodeSum1, props); //$NON-NLS-1$ String label3 = (String)row.elementAt(j); INodePosition nodePos3 = addNodeToView(rootView2, label3, ICoreConstants.POSITION, x3, y2); INodeSummary nodeSum3 = nodePos3.getNode(); rootView2.addMemberLink(ICoreConstants.DEFAULT_LINK, "", author, nodeSum3, nodeSum2, props); //$NON-NLS-1$ y2 += ySpacer; } if (type == ICoreConstants.MAPVIEW) { y1 += ySpacer; } else { y1++; } } } catch(Exception ex) { log.error("Error...", ex); } } else if (listUI != null) { } } /** * TO BE IMPLEMENTED. */ private void processAsWord() { } /** * Create a new node with the given attributes. * * @param view com.compendium.core.datamodel.View, the view to add the node to. * @param label, the label for the new node. * @param type, the type of the new node. * @param x, the x position for the new node. * @param y, the y position for the new node. */ private NodePosition addNodeToView(IView view, String label, int type, int x, int y) throws Exception { NodePosition pos = null; pos = view.addMemberNode(type, "", "", author, label, "", x, y); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return pos; } /** * Create a new node in the given view with the given attributes. * * @param viewPane com.compendium.ui.plaf.ViewPaneUI, the view to add the node to. * @param text, the label for the new node. * @param type, the type of the new node. * @param x, the x position for the new node. * @param y, the y position for the new node. */ private UINode addNodeToMap(ViewPaneUI viewPane, String text, int type, int x, int y) { UINode node = viewPane.addNewNode(type, x, y); try { node.setText(text); node.getUI().refreshBounds(); } catch(Exception ex) { log.info("Error: (UIDropSelectionDialog.addNodeToMap)\n\n"+ex.getMessage()); //$NON-NLS-1$ } return node; } }