/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.yoursway.completion.gui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import com.yoursway.completion.gui.CompletionProvider.DisplayState;
public class ProposalsView{
private static final String[] NO_PROPOSALS = new String[]{"Sorry, no proposals"};
private static final String[] IN_PROGRESS = new String[]{"In progress..."};
Shell shell;
List list;
int minimumWidth;
Thread thread;
private final CompletionStrategy strategy;
private String[] completionItems;
private final Control control;
private KeyAdapter simpleKeyListener;
public ProposalsView(Control control, CompletionStrategy strategy) {
this(control, 0, strategy);
}
public ProposalsView(final Control control, int style, CompletionStrategy strategy) {
this.control = control;
this.strategy = strategy;
shell = new Shell(control.getShell(), checkStyle(style) | SWT.ON_TOP | SWT.NO_FOCUS);
list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);
// resize shell when list resizes
shell.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
Rectangle shellSize = shell.getClientArea();
list.setSize(shellSize.width, shellSize.height);
}
});
// return list selection on Mouse Up or Carriage Return
list.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
ProposalsView.this.strategy.tabReleased();
}
});
list.addFocusListener(new FocusAdapter(){
@Override
public void focusGained(FocusEvent e) {
control.setFocus();
ProposalsView.this.strategy.tabReleased();
}
});
simpleKeyListener = new KeyAdapter(){
@Override
public void keyPressed(KeyEvent event) {
parentKeyPressed(event);
}
};
}
public void hookArrowKeys() {
if(!control.isDisposed()){
//XXX: Since addKeyListener doesn't check for duplicates
control.removeKeyListener(simpleKeyListener);
control.addKeyListener(simpleKeyListener);
}
}
public void unhookArrowKeys() {
if(!control.isDisposed()){
control.removeKeyListener(simpleKeyListener);
}
}
void dispose(){
unhookArrowKeys();
}
public String[] getItems() {
return completionItems;
}
public int getItemCount() {
return completionItems.length;
}
public int getSelectionIndex() {
if(completionItems.length == 0) return -1;
return list.getSelectionIndex();
}
private static int checkStyle(int style) {
int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
public int getMinimumWidth() {
return minimumWidth;
}
public void setItems(String[] strings) {
if(list.isDisposed()) return;
list.setItems(strings);
completionItems = strings;
if(strings == IN_PROGRESS){
completionItems = new String[]{};
list.deselectAll();
}else if(strings.length == 0){
list.setItems(NO_PROPOSALS);
list.deselectAll();
}else{
list.setSelection(0);
}
}
public void setMinimumWidth(int width) {
if (width < 0)
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
minimumWidth = width;
}
public boolean isVisible() {
return shell.isVisible();
}
public void show(DisplayState state) {
if(state == DisplayState.NOTHING){
setVisible(false);
}else if(state == DisplayState.IN_PROGRESS){
list.setItems(IN_PROGRESS);
list.setEnabled(false);
setVisible(true);
}else if(state == DisplayState.SUGGESTION){
setVisible(true);
list.setEnabled(false);
}else if(state == DisplayState.LIST){
setVisible(true);
list.setEnabled(completionItems.length > 0);
list.setSelection(completionItems.length>0 ? 0 : -1);
}
}
private void setVisible(boolean visible) {
if(shell.isVisible() != visible){
shell.setVisible(visible);
}
}
public void setSize(Point size) {
shell.setSize(size.x, size.y);
list.setBounds(0, 0, size.x, size.y);
}
public void setLocation(Point location) {
shell.setLocation(location.x-5, location.y);
}
private void traverseToNextItem() {
if(getSelectionIndex() < getItemCount()-1)
list.setSelection(getSelectionIndex()+1);
}
private void traverseToPrevItem() {
if(getSelectionIndex() > 0)
list.setSelection(getSelectionIndex()-1);
}
private void parentKeyPressed(KeyEvent e) {
if(e.keyCode == SWT.ARROW_DOWN){
traverseToNextItem();
e.doit = false;
} else if(e.character == SWT.CR){
ProposalsView.this.strategy.tabReleased();
e.doit = false;
}else if(e.keyCode == SWT.ARROW_UP){
traverseToPrevItem();
e.doit = false;
}
}
public boolean isDisposed() {
return list.isDisposed() || shell.isDisposed();
}
}