/* * 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. */ /* * ParametricValueEditor.java * Created: March 20, 2001 * By: Michael Cheng */ package org.openquark.gems.client.valueentry; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.util.HashSet; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPopupMenu; import org.openquark.cal.compiler.ModuleTypeInfo; import org.openquark.cal.compiler.QualifiedName; import org.openquark.cal.compiler.RecordType; import org.openquark.cal.compiler.TypeConsApp; import org.openquark.cal.compiler.TypeConstructor; import org.openquark.cal.compiler.TypeExpr; import org.openquark.cal.compiler.ScopedEntityNamingPolicy.UnqualifiedUnlessAmbiguous; import org.openquark.cal.valuenode.ParametricValueNode; import org.openquark.cal.valuenode.ValueNode; import org.openquark.gems.client.IntellicutListModelAdapter; import org.openquark.gems.client.IntellicutListRenderer; import org.openquark.gems.client.IntellicutPanel; import org.openquark.gems.client.IntellicutPanelOwner; import org.openquark.gems.client.ToolTipHelpers; import org.openquark.gems.client.IntellicutListModelAdapter.IntellicutListEntry; import org.openquark.gems.client.IntellicutManager.IntellicutInfo; import org.openquark.gems.client.IntellicutManager.IntellicutMode; import org.openquark.util.Messages; /** * The ValueEditor for choosing the data type for the uninstantiated TypeVar. * @author Michael Cheng */ class ParametricValueEditor extends ValueEditor implements IntellicutPanelOwner { private static final long serialVersionUID = -1170600242670766483L; private static Messages messages = new Messages(ParametricValueEditor.class, "ParametricValueEditor_ui"); /** * A custom value editor provider for the ParametricValueEditor. */ public static class ParametricValueEditorProvider extends ValueEditorProvider<ParametricValueEditor> { public ParametricValueEditorProvider(ValueEditorManager valueEditorManager) { super(valueEditorManager); } /** * {@inheritDoc} */ @Override public boolean canHandleValue(ValueNode valueNode, SupportInfo providerSupportInfo) { return valueNode instanceof ParametricValueNode; } /** * @see org.openquark.gems.client.valueentry.ValueEditorProvider#getEditorInstance(ValueEditorHierarchyManager, ValueNode) */ @Override public ParametricValueEditor getEditorInstance(ValueEditorHierarchyManager valueEditorHierarchyManager, ValueNode valueNode) { ParametricValueEditor editor = new ParametricValueEditor(valueEditorHierarchyManager); editor.setOwnerValueNode(valueNode); return editor; } } /** * Customized cell renderer that will use the type icon as the icon for a list entry. */ private class ParametricValueListRenderer extends IntellicutListRenderer { private static final long serialVersionUID = 345425620311502011L; public ParametricValueListRenderer(IntellicutMode mode) { super(mode); } @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); TypeExpr typeExpr = (TypeExpr) ((IntellicutListEntry) value).getData(); label.setIcon(new ImageIcon(ParametricValueEditor.class.getResource(valueEditorManager.getTypeIconName(typeExpr)))); label.setBorder(BorderFactory.createEmptyBorder(1, 2, 1, 1)); return label; } } /** * The adapter for the IntellicutListModel used by this value editor. * @author Frank Worsley */ private class IntellicutAdapter extends IntellicutListModelAdapter { @Override protected Set<TypeExpr> getDataObjects() { return getMatchingInputTypes(); } @Override protected IntellicutInfo getIntellicutInfo(IntellicutListEntry data) { return IntellicutInfo.DEFAULT_INFO; } public boolean isBestEntry(IntellicutListEntry listEntry) { return true; } @Override public String getToolTipTextForEntry(IntellicutListEntry listEntry, JComponent invoker) { Object listEntryData = listEntry.getData(); if (listEntryData instanceof RecordType) { return "<html><body><b>Prelude Record</b></body></html>"; } else if (listEntryData instanceof TypeConsApp) { TypeConsApp typeConsApp = (TypeConsApp) listEntryData; QualifiedName typeConsName = typeConsApp.getName(); TypeConstructor typeCons = valueEditorManager.getPerspective().getTypeConstructor(typeConsName); return ToolTipHelpers.getEntityToolTip(typeCons, getNamingPolicy(), valueEditorManager.getWorkspace(), invoker); } else { throw new IllegalStateException("ParametricValueEditor: Unsupported list entry type"); } } } /** The Intellicut panel used by this value editor. */ private IntellicutPanel intellicutPanel; /** * ParametricValueEditor constructor. * @param valueEditorHierarchyManager */ protected ParametricValueEditor(ValueEditorHierarchyManager valueEditorHierarchyManager) { super(valueEditorHierarchyManager); } /** * @return the JList that is used by the editor to display its values */ protected IntellicutPanel getIntellicutPanel() { return intellicutPanel; } /** * Returns the list of input data types that could possibly be available in the switch type list. * This list will be used by getMatchingInputTypes to filter out types that do not match * the value node type expression. Override this if you want to narrow down the list of * possible input types, but still want the default behaviour of filtering the types. * @return the list of possible input types */ protected Set<TypeExpr> getAvailableInputTypes() { return valueEditorManager.getAvailableInputTypes(); } /** * Filters the list returned by getAvailableInputTypes to only return the types that can actually * pattern match with the value node type expression. * @return list of input types to be displayed in the switch type list */ protected Set<TypeExpr> getMatchingInputTypes() { Set<TypeExpr> dataTypes = getAvailableInputTypes(); Set<TypeExpr> matchingTypes = new HashSet<TypeExpr>(); ModuleTypeInfo currentModuleTypeInfo = valueEditorManager.getPerspective().getWorkingModuleTypeInfo(); if (currentModuleTypeInfo != null) { TypeExpr valueNodeTypeExpr = getValueNode().getTypeExpr(); for (final TypeExpr typeExpr : dataTypes) { if (TypeExpr.canPatternMatch(typeExpr, valueNodeTypeExpr, currentModuleTypeInfo)) { matchingTypes.add(typeExpr); } } } return matchingTypes; } /** * {@inheritDoc} */ @Override protected void commitValue() { IntellicutListEntry listEntry = (IntellicutListEntry) intellicutPanel.getIntellicutList().getSelectedValue(); if (listEntry != null) { // Note: For TypeExpr which contains uninstantiated TypeVars, we must 'duplicate' them somehow. TypeExpr instanceTypeExpr = ((TypeExpr) listEntry.getData()).copyTypeExpr(); ValueNode replacement = getOwnerValueNode().transmuteValueNode(valueEditorManager.getValueNodeBuilderHelper(), valueEditorManager.getValueNodeTransformer(), instanceTypeExpr); // Get the TypeVar that we are instantiating. replaceValueNode(replacement, true); notifyValueCommitted(); } } /** * {@inheritDoc} */ @Override public Component getDefaultFocusComponent() { return intellicutPanel; } /** * {@inheritDoc} */ @Override public void setInitialValue() { setLayout(new BorderLayout()); setResizable(true); IntellicutAdapter adapter = new IntellicutAdapter(); adapter.setNamingPolicy(new UnqualifiedUnlessAmbiguous(valueEditorManager.getPerspective().getWorkingModuleTypeInfo())); intellicutPanel = new IntellicutPanel(this, adapter, null, IntellicutMode.NOTHING); intellicutPanel.loadListModel(); intellicutPanel.setBorder(null); intellicutPanel.setMoveable(false); intellicutPanel.getIntellicutList().setCellRenderer(new ParametricValueListRenderer(IntellicutMode.NOTHING)); // By default there is no item selected. intellicutPanel.getIntellicutList().clearSelection(); add(intellicutPanel, BorderLayout.CENTER); resetSize(); } /** * Resets the current size and minimum resize dimension of the editor. */ protected final void resetSize() { int size = intellicutPanel.getIntellicutListModel().getSize(); if (size > 0) { // If the list is displayed, then setup some sizes. // Set the minimum resize dimension to a height of 2 item. intellicutPanel.setPreferredVisibleRows(2); setMinResizeDimension(getPreferredSize()); setMaxResizeDimension(new Dimension(getPreferredSize().width, 2048)); setResizable(true); // Set the preferred list height to max 10 rows intellicutPanel.setPreferredVisibleRows(size >= 10 ? 10 : size + 1); } else { setResizable(false); } setSize(getPreferredSize()); } /** * @see org.openquark.gems.client.IntellicutPanelOwner#connectSelectedGem() */ public void connectSelectedGem() { handleCommitGesture(); } /** * @see org.openquark.gems.client.IntellicutPanelOwner#stopIntellicutPanel() */ public void stopIntellicutPanel() { handleCancelGesture(); } /** * @see org.openquark.gems.client.IntellicutPanelOwner#getIntellicutPopupMenu() */ public JPopupMenu getIntellicutPopupMenu() { return null; } /** * @see org.openquark.gems.client.IntellicutPanelOwner#getMessages() */ public Messages getMessages() { return messages; } }