/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * 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. */ /* * QualificationsDisplay.java * Creation date: (Feb 20, 2004 1:37:20 PM) * By: Iulian Radu */ package org.openquark.gems.client; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.ListCellRenderer; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.border.EmptyBorder; import org.openquark.cal.compiler.CodeAnalyser; import org.openquark.cal.compiler.CodeQualificationMap; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.compiler.ModuleTypeInfo; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.compiler.SourceIdentifier; import org.openquark.cal.compiler.CodeAnalyser.AnalysedIdentifier; import org.openquark.cal.compiler.SourceIdentifier.Category; import org.openquark.cal.services.CALWorkspace; import org.openquark.gems.client.caleditor.AdvancedCALEditor; import org.openquark.gems.client.caleditor.AdvancedCALEditor.PositionlessIdentifier; public class QualificationsDisplay extends JPanel { private static final long serialVersionUID = 1203014794470429073L; /** * Interface for a listener which wishes to be informed of various panel events * * @author Iulian Radu */ public interface PanelEventListener { /** * Notify the listener that a panel's type icon was double-clicked. * * @param qualificationPanel the panel that was double-clicked. */ public void panelTypeIconDoubleClicked(QualificationPanel qualificationPanel); /** * Notify the listener that a panel's module label was double-clicked. * * @param qualificationPanel the panel that was double-clicked. * @param mousePoint the point where the mouse is */ public void panelModuleLabelDoubleClicked(QualificationPanel qualificationPanel, Point mousePoint); } /** * Comparator object to order Qualification Panels by their type, * sub-ordered by ascending alphabetical name. */ private static class PanelTypeComparator implements Comparator<QualificationPanel> { private static final Map<Category, Integer> orderMap = new HashMap<Category, Integer>(); static { orderMap.put(SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD, Integer.valueOf(1)); orderMap.put(SourceIdentifier.Category.DATA_CONSTRUCTOR, Integer.valueOf(2)); orderMap.put(SourceIdentifier.Category.TYPE_CONSTRUCTOR, Integer.valueOf(3)); orderMap.put(SourceIdentifier.Category.TYPE_CLASS, Integer.valueOf(4)); } public int compare(QualificationPanel panel1, QualificationPanel panel2) { SourceIdentifier.Category panel1Form = panel1.getIdentifier().getCategory(); SourceIdentifier.Category panel2Form = panel2.getIdentifier().getCategory(); if (panel1Form == panel2Form) { // Forms are the same; order by identifier name string return panel1.getIdentifier().getName().compareTo(panel2.getIdentifier().getName()); } else { // Forms differ; compare by their integer representation return orderMap.get(panel1Form).compareTo(orderMap.get(panel2Form)); } } } /** * The JList Component that displays the qualifications in the CodeGem panel. * * @author Iulian Radu */ class QualificationsDisplayList extends JList { private static final long serialVersionUID = 3833006693516784243L; /** Reference to a MouseHandler */ private final MouseHandler mouseHandler; /** * Handler for drag and drop events. The default JList behavior * while dragging is to change selection to the list item pointed to. * This handler is created to resist selection change. * * @author Iulian Radu */ private class DragHandler implements DropTargetListener { /** Constructor */ public DragHandler() { } /** * This is used by default drag&drop methods listed below. * It holds true if the item dragged can be imported; false if not */ private boolean canImport = false; /** * Default handler for dragEnter(); delegates control through external transfer handler. * @see java.awt.dnd.DropTargetListener#dragEnter(java.awt.dnd.DropTargetDragEvent) */ public void dragEnter(DropTargetDragEvent e) { DataFlavor[] flavors = e.getCurrentDataFlavors(); JComponent c = (JComponent)e.getDropTargetContext().getComponent(); TransferHandler importer = c.getTransferHandler(); if (importer != null && importer.canImport(c, flavors)) { canImport = true; } else { canImport = false; } int dropAction = e.getDropAction(); if (canImport) { e.acceptDrag(dropAction); } else { e.rejectDrag(); } } /** * Default handler for dragOver(); delegates control through external transfer handler. * @see java.awt.dnd.DropTargetListener#dragOver(java.awt.dnd.DropTargetDragEvent) */ public void dragOver(DropTargetDragEvent e) { int dropAction = e.getDropAction(); if (canImport) { e.acceptDrag(dropAction); } else { e.rejectDrag(); } } /** * Default handler for drop(); delegates control through external transfer handler. * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent) */ public void drop(DropTargetDropEvent e) { int dropAction = e.getDropAction(); JComponent c = (JComponent)e.getDropTargetContext().getComponent(); TransferHandler importer = c.getTransferHandler(); if (canImport && importer != null) { e.acceptDrop(dropAction); try { Transferable t = e.getTransferable(); e.dropComplete(importer.importData(c, t)); } catch (RuntimeException re) { e.dropComplete(false); } } else { e.rejectDrop(); } } /** * Default handler for dragActionChanged(); delegates control through external transfer handler. * @see java.awt.dnd.DropTargetListener#dropActionChanged(java.awt.dnd.DropTargetDragEvent) */ public void dropActionChanged(DropTargetDragEvent e) { int dropAction = e.getDropAction(); if (canImport) { e.acceptDrag(dropAction); } else { e.rejectDrag(); } } /** * Default handler for dragExit(); does nothing * @param e */ public void dragExit(DropTargetEvent e) { } } /** * Inner class to handle mouse events on the Display. * * @author Iulian Radu */ private class MouseHandler extends org.openquark.gems.client.utilities.MouseClickDragAdapter { /** The index of the panel clicked, if any. */ private int panelNumClicked; /** * Constructor for the Mouse Handler */ private MouseHandler() { } /** * Invoked when a mouse button has been pressed on a component. */ @Override public void mousePressed(MouseEvent e){ super.mousePressed(e); panelClicked = getClickedPanel(e); // clear the selection if we clicked on a blank area if (panelClicked == null) { clearSelection(); } maybeShowPopup(e); } /** * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ @Override public void mouseReleased(MouseEvent e) { super.mouseReleased(e); maybeShowPopup(e); } /** * Find out whether a mouse event's location corresponds to a panel's type icon * @param e MouseEvent the relevant event * @return boolean whether a panel's type icon was hit. */ private boolean checkTypeIconHit(MouseEvent e) { QualificationPanel varPan = getClickedPanel(e); if (varPan == null) { return false; } return varPan.checkIconHit(listToPanelPoint(e.getPoint())); } /** * Find out whether a mouse event's location corresponds to a panel's module label * @param e MouseEvent the relevant event * @return boolean whether a panel's module label was hit. */ private boolean checkModuleLabelHit(MouseEvent e) { QualificationPanel varPan = getClickedPanel(e); if (varPan == null) { return false; } return varPan.checkModuleLabelHit(listToPanelPoint(e.getPoint())); } /** * Converts the specified point on the display list to a point * relative to the selected panel. * @param p point in coordinates of the Qualifications Display * @return point in coordinates of the Qualification Panel */ private Point listToPanelPoint(Point p) { // We have to translate the point from the JList's coordinate system to the panel's int panelIndex = locationToIndex(p); Rectangle panelBounds = getCellBounds(panelIndex, panelIndex); Point convertedPoint = new Point(p.x - panelBounds.x, p.y - panelBounds.y); return convertedPoint; } /** * @see org.openquark.gems.client.utilities.MouseClickDragListener#abortDrag() */ @Override public void abortDrag() { super.abortDrag(); clearSelection(); panelClicked = null; exitDragState(null); getDropTarget().getDropTargetContext().dropComplete(false); } /** * Surrogate method for mouseClicked. Called only when our definition of click occurs. * @param e MouseEvent the relevant event * @return boolean true if the click was a double click */ @Override public boolean mouseReallyClicked(MouseEvent e){ boolean doubleClicked = super.mouseReallyClicked(e); // clear the selection if we clicked on a blank area if (panelClicked == null) { clearSelection(); // otherwise, if we double clicked a panel's type icon or label , notify the appropriate listener } else if (doubleClicked && checkTypeIconHit(e)) { notifyPanelTypeIconDoubleClicked(panelClicked); } else if (doubleClicked && checkModuleLabelHit(e)) { notifyPanelModuleLabelDoubleClicked(panelClicked, e.getPoint()); } return doubleClicked; } /** * Carry out setup appropriate to enter the drag state. * Principal effect is to change dragMode as appropriate. * @param e MouseEvent the mouse event which triggered entry into the drag state. */ @Override public void enterDragState(MouseEvent e) { super.enterDragState(e); // ignore anything that is not a left mouse button if (!SwingUtilities.isLeftMouseButton(e)) { return; } // Did they hit anything? if ((panelClicked != null) && getDragEnabled()) { // exit the normal mouse drag and, give control to drag&drop clearSelection(); panelClicked.setEnabled(false); exitDragState(e); getTransferHandler().exportAsDrag(QualificationsDisplayList.this, e, TransferHandler.MOVE); } else { abortDrag(); return; } } /** * Get the panel which was clicked. * @param e MouseEvent the related mouse event * @return QualificationPanel the Panel which was clicked */ private QualificationPanel getClickedPanel(MouseEvent e) { // check that there is a panel clicked Point clickLocation = e.getPoint(); panelNumClicked = locationToIndex(clickLocation); if (-1 < panelNumClicked && getCellBounds(panelNumClicked, panelNumClicked).contains(clickLocation)) { return (QualificationPanel)getModel().getElementAt(panelNumClicked); } else { return null; } } /** * Notify the listener that a panel's type icon was double-clicked. * @param panel the panel whose type icon was double-clicked. */ private void notifyPanelTypeIconDoubleClicked(QualificationPanel panel) { for (int i = 0; i < panelEventListeners.size(); i++) { panelEventListeners.get(i).panelTypeIconDoubleClicked(panel); } } /** * Notify the listeners that a panel's module label was double-clicked. * @param panel the panel whose module label was double-clicked. */ private void notifyPanelModuleLabelDoubleClicked(QualificationPanel panel, Point mousePoint) { for (int i = 0; i < panelEventListeners.size(); i++) { panelEventListeners.get(i).panelModuleLabelDoubleClicked(panel, mousePoint); } } /** * Show the popup, if the given mouse event is the popup trigger. * @param e the mouse event. */ private void maybeShowPopup(MouseEvent e) { if (e.isPopupTrigger() && popupProvider != null) { // Get the popup menu for the current identifier if (panelClicked == null) { return; } JPopupMenu menu = popupProvider.getPopupMenu(panelClicked.getIdentifier()); if (menu == null) { return; } menu.show(e.getComponent(), e.getX(), e.getY()); } } } /** * A trivial implementation of ListCellRenderer. * Creation date: (04/07/2001 3:57:15 PM) * @author Edward Lam */ public class QualificationsDisplayRenderer implements ListCellRenderer { /** * Return an object that can paint a QualificationPanel (ie. itself). * Creation date: (04/07/2001 3:30:13 PM) * @param list Jlist - The JList we're painting. * @param value Object - The value returned by list.getModel().getElementAt(index). * @param index int - The cell's index. * @param isSelected boolean - True if the specified cell was selected. * @param cellHasFocus boolean - True if the specified cell has the focus. * @return Component the component capable of rendering the list item */ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { // the list objects should all be QualificationPanel objects QualificationPanel pan = (QualificationPanel)value; pan.setSelected(isSelected); // gray out the panel if it's disabled pan.setGrayed(!pan.isEnabled()); return pan; } } /** * Default constructor for a QualificationsDisplay. */ public QualificationsDisplayList() { super(); setName("QualificationsDisplay"); setModel(new DefaultListModel()); setAlignmentY(Component.TOP_ALIGNMENT); setCellRenderer(new QualificationsDisplayRenderer()); setBackground(new Color(239,239,239)); setPreferredSize(new Dimension(25, 101)); setAlignmentX(Component.LEFT_ALIGNMENT); setSize(25, 191); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // add the mouse listener mouseHandler = new MouseHandler(); addMouseListener(mouseHandler); addMouseMotionListener(mouseHandler); // set this list to be a drop target and set its dnd handler setDropTarget(new DropTarget(this, new DragHandler())); } /** * Cleans up qualifications display after a dragged * item was dropped. This should be called by the * external drag&drop TransferHandler after an item * was exported from this display. */ void externalDropComplete() { if (panelClicked != null) { // Display still believes it is dragging; this means // the drop operation has happened on an external component panelClicked.setEnabled(true); panelClicked = null; } setCursor(null); clearSelection(); repaint(); } /** * @return the panel that was last clicked by the mouse. */ QualificationPanel getClickedPanel() { return panelClicked; } } /** Comparator of panels by type */ public static final PanelTypeComparator panelTypeComparator = new PanelTypeComparator(); /** List contained within this display */ private final QualificationsDisplayList qualificationsDisplayList; /** Title label for this panel */ private final JLabel titleLabel = new JLabel(); /** The Panel which was clicked. */ private QualificationPanel panelClicked; /** Reference to listeners on events regarding mouse clicks and module changes. */ private final List<PanelEventListener> panelEventListeners = new ArrayList<PanelEventListener>(); /** Provider for popup menus for this display */ private AdvancedCALEditor.IdentifierPopupMenuProvider popupProvider; /** The current workspace */ private final CALWorkspace workspace; /** Constructor for the display */ public QualificationsDisplay(CALWorkspace workspace) { this.workspace = workspace; setLayout(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(); scrollPane.setName("JScrollPane1"); scrollPane.setPreferredSize(new Dimension(175, 131)); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); qualificationsDisplayList = new QualificationsDisplayList(); scrollPane.setViewportView(qualificationsDisplayList); this.add(scrollPane,"Center"); qualificationsDisplayList.setBorder(BorderFactory.createEmptyBorder()); scrollPane.setBorder(BorderFactory.createEmptyBorder()); titleLabel.setText(GemCutter.getResourceString("CEP_Functions_Title")); titleLabel.setBorder(new EmptyBorder(0,7,0,0)); titleLabel.setOpaque(true); this.add(titleLabel,"North"); } /** * Sets the display title * @param title */ public void setTitle(String title) { titleLabel.setText(title); } /** * Get the tooltip for an element in the list. * * @param e MouseEvent the related mouse event * @return the associated tooltip */ @Override public String getToolTipText(MouseEvent e) { int index = qualificationsDisplayList.locationToIndex(e.getPoint()); if (-1 < index) { QualificationPanel varPan = (QualificationPanel)qualificationsDisplayList.getModel().getElementAt(index); return varPan.getToolTipText(); } else { return null; } } /** * Update the panels displayed by this JList * * @param faVarPanels the panels */ private void updateQualificationPanels(List<QualificationPanel> faVarPanels) { // update the JList to show the new data qualificationsDisplayList.setListData(faVarPanels.toArray()); updatePreferredSize(); // Validate everything (for now - maybe restrict later) validate(); // Repaint the Display qualificationsDisplayList.repaint(); } /** * Return a new list containing the data in this JList. * * @return this JList's list data. */ private List<QualificationPanel> getListData() { ListModel listModel = qualificationsDisplayList.getModel(); int numElements = listModel.getSize(); ArrayList<QualificationPanel> listData = new ArrayList<QualificationPanel>(numElements); for (int i = 0; i < numElements; i++) { listData.add((QualificationPanel)listModel.getElementAt(i)); } return listData; } /** * Adds a listener for panel events in this component. * * @param newPanelEventListener the new PanelEventListener. */ public void addPanelEventListener(PanelEventListener newPanelEventListener) { panelEventListeners.add(newPanelEventListener); } /** * Update the preferred size of the JList according to the sizes of the component panels * */ private void updatePreferredSize() { // we only care about the height int numVarPanels = qualificationsDisplayList.getModel().getSize(); if (numVarPanels > 0) { Rectangle rect = qualificationsDisplayList.getCellBounds(0, numVarPanels - 1); qualificationsDisplayList.setPreferredSize(new Dimension(0, rect.height)); } else { qualificationsDisplayList.setPreferredSize(new Dimension(0, 0)); } } /** * Generates qualifications panels within this display, corresponding to * qualifications which occur in code and in the auto-qualification map * * @param qualificationMap * @param identifiers * @param moduleTypeInfo */ public void generateQualificationPanels(CodeQualificationMap qualificationMap, List<CodeAnalyser.AnalysedIdentifier> identifiers, ModuleTypeInfo moduleTypeInfo) { // Generate panels List<QualificationPanel> newPanels = generateExternalQualificationsPanels(identifiers, moduleTypeInfo); newPanels.addAll(generateMappedQualificationsPanels(qualificationMap, moduleTypeInfo)); // Sort the list Collections.sort(newPanels, panelTypeComparator); updateQualificationPanels(newPanels); // Set title accordingly setTitle(getProperTitle(identifiers)); } /** * Gets the proper title for this panel, based on what identifier types it is representing * @param identifiers List */ public String getProperTitle(List<AnalysedIdentifier> identifiers) { if (identifiers == null) { return GemCutter.getResourceString("CEP_Functions_Title"); } boolean functions = false; boolean types = false; for (final AnalysedIdentifier identifier : identifiers) { if ((identifier.getQualificationType() == CodeAnalyser.AnalysedIdentifier.QualificationType.QualifiedResolvedTopLevelSymbol) || (identifier.getQualificationType() == CodeAnalyser.AnalysedIdentifier.QualificationType.UnqualifiedResolvedTopLevelSymbol)) { // Only look at identifiers shown by this display if ((identifier.getCategory() == SourceIdentifier.Category.DATA_CONSTRUCTOR) || (identifier.getCategory() == SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD)) { functions = true; } else { types = true; } } if (functions && types) { break; } } if (functions && types) { return GemCutter.getResourceString("CEP_FunctionsAndTypes_Title"); } else if (types) { return GemCutter.getResourceString("CEP_Types_Title"); } else { return GemCutter.getResourceString("CEP_Functions_Title"); } } /** * Generate panels for identifiers qualified through map * @param qualificationMap * @param moduleTypeInfo * @return panels representing identifiers qualified through the map */ private List<QualificationPanel> generateMappedQualificationsPanels(CodeQualificationMap qualificationMap, ModuleTypeInfo moduleTypeInfo) { // Create panels with mapped items List<QualificationPanel> newPanels = new ArrayList<QualificationPanel>(); newPanels.addAll(generateMappedQualificationPanelsForType( qualificationMap, SourceIdentifier.Category.TOP_LEVEL_FUNCTION_OR_CLASS_METHOD, moduleTypeInfo)); newPanels.addAll(generateMappedQualificationPanelsForType( qualificationMap, SourceIdentifier.Category.TYPE_CLASS, moduleTypeInfo)); newPanels.addAll(generateMappedQualificationPanelsForType( qualificationMap, SourceIdentifier.Category.TYPE_CONSTRUCTOR, moduleTypeInfo)); newPanels.addAll(generateMappedQualificationPanelsForType( qualificationMap, SourceIdentifier.Category.DATA_CONSTRUCTOR, moduleTypeInfo)); return newPanels; } /** * Generate qualification panels representing mapped identifiers of the specified category. * * @param qualificationMap qualification map to extract unqualified names of identifiers * @param type identifiers all belong to this category * @param moduleTypeInfo type info for the current module * @return list of qualification panels created from the identifiers */ private List<QualificationPanel> generateMappedQualificationPanelsForType( CodeQualificationMap qualificationMap, SourceIdentifier.Category type, ModuleTypeInfo moduleTypeInfo) { List<String> unqualifiedIdentifiers = new ArrayList<String>(qualificationMap.getUnqualifiedNames(type)); List<QualificationPanel> newPanels = new ArrayList<QualificationPanel>(); for (final String unqualifiedName : unqualifiedIdentifiers) { ModuleName moduleName = qualificationMap.getQualifiedName(unqualifiedName, type).getModuleName(); ModuleName minimallyQualifiedModuleName = moduleTypeInfo.getModuleNameResolver().getMinimallyQualifiedModuleName(moduleName); QualificationPanel newPanel = new QualificationPanel( new AdvancedCALEditor.PositionlessIdentifier(unqualifiedName, moduleName, moduleName, minimallyQualifiedModuleName, type, CodeAnalyser.AnalysedIdentifier.QualificationType.UnqualifiedResolvedTopLevelSymbol), getTypeToolTipText(QualifiedName.make(moduleName, unqualifiedName), type, moduleTypeInfo), CodeAnalyser.getModulesContainingIdentifier(unqualifiedName, type, moduleTypeInfo).size() > 1); newPanels.add(newPanel); } return newPanels; } /** * Generate panels for externally qualified identifiers. * * @param identifiers identifiers from code analysis, null if none was performed * @param moduleTypeInfo */ private List<QualificationPanel> generateExternalQualificationsPanels(List<AnalysedIdentifier> identifiers, ModuleTypeInfo moduleTypeInfo) { List<QualificationPanel> newPanels = new ArrayList<QualificationPanel>(); if (identifiers == null) { return newPanels; } // Iterate through the source identifiers, and add resolved code qualifications within each map // Create set of PositionlessIdentifiers of qualifications in code Set<PositionlessIdentifier> qualifiedIdentifiers = new HashSet<PositionlessIdentifier>(); for (final AnalysedIdentifier identifier : identifiers) { if (identifier.getQualificationType() == CodeAnalyser.AnalysedIdentifier.QualificationType.QualifiedResolvedTopLevelSymbol) { qualifiedIdentifiers.add(new AdvancedCALEditor.PositionlessIdentifier(identifier.getName(), identifier.getRawModuleName(), identifier.getResolvedModuleName(), identifier.getMinimallyQualifiedModuleName(), identifier.getCategory(), identifier.getQualificationType())); } } // Now add panels for (final PositionlessIdentifier identifier : qualifiedIdentifiers) { ModuleName resolvedModuleNameOrNull = identifier.getResolvedModuleName(); if (resolvedModuleNameOrNull == null) { continue; } QualificationPanel newPanel = new QualificationPanel( identifier, getTypeToolTipText(QualifiedName.make(resolvedModuleNameOrNull, identifier.getName()), identifier.getCategory(), moduleTypeInfo), false); newPanels.add(newPanel); } return newPanels; } /** * Selects the panel corresponding to the specified identifier. * Clears selection if identifier not found. * @param identifier */ public void selectPanelForIdentifier(AdvancedCALEditor.PositionlessIdentifier identifier) { List<QualificationPanel> panels = getListData(); for (int i = 0; i < panels.size(); i++) { QualificationPanel panel = panels.get(i); if (identifier.equals(panel.getIdentifier())) { qualificationsDisplayList.setSelectedIndex(i); return; } } qualificationsDisplayList.clearSelection(); } /** * Returns tooltip describing an entity with the specified * qualified name, and belonging to a panel of the given form. * * @param qualifiedName * @param form * @param currentModuleTypeInfo type information of the current module * @return tooltip text */ private String getTypeToolTipText(QualifiedName qualifiedName, SourceIdentifier.Category form, ModuleTypeInfo currentModuleTypeInfo) { return AdvancedCALEditor.getMetadataToolTipText(qualifiedName.getUnqualifiedName(), qualifiedName.getModuleName(), form, currentModuleTypeInfo, workspace, this); } /** * Clear list selection */ public void clearSelection() { qualificationsDisplayList.clearSelection(); } /** * Enable drag and drop * @param enabled */ void setDragEnabled(boolean enabled) { qualificationsDisplayList.setDragEnabled(enabled); } /** * Set the transfer handler for the display list * @param handler */ void setListTransferHandler(TransferHandler handler) { qualificationsDisplayList.setTransferHandler(handler); } /** * @return the display list component */ QualificationsDisplayList getListComponent() { return qualificationsDisplayList; } /** * Add a focus listener to the list component * @param listener */ void addListFocusListener(FocusListener listener) { qualificationsDisplayList.addFocusListener(listener); } /** * Set popup provider for display menus * @param popupProvider */ public void setPopupMenuProvider(AdvancedCALEditor.IdentifierPopupMenuProvider popupProvider) { this.popupProvider = popupProvider; } /** * @return provider for popup menus */ public AdvancedCALEditor.IdentifierPopupMenuProvider getPopupMenuProvider() { return popupProvider; } }