package com.redhat.ceylon.eclipse.code.refactor;
import static com.redhat.ceylon.eclipse.code.complete.CodeCompletions.getQualifiedDescriptionFor;
import static com.redhat.ceylon.eclipse.code.outline.CeylonLabelProvider.getImageForDeclaration;
import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.getOutlineFont;
import static com.redhat.ceylon.model.typechecker.model.ModelUtil.getContainingDeclaration;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.ui.CeylonPlugin;
import com.redhat.ceylon.eclipse.ui.CeylonResources;
import com.redhat.ceylon.eclipse.util.Highlights;
import com.redhat.ceylon.model.typechecker.model.Declaration;
abstract class SelectContainerPopup extends PopupDialog {
private CeylonEditor editor;
private TableViewer table;
private List<Tree.Declaration> containingDeclarations;
private Tree.Declaration result;
abstract void finish();
abstract boolean isEnabled();
SelectContainerPopup(Shell parent, int shellStyle,
CeylonEditor editor, String title) {
super(parent, shellStyle, true, true, false, false,
false, null, null);
this.editor = editor;
setTitleText(title);
containingDeclarations = containingDeclarations();
}
private Point getLocation() {
StyledText text =
editor.getCeylonSourceViewer()
.getTextWidget();
Point selection = text.getSelection();
Point p = text.getLocationAtOffset(selection.x);
p.x -= getShell().getBorderWidth();
if (p.x < 0) p.x= 0;
if (p.y < 0) p.y= 0;
p = new Point(p.x, p.y +
text.getLineHeight(selection.x));
p = text.toDisplay(p);
return p;
}
@Override
public int open() {
if (isEnabled() && containingDeclarations.size()>1) {
int result = super.open();
getShell().setLocation(getLocation());
setFocus();
return result;
}
else {
finish();
return OK;
}
}
private List<Tree.Declaration> containingDeclarations() {
final List<Tree.Declaration> declarations =
new ArrayList<Tree.Declaration>();
Tree.CompilationUnit rootNode =
editor.getParseController()
.getLastCompilationUnit();
if (rootNode!=null) {
new Visitor() {
IRegion selection = editor.getSelection();
@Override
public void visit(Tree.Declaration that) {
if (that.getStartIndex()
<= selection.getOffset() &&
that.getEndIndex()
>= selection.getOffset()+
selection.getLength()) {
super.visit(that);
if (!(that instanceof Tree.AttributeDeclaration)) { //not 100% sure about this
declarations.add(that);
}
}
}
}.visit(rootNode);
}
return declarations;
}
@Override
protected Control createDialogArea(Composite parent) {
GridLayout layout = new GridLayout();
layout.marginTop = 0;
layout.marginLeft = 2;
layout.marginRight = 2;
layout.marginBottom = 2;
parent.setLayout(layout);
table = new TableViewer(parent,
SWT.NO_TRIM|SWT.SINGLE|SWT.FULL_SELECTION);
final Table tab = table.getTable();
tab.setFont(CeylonPlugin.getCompletionFont());
Display display = getShell().getDisplay();
tab.setCursor(new Cursor(display, SWT.CURSOR_HAND));
tab.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
table.setLabelProvider(new StyledCellLabelProvider() {
@Override
public void update(ViewerCell cell) {
Tree.Declaration dec =
(Tree.Declaration)
cell.getElement();
Declaration d =
getContainingDeclaration(
dec.getDeclarationModel());
if (d==null) {
StyledString result = new StyledString();
String pname =
dec.getUnit().getPackage()
.getQualifiedNameString();
Highlights.styleFragment(result,
"package " + pname,
true, "", getOutlineFont());
cell.setText(result.toString());
cell.setStyleRanges(result.getStyleRanges());
cell.setImage(CeylonResources.PACKAGE);
}
else {
StyledString result = getQualifiedDescriptionFor(d);
cell.setText(result.toString());
cell.setStyleRanges(result.getStyleRanges());
cell.setImage(getImageForDeclaration(d));
}
super.update(cell);
}
});
table.setContentProvider(ArrayContentProvider.getInstance());
table.setInput(containingDeclarations);
tab.setSelection(0);
tab.addKeyListener(new KeyListener() {
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
if (e.keyCode == 0x0D ||
e.keyCode == SWT.KEYPAD_CR) { // Enter key
select();
}
if (e.character == 0x1B) { // ESC
close();
}
}
});
tab.addListener(SWT.MouseMove,
new Listener() {
@Override
public void handleEvent(Event event) {
Rectangle bounds = event.getBounds();
Point point = new Point(bounds.x, bounds.y);
TableItem item = tab.getItem(point);
if (item!=null) {
StructuredSelection selection =
new StructuredSelection(
item.getData());
table.setSelection(selection);
}
}
});
tab.addMouseListener(new MouseListener() {
@Override
public void mouseUp(MouseEvent e) {
select();
}
@Override
public void mouseDown(MouseEvent e) {}
@Override
public void mouseDoubleClick(MouseEvent e) {
select();
}
});
return parent;
}
public void setFocus() {
getShell().forceFocus();
table.getControl().setFocus();
}
private void select() {
IStructuredSelection selection =
(IStructuredSelection)
table.getSelection();
setResult((Tree.Declaration)
selection.getFirstElement());
close();
finish();
}
Tree.Declaration getResult() {
return result;
}
void setResult(Tree.Declaration result) {
this.result = result;
}
}