/*==========================================================================*\
| $Id: KeyPathBrowser.java,v 1.1 2010/05/11 15:52:47 aallowat Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2006-2008 Virginia Tech
|
| This file is part of Web-CAT.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU Affero General Public License as published
| by the Free Software Foundation; either version 3 of the License, or
| (at your option) any later version.
|
| Web-CAT is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU Affero General Public License
| along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package org.webcat.oda.designer.widgets;
import java.util.ArrayList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.webcat.oda.designer.util.ImageUtils;
//------------------------------------------------------------------------
/**
* A widget modeled after the Mac OS X browser widget that permits drilling down
* a hierarchy using a horizontal sliding panel.
*
* @author Tony Allevato (Virginia Tech Computer Science)
* @version $Id: KeyPathBrowser.java,v 1.1 2010/05/11 15:52:47 aallowat Exp $
*/
public class KeyPathBrowser extends Composite
{
//~ Constructor ...........................................................
// ----------------------------------------------------------
/**
*
* @param parent
* @param style
*/
public KeyPathBrowser(Composite parent, int style)
{
super(parent, style);
selectionListeners = new ArrayList<SelectionListener>();
segments = new ArrayList<SegmentInfo>();
arrowImage = ImageUtils.getImage("icons/keypath/arrow.gif"); //$NON-NLS-1$
createControls(parent);
}
//~ Methods ...............................................................
// ----------------------------------------------------------
@Override
public void dispose()
{
arrowImage.dispose();
super.dispose();
}
// ----------------------------------------------------------
/**
*
* @param parent
*/
private void createControls(Composite parent)
{
GridData gd;
GridLayout thisLayout = new GridLayout(LIST_COUNT, true);
thisLayout.horizontalSpacing = thisLayout.verticalSpacing = 0;
thisLayout.marginWidth = thisLayout.marginHeight = 0;
this.setLayout(thisLayout);
browserLists = new Table[LIST_COUNT];
for (int i = 0; i < LIST_COUNT; i++)
{
Table list = new Table(this, SWT.V_SCROLL | SWT.FULL_SELECTION);
new TableColumn(list, SWT.LEFT);
list.setData(LIST_INDEX_KEY, Integer.valueOf(i));
list.addControlListener(new ControlAdapter()
{
public void controlResized(ControlEvent e)
{
Table table = (Table) e.widget;
TableColumn column = table.getColumn(0);
column.setWidth(table.getClientArea().width);
}
});
list.addListener(SWT.PaintItem, new Listener()
{
public void handleEvent(Event event)
{
Table table = (Table) event.widget;
TableItem item = (TableItem) event.item;
String className = (String) item.getData("className"); //$NON-NLS-1$
String key = (String) item.getData("key"); //$NON-NLS-1$
if (className != null && key != null)
{
String destType = keyProvider
.getKeyType(className, key);
if (keyProvider.hasKeys(destType))
{
int width = table.getClientArea().width;
int x = width - arrowImage.getBounds().width - 4;
int itemHeight = table.getItemHeight();
int imageHeight = arrowImage.getBounds().height;
int y = event.y + (itemHeight - imageHeight) / 2;
event.gc.drawImage(arrowImage, x, y);
}
}
}
});
list.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
if (!currentlyInSelection)
{
currentlyInSelection = true;
int widgetIndex = ((Integer) e.widget
.getData(LIST_INDEX_KEY)).intValue();
handleSelectionChanged(widgetIndex);
notifySelectionListeners(e, false);
currentlyInSelection = false;
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e)
{
notifySelectionListeners(e, true);
}
});
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
list.setLayoutData(gd);
browserLists[i] = list;
}
browserSlider = new Slider(this, SWT.HORIZONTAL);
browserSlider.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
updateLists(0);
}
});
gd = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
gd.horizontalSpan = LIST_COUNT;
browserSlider.setLayoutData(gd);
}
// ----------------------------------------------------------
public void addSelectionListener(SelectionListener listener)
{
selectionListeners.add(listener);
}
// ----------------------------------------------------------
public void removeSelectionListener(SelectionListener listener)
{
selectionListeners.remove(listener);
}
// ----------------------------------------------------------
public void notifySelectionListeners(SelectionEvent e,
boolean defaultSelection)
{
e.widget = this;
for (SelectionListener listener : selectionListeners)
{
if (defaultSelection)
listener.widgetDefaultSelected(e);
else
listener.widgetSelected(e);
}
}
// ----------------------------------------------------------
/**
*
* @param listIndex
*/
private void handleSelectionChanged(int widgetIndex)
{
int selection = browserLists[widgetIndex].getSelectionIndex();
int offset = browserSlider.getSelection();
int segmentIndex = widgetIndex + offset;
SegmentInfo segment = segments.get(segmentIndex);
String[] theseKeys = keyProvider.getKeys(segment.getClassName());
segment.setKey(theseKeys[selection]);
String nextType = keyProvider.getKeyType(segment.getClassName(),
theseKeys[selection]);
// Remove any segments after the one that was changed.
for (int i = segments.size() - 1; i > segmentIndex; i--)
segments.remove(i);
// Add a new segment to the end of the list.
segments.add(new SegmentInfo(nextType, null));
// Scroll the lists over and put the new keys in the last list.
int lastList = lastListIndex();
int oldSelection = browserSlider.getSelection();
int newSelection = Math.max(0, lastList + 1 - LIST_COUNT);
updateScroller(newSelection, 0, lastList + 1);
// If the selection doesn't cause any scrolling to occur, only
// update the lists to the right of the one where the selection
// occurred.
if (oldSelection == newSelection)
updateLists(widgetIndex + 1);
else
updateLists(0);
// For user-interface consistency, make sure that the focus gets
// transfered to the list where the selection was just made, if it
// was scrolled.
int newWidgetIndex = (widgetIndex + oldSelection) - newSelection;
if (newWidgetIndex >= 0 && newWidgetIndex < LIST_COUNT)
{
browserLists[newWidgetIndex].setFocus();
}
}
// ----------------------------------------------------------
private void updateScroller(int selection, int min, int max)
{
browserSlider.setValues(selection, min, max, LIST_COUNT, 1, LIST_COUNT);
browserSlider.setEnabled(max > LIST_COUNT);
}
// ----------------------------------------------------------
/**
*
*/
private void updateLists(int firstWidgetToUpdate)
{
int firstIndex = browserSlider.getSelection();
for (int i = firstWidgetToUpdate; i < LIST_COUNT; i++)
{
browserLists[i].removeAll();
if (firstIndex + i <= lastListIndex())
{
SegmentInfo segment = segments.get(firstIndex + i);
if (keyProvider.hasKeys(segment.getClassName()))
{
String[] keys = keyProvider.getKeys(segment.getClassName());
addKeysToList(i, segment.getClassName(), keys);
for (int j = 0; j < keys.length; j++)
{
if (keys[j].equals(segment.getKey()))
{
browserLists[i].select(j);
browserLists[i].showSelection();
break;
}
}
}
}
}
}
// ----------------------------------------------------------
private int lastListIndex()
{
int lastIndex = segments.size() - 1;
SegmentInfo lastSegment = segments.get(lastIndex);
if (keyProvider.hasKeys(lastSegment.getClassName()))
return lastIndex;
else
return lastIndex - 1;
}
// ----------------------------------------------------------
/**
* Initializes the contents of the lists based on the current root class.
*/
private void initializeLists()
{
if (keyProvider != null && keyLabelProvider != null
&& rootClassName != null)
{
updateScroller(0, 0, 0);
for (int i = 0; i < LIST_COUNT; i++)
browserLists[i].removeAll();
String[] rootKeys = keyProvider.getKeys(rootClassName);
addKeysToList(0, rootClassName, rootKeys);
}
}
// ----------------------------------------------------------
private void addKeysToList(int listIndex, String className, String[] keys)
{
if (keys != null)
{
browserLists[listIndex].setRedraw(false);
for (int i = 0; i < keys.length; i++)
{
String key = keys[i];
TableItem item = new TableItem(browserLists[listIndex],
SWT.NONE);
item.setData("className", className); // $NON_NLS_1$ //$NON-NLS-1$
item.setData("key", key); // $NON_NLS_1$ //$NON-NLS-1$
Color fgColor = keyLabelProvider.getForegroundColor(className,
key);
if (fgColor != null)
item.setForeground(fgColor);
item.setText(keyLabelProvider.getLabel(className, key));
item.setImage(keyLabelProvider.getImage(className, key));
}
browserLists[listIndex].setRedraw(true);
}
}
// ----------------------------------------------------------
public void setKeyProvider(IKeyProvider provider)
{
keyProvider = provider;
initializeLists();
}
// ----------------------------------------------------------
public IKeyProvider getKeyProvider()
{
return keyProvider;
}
// ----------------------------------------------------------
public void setKeyLabelProvider(IKeyLabelProvider provider)
{
keyLabelProvider = provider;
initializeLists();
}
// ----------------------------------------------------------
public IKeyLabelProvider getKeyLabelProvider()
{
return keyLabelProvider;
}
// ----------------------------------------------------------
public void setRootClassName(String className)
{
rootClassName = className;
segments.clear();
segments.add(new SegmentInfo(rootClassName, null));
initializeLists();
}
// ----------------------------------------------------------
public String getRootClassName()
{
return rootClassName;
}
// ----------------------------------------------------------
public void setSelectedKeyPath(String keyPath)
{
// TODO implement
}
// ----------------------------------------------------------
public String getSelectedKeyPath()
{
if (segments.isEmpty() || segments.get(0).getKey() == null)
return ""; //$NON-NLS-1$
StringBuilder buffer = new StringBuilder();
buffer.append(segments.get(0).getKey());
for (int i = 1; i < segments.size(); i++)
{
SegmentInfo segment = segments.get(i);
if (segment.getKey() != null)
{
buffer.append("."); //$NON-NLS-1$
buffer.append(segment.getKey());
}
}
return buffer.toString();
}
//~ Nested classes ........................................................
// ----------------------------------------------------------
private class SegmentInfo
{
//~ Constructor .......................................................
// ----------------------------------------------------------
public SegmentInfo(String className, String key)
{
this.className = className;
this.key = key;
}
//~ Methods ...........................................................
// ----------------------------------------------------------
public String getClassName()
{
return className;
}
// ----------------------------------------------------------
public void setClassName(String value)
{
className = value;
}
// ----------------------------------------------------------
public String getKey()
{
return key;
}
// ----------------------------------------------------------
public void setKey(String value)
{
key = value;
}
//~ Static/instance variables .........................................
private String className;
private String key;
}
//~ Static/instance variables .............................................
private static final int LIST_COUNT = 3;
private static final String LIST_INDEX_KEY = "listIndex"; // $NON_NLS_1$ //$NON-NLS-1$
private String rootClassName;
private IKeyProvider keyProvider;
private IKeyLabelProvider keyLabelProvider;
private java.util.List<SelectionListener> selectionListeners;
private boolean currentlyInSelection = false;
private Table[] browserLists;
private Slider browserSlider;
private java.util.List<SegmentInfo> segments;
private Image arrowImage;
}