📄 listview.java
字号:
/**
* Copyright (C) 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 63.529,40 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.azureus.ui.swt.views.list;
import java.util.*;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.views.TableView.GroupTableRowRunner;
import org.gudy.azureus2.ui.swt.views.table.*;
import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnManager;
import org.gudy.azureus2.ui.swt.views.table.utils.TableStructureEventDispatcher;
import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
import com.aelitis.azureus.ui.swt.utils.*;
import com.aelitis.azureus.ui.swt.utils.ImageLoader;
import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent;
import org.gudy.azureus2.plugins.ui.tables.TableColumn;
/**
* @author TuxPaper
* @created Jun 12, 2006
*
*/
public abstract class ListView implements UIUpdatable, Listener,
ITableStructureModificationListener
{
private static final boolean DEBUGADDREMOVE = false;
// Shorter name for ConfigManager, easier to read code
private static final ConfigurationManager configMan = ConfigurationManager.getInstance();
private static final String CFG_SORTDIRECTION = "config.style.table.defaultSortOrder";
private static final boolean DEBUG_SORTER = false;
private Composite listComposite;
private ScrolledComposite sc;
private final SWTSkinProperties skinProperties;
private TableColumnCore[] visibleColumns;
/** ArrayList of ListRow */
private ArrayList selectedRows = new ArrayList();
private AEMonitor selectedRows_mon = new AEMonitor("ListView:SR");
private ArrayList rows = new ArrayList();
private Map mapDataSourceToRow = new HashMap();
/** Monitor for both rows and mapDataSourceToRow since these two are linked */
private AEMonitor row_mon = new AEMonitor("ListView:OTSI");
private ListRow rowFocused = null;
private final String sTableID;
/** Queue added datasources and add them on refresh */
private List dataSourcesToAdd = new ArrayList(4);
/** Queue removed datasources and add them on refresh */
private List dataSourcesToRemove = new ArrayList(4);
private long lCancelSelectionTriggeredOn = -1;
private List listenersSelection = new ArrayList();
private List listenersCountChange = new ArrayList();
private boolean bMouseClickIsDefaultSelection = false;
private int iGraphicRefresh;
protected int graphicsUpdate;
/** Sorting functions */
private TableColumnCore sortColumn;
/** TimeStamp of when last sorted all the rows was */
private long lLastSortedOn;
private Composite headerArea;
private TableColumnCore[] allColumns;
public ListView(String sTableID, SWTSkinProperties skinProperties,
Composite parent) {
this.skinProperties = skinProperties;
this.sTableID = sTableID;
FormData formData;
COConfigurationManager.addAndFireParameterListener("Graphics Update",
new ParameterListener() {
public void parameterChanged(String parameterName) {
graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update");
}
});
parent.setBackgroundMode(SWT.INHERIT_FORCE);
sc = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
formData = new FormData();
formData.left = new FormAttachment(0);
formData.top = new FormAttachment(0);
formData.right = new FormAttachment(100);
formData.bottom = new FormAttachment(100);
sc.setLayoutData(formData);
//listComposite = new Composite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
listComposite = new Composite(sc, SWT.NONE);
listComposite.setLayout(new FormLayout());
formData = new FormData();
formData.left = new FormAttachment(0);
formData.top = new FormAttachment(0);
formData.right = new FormAttachment(100);
formData.bottom = new FormAttachment(100);
listComposite.setLayoutData(formData);
sc.setContent(listComposite);
sc.setExpandHorizontal(true);
sc.setExpandVertical(true);
sc.getVerticalBar().setIncrement(30);
listComposite.addListener(SWT.MouseDoubleClick, this);
listComposite.addListener(SWT.FocusIn, this);
listComposite.addListener(SWT.FocusOut, this);
listComposite.addListener(SWT.Traverse, this);
listComposite.addListener(SWT.DefaultSelection, this);
listComposite.addListener(SWT.KeyDown, this); // so we are a tab focus
UIUpdaterFactory.getInstance().addUpdater(this);
TableStructureEventDispatcher.getInstance(sTableID).addListener(this);
}
/**
* @param headerArea
*/
protected void setupHeader(final Composite headerArea) {
this.headerArea = headerArea;
FormData formData;
Label lblCenterer = new Label(headerArea, SWT.WRAP);
formData = new FormData(0, 0);
formData.top = new FormAttachment(0, 0);
formData.bottom = new FormAttachment(100, 0);
lblCenterer.setLayoutData(formData);
ImageLoader imgLoader = ImageLoaderFactory.getInstance();
final Image imgSortAsc = imgLoader.getImage("image.sort.asc");
final Image imgSortDesc = imgLoader.getImage("image.sort.desc");
int sortWidth = Math.max(imgSortAsc.getBounds().width,
imgSortDesc.getBounds().width) + 2;
// set min column width to width of header
GC gc = new GC(headerArea);
try {
TableColumnCore[] columns = getVisibleColumns();
for (int i = 0; i < columns.length; i++) {
TableColumnCore column = columns[i];
String title = MessageText.getString(column.getTitleLanguageKey(), "");
int oldWidth = column.getWidth();
int minWidth = gc.textExtent(title).x + sortWidth;
if (minWidth > oldWidth) {
column.setWidth(minWidth);
}
}
} finally {
if (gc != null) {
gc.dispose();
}
}
headerArea.addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
TableColumnCore[] columns = getVisibleColumns();
int inColumn = -1;
for (int i = 0; i < columns.length; i++) {
Rectangle bounds = (Rectangle) headerArea.getData("Column" + i
+ "Bounds");
if (bounds != null && bounds.contains(e.x, e.y)) {
inColumn = i;
break;
}
}
if (inColumn != -1) {
setSortColumn(columns[inColumn]);
System.out.println("sorting on " + columns[inColumn].getName());
}
}
});
headerArea.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
TableColumnCore[] columns = getVisibleColumns();
e.gc.setForeground(skinProperties.getColor("color.list.header.fg"));
Rectangle clientArea = headerArea.getClientArea();
int pos = clientArea.x + ListRow.MARGIN_WIDTH;
for (int i = 0; i < columns.length; i++) {
int width = columns[i].getWidth();
String key = columns[i].getTitleLanguageKey();
String text = MessageText.getString(key, "");
int align = columns[i].getSWTAlign();
int drawWidth = width;
if (columns[i].equals(sortColumn)) {
Image img = sortColumn.isSortAscending() ? imgSortAsc : imgSortDesc;
Rectangle bounds = img.getBounds();
if (align == SWT.RIGHT) {
e.gc.drawImage(img, pos + width - bounds.width, clientArea.height
- bounds.height);
drawWidth -= bounds.width + 2;
} else {
e.gc.drawImage(img, pos, clientArea.height - bounds.height);
if (align == SWT.CENTER) {
int adj = bounds.width / 2 + 1;
pos += adj;
width -= adj;
} else {
pos += bounds.width + 2;
width -= bounds.width + 2;
}
drawWidth = width;
}
}
if (text.length() > 0) {
//Point size = e.gc.textExtent(text);
Rectangle bounds = new Rectangle(pos, clientArea.y, drawWidth,
clientArea.height);
headerArea.setData("Column" + i + "Bounds", bounds);
GCStringPrinter.printString(e.gc, text, bounds, false, false, align);
}
//e.gc.drawLine(pos, bounds.y, pos, bounds.y + bounds.height);
pos += width + (ListRow.MARGIN_WIDTH * 2);
}
}
});
}
/**
* @param i
*/
protected void moveFocus(int relative, boolean moveall) {
int index;
if (moveall) {
System.err.println("moveall not supported "
+ Debug.getCompressedStackTrace());
}
selectedRows_mon.enter();
try {
if (selectedRows.size() == 0) {
return;
}
ListRow focusedRow = getRowFocused();
ListRow firstRow = (ListRow) selectedRows.get(0);
index = indexOf(firstRow) + relative;
if (index < 0) {
index = 0;
}
if (index >= rows.size()) {
if (index == 0) {
return;
}
index = rows.size() - 1;
}
ListRow newRow = (ListRow) rows.get(index);
setSelectedRows(new ListRow[] { newRow
});
if (firstRow.equals(focusedRow)) {
newRow.setFocused(true);
}
} finally {
selectedRows_mon.exit();
}
}
public void refreshAll(final boolean doGraphics) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
// String s = "";
for (int i = 0; i < rows.size(); i++) {
ListRow row = (ListRow) rows.get(i);
// if (row.isVisible()) {
// s += i + ";";
// }
row.refresh(doGraphics);
}
//System.out.println(sTableID + "; vis=" + s);
}
});
}
/**
* Process the queue of datasources to be added and removed
*
*/
public void processDataSourceQueue() {
Object[] dataSourcesAdd = null;
Object[] dataSourcesRemove = null;
try {
row_mon.enter();
if (dataSourcesToAdd.size() > 0) {
dataSourcesAdd = dataSourcesToAdd.toArray();
dataSourcesToAdd.clear();
// remove the ones we are going to add then delete
if (dataSourcesToRemove != null && dataSourcesToRemove.size() > 0) {
for (int i = 0; i < dataSourcesAdd.length; i++) {
if (dataSourcesToRemove.contains(dataSourcesAdd[i])) {
dataSourcesToRemove.remove(dataSourcesAdd[i]);
dataSourcesAdd[i] = null;
if (DEBUGADDREMOVE) {
System.out.println(sTableID
+ ": Saved time by not adding a row that was removed");
}
}
}
}
}
if (dataSourcesToRemove != null && dataSourcesToRemove.size() > 0) {
dataSourcesRemove = dataSourcesToRemove.toArray();
if (DEBUGADDREMOVE && dataSourcesRemove.length > 1) {
System.out.println(sTableID + ": Streamlining removing "
+ dataSourcesRemove.length + " rows");
}
dataSourcesToRemove.clear();
}
} finally {
row_mon.exit();
}
if (dataSourcesAdd != null) {
addDataSources(dataSourcesAdd, true, -1);
if (DEBUGADDREMOVE && dataSourcesAdd.length > 1) {
System.out.println(sTableID + ": Streamlined adding "
+ dataSourcesAdd.length + " rows");
}
}
if (dataSourcesRemove != null) {
// for now, remove one at a time
// TODO: all at once
for (int i = 0; i < dataSourcesRemove.length; i++) {
Object ds = dataSourcesRemove[i];
removeDataSource(ds, true);
}
}
}
public void addDataSource(final Object datasource, boolean bImmediate) {
addDataSources(new Object[] { datasource
}, bImmediate, -1);
}
public void addDataSource(final Object datasource, boolean bImmediate, int pos) {
addDataSources(new Object[] { datasource
}, bImmediate, pos);
}
public void addDataSources(final Object[] dataSources, boolean bImmediate) {
addDataSources(dataSources, bImmediate, -1);
}
public void addDataSources(final Object[] dataSources, boolean bImmediate,
final int pos) {
if (dataSources == null) {
return;
}
// In order to save time, we cache entries to be added and process them
// in a refresh cycle. This is a huge benefit to tables that have
// many rows being added and removed in rapid succession
if (!bImmediate) {
int count;
if (DEBUGADDREMOVE) {
count = 0;
}
try {
row_mon.enter();
if (dataSourcesToAdd == null) {
dataSourcesToAdd = new ArrayList(4);
}
for (int i = 0; i < dataSources.length; i++) {
if (!mapDataSourceToRow.containsKey(dataSources[i])) {
dataSourcesToAdd.add(dataSources[i]);
if (DEBUGADDREMOVE) {
count++;
}
}
}
if (DEBUGADDREMOVE && count > 0) {
System.out.println(sTableID + ": Queueing " + count
+ " dataSources to add");
}
return;
} finally {
row_mon.exit();
}
}
Utils.execSWTThread(new Runnable() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -