blob: eb79bb650c589ebc8472aa1206f0edacd7df0fe5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.php.editor.actions;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import org.netbeans.api.editor.document.LineDocumentUtils;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.editor.BaseDocument;
import org.netbeans.modules.csl.api.EditList;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.php.editor.lexer.LexUtilities;
import org.netbeans.modules.php.editor.lexer.PHPTokenId;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
/**
* This file is originally from Retouche, the Java Support
* infrastructure in NetBeans. I have modified the file as little
* as possible to make merging Retouche fixes back as simple as
* possible.
*
* (This used to be ImportClassPanel in org.netbeans.modules.java.editor.imports)
*
* @author Jan Lahoda, Tor Norbye
*/
public class ImportModulePanel extends javax.swing.JPanel {
private ParserResult info;
private DefaultListModel model;
private final int position;
/** Creates new form ImportClassPanel. */
@SuppressWarnings("deprecation")
public ImportModulePanel(List</*TypeElement*/String> priviledged,
List</*TypeElement*/String> denied, Font font, ParserResult info, int position) {
this.info = info;
this.position = position;
createModel(priviledged, denied);
initComponents();
setBackground(jList1.getBackground());
if (model.size() > 0) {
jList1.setModel(model);
setFocusable(false);
setNextFocusableComponent(jList1);
jScrollPane1.setBackground(jList1.getBackground());
setBackground(jList1.getBackground());
if (font != null) {
jList1.setFont(font);
}
int modelSize = jList1.getModel().getSize();
if (modelSize > 0) {
jList1.setSelectedIndex(0);
}
jList1.setVisibleRowCount(modelSize > 8 ? 8 : modelSize);
jList1.setCellRenderer(new Renderer(jList1));
jList1.grabFocus();
} else {
remove(jScrollPane1);
JLabel nothingFoundJL = new JLabel(NbBundle.getMessage(ImportModulePanel.class, "NoModsFound"));
if (font != null) {
nothingFoundJL.setFont(font);
}
nothingFoundJL.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 4, 4, 4));
nothingFoundJL.setEnabled(false);
nothingFoundJL.setBackground(jList1.getBackground());
//nothingFoundJL.setOpaque(true);
add(nothingFoundJL);
}
setA11Y();
updatePreview(null);
}
private void setA11Y() {
this.getAccessibleContext().setAccessibleName(NbBundle.getMessage(ImportModulePanel.class, "ImportClassPanel_ACN"));
this.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(ImportModulePanel.class, "ImportClassPanel_ACSD"));
jList1.getAccessibleContext().setAccessibleName(NbBundle.getMessage(ImportModulePanel.class, "ImportClassPanel_JList1_ACN"));
jList1.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(ImportModulePanel.class, "ImportClassPanel_JList1_ACSD"));
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList();
jLabel1 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
ctrlLabel = new javax.swing.JLabel();
importPreviewLabel = new javax.swing.JLabel();
jSeparator1 = new javax.swing.JSeparator();
setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(64, 64, 64)));
setLayout(new java.awt.BorderLayout());
jScrollPane1.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 4, 4, 4));
jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jList1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent evt) {
listMouseReleased(evt);
}
});
jList1.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
updatePreview(evt);
}
public void keyReleased(java.awt.event.KeyEvent evt) {
listKeyReleased(evt);
updatePreview(evt);
}
});
jScrollPane1.setViewportView(jList1);
add(jScrollPane1, java.awt.BorderLayout.CENTER);
jLabel1.setLabelFor(jList1);
jLabel1.setText(org.openide.util.NbBundle.getMessage(ImportModulePanel.class, "ImportChoices")); // NOI18N
jLabel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(4, 4, 4, 4));
jLabel1.setOpaque(true);
add(jLabel1, java.awt.BorderLayout.PAGE_START);
jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(4, 4, 4, 4));
ctrlLabel.setText(org.openide.util.NbBundle.getMessage(ImportModulePanel.class, "LBL_PackageImport")); // NOI18N
importPreviewLabel.setText(" ");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ctrlLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
.addComponent(importPreviewLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
.addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(ctrlLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(importPreviewLabel)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
add(jPanel1, java.awt.BorderLayout.PAGE_END);
}// </editor-fold>//GEN-END:initComponents
private void listMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listMouseReleased
boolean packageImport = (evt.getModifiers() & InputEvent.ALT_MASK) > 0;
boolean useFqn = (evt.getModifiers() & InputEvent.SHIFT_MASK) > 0;
importModule(getSelected(), packageImport, useFqn);
}//GEN-LAST:event_listMouseReleased
private void listKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listKeyReleased
KeyStroke ks = KeyStroke.getKeyStrokeForEvent(evt);
if (ks.getKeyCode() == KeyEvent.VK_ENTER
|| ks.getKeyCode() == KeyEvent.VK_SPACE) {
boolean packageImport = (evt.getModifiers() & InputEvent.ALT_MASK) > 0;
boolean useFqn = (evt.getModifiers() & InputEvent.SHIFT_MASK) > 0;
importModule(getSelected(), packageImport, useFqn);
}
}//GEN-LAST:event_listKeyReleased
private void updatePreview(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_updatePreview
Object selected = jList1.getSelectedValue();
if (selected != null) {
String preview = "<html><code><b>" + ((TypeDescription) selected).qualifiedName + "</b></code></html>"; // NOI18N
importPreviewLabel.setText(preview);
}
}//GEN-LAST:event_updatePreview
// Variables declaration - do not modify//GEN-BEGIN:variables
public javax.swing.JLabel ctrlLabel;
public javax.swing.JLabel importPreviewLabel;
public javax.swing.JLabel jLabel1;
public javax.swing.JList jList1;
public javax.swing.JPanel jPanel1;
public javax.swing.JScrollPane jScrollPane1;
public javax.swing.JSeparator jSeparator1;
// End of variables declaration//GEN-END:variables
public String getSelected() {
TypeDescription typeDescription = ((TypeDescription) jList1.getSelectedValue());
return typeDescription == null ? null : typeDescription.qualifiedName;
}
private void createModel(List<String> priviledged, List<String> denied) {
List<TypeDescription> l = new ArrayList<>(priviledged.size());
for (String typeElement : priviledged) {
l.add(new TypeDescription(typeElement, false));
}
for (String typeElement : denied) {
l.add(new TypeDescription(typeElement, true));
}
Collections.sort(l);
model = new DefaultListModel();
for (TypeDescription td : l) {
model.addElement(td);
}
}
/*
*
* TODO: @param packageImport, useFqn - both unused (maybe could be misused to decide whether
* generate just one line before or at the top of the file after PHP_OPENTAG
*/
private void importModule(String importCode, boolean importInPreviousLine, boolean useFqn) {
PopupUtil.hidePopup();
int basePosition = importInPreviousLine ? position : -1;
BaseDocument document = (BaseDocument) info.getSnapshot().getSource().getDocument(false);
if (!importInPreviousLine) {
TokenSequence<PHPTokenId> ts = LexUtilities.getPHPTokenSequence(document, position);
if (ts != null) {
ts.move(position);
while (ts.movePrevious()) {
Token<PHPTokenId> token = ts.token();
if (token.id().equals(PHPTokenId.PHP_OPENTAG)) {
basePosition = ts.offset();
}
}
}
}
if (basePosition != -1) {
EditList edits = new EditList(document);
try {
int rowEnd = importInPreviousLine ? LineDocumentUtils.getLineStart(document, position) : LineDocumentUtils.getLineEnd(document, basePosition);
if (importInPreviousLine) {
importCode += "\n"; //NOI18N
} else {
importCode = "\n" + importCode; //NOI18N
}
edits.replace(rowEnd, 0, importCode, true, 0);
edits.setFormatAll(true);
edits.apply();
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
}
}
private static class Renderer extends DefaultListCellRenderer {
private static final int DARKER_COLOR_COMPONENT = 5;
private Color denidedColor = new Color(0x80, 0x80, 0x80);
private Color fgColor;
private Color bgColor;
private Color bgColorDarker;
private Color bgSelectionColor;
private Color fgSelectionColor;
public Renderer(JList list) {
setFont(list.getFont());
fgColor = list.getForeground();
bgColor = list.getBackground();
bgColorDarker = new Color(
Math.abs(bgColor.getRed() - DARKER_COLOR_COMPONENT),
Math.abs(bgColor.getGreen() - DARKER_COLOR_COMPONENT),
Math.abs(bgColor.getBlue() - DARKER_COLOR_COMPONENT));
bgSelectionColor = list.getSelectionBackground();
fgSelectionColor = list.getSelectionForeground();
}
@Override
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean hasFocus) {
if (isSelected) {
setForeground(fgSelectionColor);
setBackground(bgSelectionColor);
} else {
setForeground(fgColor);
setBackground(index % 2 == 0 ? bgColor : bgColorDarker);
}
if (value instanceof TypeDescription) {
TypeDescription td = (TypeDescription) value;
// setIcon(td.getIcon());
setText(td.qualifiedName);
if (td.isDenied) {
setForeground(denidedColor);
}
// TODO - depend on gsf directly and get icons from there!
//setIcon( ElementIcons.getElementIcon( td.kind, null ) );
setIcon(new ImageIcon(ImageUtilities.loadImage("org/netbeans/modules/php/editor/resources/interface.png"))); // NOI18N
} else {
setText(value.toString());
}
return this;
}
}
private static class TypeDescription implements Comparable<TypeDescription> {
private boolean isDenied;
private final String qualifiedName;
public TypeDescription(String typeElement, boolean isDenied) {
this.isDenied = isDenied;
this.qualifiedName = typeElement;
}
@Override
public int hashCode() {
int hash = 7;
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TypeDescription other = (TypeDescription) obj;
if (this.isDenied != other.isDenied) {
return false;
}
if ((this.qualifiedName == null) ? (other.qualifiedName != null) : !this.qualifiedName.equals(other.qualifiedName)) {
return false;
}
return true;
}
@Override
public int compareTo(TypeDescription o) {
if (isDenied && !o.isDenied) {
return 1;
} else if (!isDenied && o.isDenied) {
return -1;
} else {
return qualifiedName.compareTo(o.qualifiedName);
}
}
}
}