package org.gudy.azureus2.ui.swt.views.table.painted;
import java.util.*;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.plugins.ui.tables.*;
import org.gudy.azureus2.plugins.ui.tables.TableColumn;
import org.gudy.azureus2.ui.swt.MenuBuildUtils;
import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.HSLColor;
import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.views.table.*;
import org.gudy.azureus2.ui.swt.views.table.impl.*;
import com.aelitis.azureus.ui.common.table.*;
import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
import com.aelitis.azureus.ui.common.table.impl.TableRowCoreSorter;
import com.aelitis.azureus.ui.common.table.impl.TableViewImpl;
import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.utils.FontUtils;
/**
* A TableView implemented by painting on a canvas
*
* TODO:
* Keyboard Selection
* Cursor
* Column move and resize past bounds
*/
public class TableViewPainted
extends TableViewImpl<Object>
implements ParameterListener, TableViewSWT<Object>, ObfusticateImage,
MessageTextListener
{
private static final boolean hasGetScrollBarMode = SWT.getVersion() >= 3821;
private static final boolean DEBUG_ROWCHANGE = false;
private static final boolean DEBUG_WITH_SHELL = false;
private static final int DEFAULT_HEADER_HEIGHT = 27;
private Composite cTable;
private int loopFactor;
/** How often graphic cells get updated
*/
protected int graphicsUpdate = configMan.getIntParameter("Graphics Update");
protected int reOrderDelay = configMan.getIntParameter("ReOrder Delay");
protected boolean extendedErase = configMan.getBooleanParameter("Table.extendedErase");
private int defaultRowHeight = 17;
/**
* Rows visible to user. We assume this list is always up to date
*/
LinkedHashSet<TableRowPainted> visibleRows = new LinkedHashSet<TableRowPainted>();
Object visibleRows_sync = new Object();
Object lock = new Object();
/**
* Up to date table client area. So far, the best places to refresh
* this variable are in the PaintItem event and the scrollbar's events.
* Typically table.getClientArea() is time consuming
*/
protected Rectangle clientArea;
private boolean isVisible;
private Shell shell;
private Color colorLine;
private int headerHeight;
private Canvas cHeaderArea;
private Image canvasImage;
private final String sDefaultSortOn;
private TableViewSWT_Common tvSWTCommon;
private TableViewSWT_TabsCommon tvTabsCommon;
private TableViewSWTPanelCreator mainPanelCreator;
private boolean isMultiSelect;
private int columnsWidth;
private Menu menu;
protected boolean isHeaderDragging;
private TableRowPainted focusedRow;
private boolean enableTabViews;
private String[] tabViewRestriction;
private boolean tabViewsExpandedByDefault = true;
protected boolean isDragging;
private Composite mainComposite;
private Object heightChangeSync = new Object();
private int totalHeight = 0;
private boolean redrawTableScheduled;
private Font fontHeaderSmall;
private Font fontHeader;
private ScrollBar hBar;
private ScrollBar vBar;
private Canvas sCanvasImage;
class RefreshTableRunnable extends AERunnable {
private boolean forceSort;
public void runSupport() {
__refreshTable(isForceSort());
}
public boolean isForceSort() {
return forceSort;
}
public void setForceSort(boolean forceSort) {
this.forceSort = forceSort;
}
}
private RefreshTableRunnable refreshTableRunnable = new RefreshTableRunnable();
protected boolean isFocused;
/**
* Main Initializer
* @param _sTableID Which table to handle (see
* {@link org.gudy.azureus2.plugins.ui.tables.TableManager}).
* Config settings are stored with the prefix of
* "Table.<i>TableID</i>"
* @param _sPropertiesPrefix Prefix for retrieving text from the properties
* file (MessageText). Typically
* <i>TableID</i> + "View"
* @param _basicItems Column Definitions
* @param _sDefaultSortOn Column name to sort on if user hasn't chosen one yet
* @param _iTableStyle SWT style constants used when creating the table
*/
public TableViewPainted(Class<?> pluginDataSourceType, String _sTableID,
String _sPropertiesPrefix, TableColumnCore[] _basicItems,
String _sDefaultSortOn, int _iTableStyle) {
super(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems);
setRowsSync(lock);
// boolean wantTree = (_iTableStyle & SWT.CASCADE) != 0;
// _iTableStyle &= ~SWT.CASCADE;
// if (wantTree) {
// useTree = COConfigurationManager.getBooleanParameter("Table.useTree")
// && !Utils.isCarbon;
// }
// basicItems = _basicItems;
// sDefaultSortOn = _sDefaultSortOn;
// iTableStyle = _iTableStyle | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED;
this.sDefaultSortOn = _sDefaultSortOn;
this.isMultiSelect = (_iTableStyle & SWT.MULTI) != 0;
// Deselect rows if user clicks on a blank spot (a spot with no row)
tvSWTCommon = new TableViewSWT_Common(this) {
public void widgetSelected(SelectionEvent event) {
//updateSelectedRows(table.getSelection(), true);
}
@Override
public void mouseUp(TableRowCore clickedRow, TableCellCore cell, int button,
int stateMask) {
super.mouseUp(clickedRow, cell, button, stateMask);
if (clickedRow == null) {
return;
}
if (button == 1) {
int keyboardModifier = (stateMask & SWT.MODIFIER_MASK);
if ((keyboardModifier & SWT.SHIFT) != 0) {
// select from focus to row
selectRowsTo(clickedRow);
return;
} else if (keyboardModifier == 0) {
setSelectedRows(new TableRowCore[] {
clickedRow
});
return;
}
}
}
@Override
public void mouseDown(TableRowSWT clickedRow, TableCellCore cell, int button,
int stateMask) {
if (clickedRow == null) {
return;
}
int keyboardModifier = (stateMask & SWT.MODIFIER_MASK);
if (button == 1) {
if ((keyboardModifier & SWT.MOD1) != 0) {
// control (win), alt (mac)
setRowSelected(clickedRow, !clickedRow.isSelected(), true);
return;
}
} else if (button == 3) {
if (!isSelected(clickedRow) && keyboardModifier == 0) {
setSelectedRows(new TableRowCore[] {
clickedRow
});
}
}
if (getSelectedRowsSize() == 0) {
setSelectedRows(new TableRowCore[] {
clickedRow
});
}
}
@Override
public void keyPressed(KeyEvent event) {
if (getComposite() != event.widget) {
super.keyPressed(event);
return;
}
boolean updateTable = false;
if (event.keyCode == SWT.ARROW_UP) {
TableRowCore rowToSelect = getPreviousRow(focusedRow);
if ((event.stateMask & SWT.SHIFT) != 0) {
if (rowToSelect != null) {
TableRowCore[] selectedRows = getSelectedRows();
Arrays.sort(selectedRows, new TableRowCoreSorter());
boolean select = selectedRows.length == 0
|| selectedRows[0] == focusedRow;
// System.out.println("i=" + selectedRows[0].getIndex() + ";"
// + select + ";" + focusedRow.getIndex());
if (select) {
rowToSelect.setSelected(select);
} else {
focusedRow.setSelected(false);
setFocusedRow(rowToSelect);
}
updateTable = true;
}
} else if ((event.stateMask & SWT.CONTROL) != 0) {
// show one more topRow
TableRowPainted firstRow = visibleRows.iterator().next();
if (firstRow != null) {
int hChange = 0;
if (isRowPartiallyVisible(firstRow)) {
hChange = firstRow.getDrawOffset().y - clientArea.y;
} else {
TableRowCore prevRow = getPreviousRow(firstRow);
if (prevRow != firstRow && prevRow != null) {
hChange = -prevRow.getHeight();
}
}
vBar.setSelection(vBar.getSelection() + hChange);
swt_vBarChanged();
}
} else {
setSelectedRows(new TableRowCore[] {
rowToSelect
});
updateTable = true;
}
} else if (event.keyCode == SWT.PAGE_UP) {
TableRowCore row = focusedRow;
TableRowPainted lastRow = getLastVisibleRow();
int y = lastRow == null ? 0 : (clientArea.y + clientArea.height) - lastRow.getDrawOffset().y;
while (row != null && y < clientArea.height) {
y += row.getHeight();
row = getPreviousRow(row);
}
if (row == null) {
row = getRow(0);
}
if ((event.stateMask & SWT.SHIFT) != 0) {
selectRowsTo(row);
} else if (event.stateMask == 0) {
setSelectedRows(new TableRowCore[] {
row
});
}
updateTable = true;
} else if (event.keyCode == SWT.HOME) {
if ((event.stateMask & SWT.SHIFT) != 0) {
selectRowsTo(getRow(0));
} else if (event.stateMask == 0) {
setSelectedRows(new TableRowCore[] {
getRow(0)
});
}
updateTable = true;
} else if (event.keyCode == SWT.ARROW_DOWN) {
if ((event.stateMask & SWT.CONTROL) != 0) {
// show one less topRow
TableRowPainted firstRow = visibleRows.iterator().next();
if (firstRow != null) {
int hChange = 0;
if (isRowPartiallyVisible(firstRow)) {
hChange = firstRow.getHeight() + (firstRow.getDrawOffset().y - clientArea.y);
} else {
hChange = firstRow.getHeight();
}
vBar.setSelection(vBar.getSelection() + hChange);
swt_vBarChanged();
}
} else {
TableRowCore rowToSelect = getNextRow(focusedRow);
if (rowToSelect != null) {
if ((event.stateMask & SWT.SHIFT) != 0) {
TableRowCore[] selectedRows = getSelectedRows();
Arrays.sort(selectedRows, new TableRowCoreSorter());
boolean select = selectedRows.length == 0
|| selectedRows[selectedRows.length - 1] == focusedRow;
if (select) {
rowToSelect.setSelected(select);
} else {
focusedRow.setSelected(false);
setFocusedRow(rowToSelect);
}
} else {
setSelectedRows(new TableRowCore[] {
rowToSelect
});
}
updateTable = true;
}
}
} else if (event.keyCode == SWT.PAGE_DOWN) {
TableRowCore row = focusedRow;
TableRowPainted firstRow = visibleRows.size() == 0 ? null : visibleRows.iterator().next();
int y = firstRow == null ? 0 : firstRow.getHeight() - (clientArea.y - firstRow.getDrawOffset().y);
while (row != null && y < clientArea.height) {
y += row.getHeight();
TableRowCore nextRow = getNextRow(row);
if (nextRow == null) {
break;
}
row = nextRow;
}
if ((event.stateMask & SWT.SHIFT) != 0) {
selectRowsTo(row);
} else if (event.stateMask == 0) {
setSelectedRows(new TableRowCore[] {
row
});
}
updateTable = true;
} else if (event.keyCode == SWT.END) {
TableRowCore lastRow = getRow(getRowCount() - 1);
if ((event.stateMask & SWT.SHIFT) != 0) {
selectRowsTo(lastRow);
} else if (event.stateMask == 0) {
setSelectedRows(new TableRowCore[] {
lastRow
});
}
updateTable = true;
} else if (event.keyCode == SWT.ARROW_RIGHT && event.stateMask == 0) {
if (event.stateMask == 0 && focusedRow != null && !focusedRow.isExpanded() && canHaveSubItems()) {
focusedRow.setExpanded(true);
} else {
if (hBar.isEnabled()) {
hBar.setSelection(hBar.getSelection() + 50);
cTable.redraw();
updateTable = true;
}
}
} else if (event.keyCode == SWT.ARROW_LEFT && event.stateMask == 0) {
if (event.stateMask == 0 && focusedRow != null && focusedRow.isExpanded() && canHaveSubItems()) {
focusedRow.setExpanded(false);
} else {
if (hBar.isEnabled()) {
hBar.setSelection(hBar.getSelection() - 50);
cTable.redraw();
updateTable = true;
}
}
}
if (updateTable) {
cTable.update();
}
super.keyPressed(event);
}
@Override
public void keyReleased(KeyEvent e) {
swt_calculateClientArea();
visibleRowsChanged();
super.keyReleased(e);
}
};
}
protected boolean isRowPartiallyVisible(TableRowPainted row) {
if (row == null) {
return false;
}
Point drawOffset = row.getDrawOffset();
int height = row.getHeight();
return (drawOffset.y < clientArea.y && drawOffset.y + height > clientArea.y)
|| (drawOffset.y < clientArea.y + clientArea.height && drawOffset.y
+ height > clientArea.y + clientArea.height);
}
protected void selectRowsTo(TableRowCore clickedRow) {
if (!isMultiSelect) {
setSelectedRows(new TableRowCore[] {
clickedRow
});
return;
}
TableRowCore[] selectedRows = getSelectedRows();
TableRowCore firstRow = selectedRows.length > 0 ? selectedRows[0]
: getRow(0);
TableRowCore parentFirstRow = firstRow;
while (parentFirstRow.getParentRowCore() != null) {
parentFirstRow = parentFirstRow.getParentRowCore();
}
TableRowCore parentClickedRow = clickedRow;
while (parentClickedRow.getParentRowCore() != null) {
parentClickedRow = parentClickedRow.getParentRowCore();
}
int startPos;
int endPos;
if (parentFirstRow == parentClickedRow) {
startPos = parentFirstRow == firstRow ? -1 : firstRow.getIndex();
endPos = parentClickedRow == clickedRow ? -1 : clickedRow.getIndex();
} else {
startPos = indexOf(parentFirstRow);
endPos = indexOf(parentClickedRow);
if (endPos == -1 || startPos == -1) {
return;
}
}
ArrayList<TableRowCore> rowsToSelect = new ArrayList<TableRowCore>(Arrays.asList(selectedRows));
TableRowCore curRow = firstRow;
do {
if (!rowsToSelect.contains(curRow)) {
rowsToSelect.add(curRow);
}
TableRowCore newRow = (startPos < endPos) ? getNextRow(curRow) : getPreviousRow(curRow);
// prevent infinite loop if things go wonky (which they have been soon to do!)
if ( newRow == curRow ){
break;
}else{
curRow = newRow;
}
} while (curRow != clickedRow && curRow != null);
if (curRow != null && !rowsToSelect.contains(curRow)) {
rowsToSelect.add(curRow);
}
setSelectedRows(rowsToSelect.toArray(new TableRowCore[0]));
setFocusedRow(clickedRow);
}
protected TableRowCore getPreviousRow(TableRowCore relativeToRow) {
TableRowCore rowToSelect = null;
if (relativeToRow != null) {
TableRowCore parentRow = relativeToRow.getParentRowCore();
if (parentRow == null) {
TableRowCore row = getRow(indexOf(relativeToRow) - 1);
if (row != null && row.isExpanded() && row.getSubItemCount() > 0) {
rowToSelect = row.getSubRow(row.getSubItemCount() - 1);
} else {
rowToSelect = row;
}
} else {
int index = relativeToRow.getIndex();
if (index > 0) {
rowToSelect = parentRow.getSubRow(index - 1);
} else {
rowToSelect = parentRow;
}
}
}
if (rowToSelect == null) {
rowToSelect = getRow(0);
}
return rowToSelect;
}
protected TableRowCore getNextRow(TableRowCore relativeToRow) {
TableRowCore rowToSelect = null;
if (relativeToRow == null) {
rowToSelect = getRow(0);
} else {
if (relativeToRow.isExpanded() && relativeToRow.getSubItemCount() > 0) {
TableRowCore[] subRowsWithNull = relativeToRow.getSubRowsWithNull();
for (TableRowCore row : subRowsWithNull) {
if (row != null) {
rowToSelect = row;
break;
}
}
if (rowToSelect == null) {
rowToSelect = getRow(relativeToRow.getIndex() + 1);
}
} else {
TableRowCore parentRow = relativeToRow.getParentRowCore();
if (parentRow != null) {
rowToSelect = parentRow.getSubRow(relativeToRow.getIndex() + 1);
if (rowToSelect == null) {
rowToSelect = getRow(parentRow.getIndex() + 1);
}
} else {
rowToSelect = getRow(relativeToRow.getIndex() + 1);
}
}
}
return rowToSelect;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#clipboardSelected()
*/
public void clipboardSelected() {
String sToClipboard = "";
TableColumnCore[] visibleColumns = getVisibleColumns();
for (int j = 0; j < visibleColumns.length; j++) {
if (j != 0) {
sToClipboard += "\t";
}
String title = MessageText.getString(visibleColumns[j].getTitleLanguageKey());
sToClipboard += title;
}
TableRowCore[] rows = getSelectedRows();
for (TableRowCore row : rows) {
sToClipboard += "\n";
for (int j = 0; j < visibleColumns.length; j++) {
TableColumnCore column = visibleColumns[j];
if (j != 0) {
sToClipboard += "\t";
}
TableCellCore cell = row.getTableCellCore(column.getName());
if (cell != null) {
sToClipboard += cell.getClipboardText();
}
}
}
new Clipboard(getComposite().getDisplay()).setContents(new Object[] {
sToClipboard
}, new Transfer[] {
TextTransfer.getInstance()
});
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#isDisposed()
*/
public boolean isDisposed() {
return cTable == null || cTable.isDisposed();
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#refreshTable(boolean)
*/
public void refreshTable(final boolean bForceSort) {
//__refreshTable(bForceSort);
refreshTableRunnable.setForceSort(bForceSort);
Utils.getOffOfSWTThread(refreshTableRunnable);
}
public void __refreshTable(boolean bForceSort) {
long lStart = SystemTime.getCurrentTime();
super.refreshTable(bForceSort);
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
// call to trigger invalidation if visibility changes
isVisible();
}
});
final boolean bDoGraphics = (loopFactor % graphicsUpdate) == 0;
final boolean bWillSort = bForceSort || (reOrderDelay != 0)
&& ((loopFactor % reOrderDelay) == 0);
//System.out.println("Refresh.. WillSort? " + bWillSort);
if (bWillSort) {
TableColumnCore sortColumn = getSortColumn();
if (bForceSort && sortColumn != null) {
resetLastSortedOn();
sortColumn.setLastSortValueChange(SystemTime.getCurrentTime());
}
_sortColumn(true, false, false);
}
runForAllRows(new TableGroupRowVisibilityRunner() {
public void run(TableRowCore row, boolean bVisible) {
row.refresh(bDoGraphics, bVisible);
}
});
loopFactor++;
long diff = SystemTime.getCurrentTime() - lStart;
if (diff > 0) {
//debug("refreshTable took " + diff);
}
if (tvTabsCommon != null) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (tvTabsCommon != null) {
tvTabsCommon.swt_refresh();
}
}
});
}
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setEnableTabViews(boolean)
*/
public void setEnableTabViews(boolean enableTabViews, boolean expandByDefault, String[] restrictedToIDs ){
this.enableTabViews = enableTabViews;
tabViewRestriction = restrictedToIDs;
tabViewsExpandedByDefault = expandByDefault;
}
public boolean isTabViewsEnabled() {
return enableTabViews;
}
public String[] getTabViewsRestrictedTo() {
return( tabViewRestriction );
}
public boolean
getTabViewsExpandedByDefault()
{
return( tabViewsExpandedByDefault );
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setFocus()
*/
public void setFocus() {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (isDisposed()) {
return;
}
cTable.setFocus();
}
});
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setRowDefaultHeight(int)
*/
public void setRowDefaultHeight(int iHeight) {
if (iHeight > defaultRowHeight) {
defaultRowHeight = iHeight;
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (vBar != null && !vBar.isDisposed()) {
vBar.setIncrement(defaultRowHeight);
}
}
});
}
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#getRow(int, int)
*/
public TableRowCore getRow(int x, int y) {
Set<TableRowPainted> visibleRows = this.visibleRows;
if (visibleRows.size() == 0) {
return null;
}
boolean firstRow = true;
int curY = 0;
for (TableRowPainted row : visibleRows) {
if (firstRow) {
curY = row.getDrawOffset().y;
}
int h = row.getHeight();
if (y >= curY && y < curY + h) {
return row;
}
curY += h;
}
return null;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#isRowVisible(com.aelitis.azureus.ui.common.table.TableRowCore)
*/
public boolean isRowVisible(TableRowCore row) {
if (row == null) {
return false;
}
synchronized (visibleRows_sync) {
return visibleRows.contains(row);
}
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#getTableCellWithCursor()
*/
public TableCellCore getTableCellWithCursor() {
// TODO: Make work outside SWT?
Point pt = cTable.getDisplay().getCursorLocation();
pt = cTable.toControl(pt);
return getTableCell(pt.x, clientArea.y + pt.y);
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#getTableRowWithCursor()
*/
public TableRowCore getTableRowWithCursor() {
// TODO: Make work outside SWT?
Point pt = cTable.getDisplay().getCursorLocation();
pt = cTable.toControl(pt);
return getTableRow(pt.x, pt.y, true);
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#getRowDefaultHeight()
*/
public int getRowDefaultHeight() {
return defaultRowHeight;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setEnabled(boolean)
*/
public void setEnabled(final boolean enable) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (!isDisposed()) {
cTable.setEnabled(enable);
}
}
});
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#canHaveSubItems()
*/
public boolean canHaveSubItems() {
return true;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setHeaderVisible(boolean)
*/
public void setHeaderVisible(final boolean visible) {
super.setHeaderVisible(visible);
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (cHeaderArea != null && !cHeaderArea.isDisposed()) {
cHeaderArea.setVisible(visible);
FormData fd = Utils.getFilledFormData();
fd.height = visible ? headerHeight : 1;
fd.bottom = null;
cHeaderArea.setLayoutData(fd);
cHeaderArea.getParent().layout(true);
}
}
});
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#getMaxItemShown()
*/
public int getMaxItemShown() {
// NOT USED
return 0;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableView#setMaxItemShown(int)
*/
public void setMaxItemShown(int newIndex) {
// NOT USED
}
/* (non-Javadoc)
* @see org.gudy.azureus2.core3.internat.MessageText.MessageTextListener#localeChanged(java.util.Locale, java.util.Locale)
*/
public void localeChanged(Locale old_locale, Locale new_locale) {
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
if (tvTabsCommon != null) {
tvTabsCommon.localeChanged();
}
tableInvalidate();
refreshTable(true);
cHeaderArea.redraw();
}
});
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableStructureModificationListener#columnOrderChanged(int[])
*/
public void columnOrderChanged(int[] iPositions) {
//TODO
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.TableStructureModificationListener#columnSizeChanged(com.aelitis.azureus.ui.common.table.TableColumnCore, int)
*/
public void columnSizeChanged(TableColumnCore tableColumn, int diff) {
columnsWidth += diff;
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (cHeaderArea != null && !cHeaderArea.isDisposed()) {
cHeaderArea.redraw();
}
swt_fixupSize();
redrawTable();
}
});
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addKeyListener(org.eclipse.swt.events.KeyListener)
*/
public void addKeyListener(KeyListener listener) {
if (tvSWTCommon == null) {
return;
}
tvSWTCommon.addKeyListener(listener);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#removeKeyListener(org.eclipse.swt.events.KeyListener)
*/
public void removeKeyListener(KeyListener listener) {
if (tvSWTCommon == null) {
return;
}
tvSWTCommon.removeKeyListener(listener);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getKeyListeners()
*/
public KeyListener[] getKeyListeners() {
if (tvSWTCommon == null) {
return new KeyListener[0];
}
return tvSWTCommon.getKeyListeners();
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addMenuFillListener(org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener)
*/
public void addMenuFillListener(TableViewSWTMenuFillListener l) {
if (tvSWTCommon == null) {
return;
}
tvSWTCommon.addMenuFillListener(l);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDragSource(int)
*/
public DragSource createDragSource(int style) {
final DragSource dragSource = new DragSource(cTable, style);
dragSource.addDragListener(new DragSourceAdapter() {
public void dragStart(DragSourceEvent event) {
cTable.setCursor(null);
TableRowCore row = getTableRow(event.x, event.y, true);
if (row != null && !row.isSelected()) {
setSelectedRows(new TableRowCore[] { row });
}
isDragging = true;
}
public void dragFinished(DragSourceEvent event) {
isDragging = false;
}
});
cTable.addDisposeListener(new DisposeListener() {
// @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
public void widgetDisposed(DisposeEvent e) {
if (!dragSource.isDisposed()) {
dragSource.dispose();
}
}
});
return dragSource;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDropTarget(int)
*/
public DropTarget createDropTarget(int style) {
final DropTarget dropTarget = new DropTarget(cTable, style);
cTable.addDisposeListener(new DisposeListener() {
// @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
public void widgetDisposed(DisposeEvent e) {
if (!dropTarget.isDisposed()) {
dropTarget.dispose();
}
}
});
return dropTarget;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getComposite()
*/
public Composite getComposite() {
return cTable;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getRow(org.eclipse.swt.dnd.DropTargetEvent)
*/
public TableRowCore getRow(DropTargetEvent event) {
//TODO
// maybe
Point pt = cTable.toControl(event.x, event.y);
return getRow(pt.x, clientArea.y + pt.y);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getRowSWT(java.lang.Object)
*/
public TableRowSWT getRowSWT(Object dataSource) {
return (TableRowSWT) getRow(dataSource);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableComposite()
*/
public Composite getTableComposite() {
return cTable;
}
/** Creates a composite within the specified composite and sets its layout
* to a default FillLayout().
*
* @param composite to create your Composite under
* @return The newly created composite
*/
public Composite createMainPanel(Composite composite) {
TableViewSWTPanelCreator mainPanelCreator = getMainPanelCreator();
if (mainPanelCreator != null) {
return mainPanelCreator.createTableViewPanel(composite);
}
Composite panel = new Composite(composite, SWT.NO_FOCUS);
composite.getLayout();
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
panel.setLayout(layout);
Object parentLayout = composite.getLayout();
if (parentLayout == null || (parentLayout instanceof GridLayout)) {
panel.setLayoutData(new GridData(GridData.FILL_BOTH));
}
return panel;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#initialize(org.eclipse.swt.widgets.Composite)
*/
public void initialize(Composite parent) {
tvTabsCommon = new TableViewSWT_TabsCommon(this);
shell = parent.getShell();
mainComposite = tvTabsCommon.createSashForm(parent);
mainComposite.setData("Name", tableID);
mainComposite.setData("ObfusticateImage", this);
Composite cTableComposite = tvTabsCommon.tableComposite;
cTableComposite.setLayout(new FormLayout());
Layout layout = parent.getLayout();
if (layout instanceof FormLayout) {
FormData fd = Utils.getFilledFormData();
cTableComposite.setLayoutData(fd);
}
cHeaderArea = new Canvas(cTableComposite, SWT.DOUBLE_BUFFERED);
fontHeader = FontUtils.getFontWithHeight(cHeaderArea.getFont(), null, 12);
fontHeaderSmall = FontUtils.getFontPercentOf(fontHeader, 0.8f);
cHeaderArea.setFont(fontHeader);
cTable = new Canvas(cTableComposite, SWT.NO_BACKGROUND | SWT.H_SCROLL | SWT.V_SCROLL);
// good test
//cTable.setFont(FontUtils.getFontPercentOf(cTable.getFont(), 1.50f));
int minRowHeight = FontUtils.getFontHeightInPX(cTable.getFont());
minRowHeight += Math.ceil(minRowHeight * 2.0 / 16.0);
if (defaultRowHeight < minRowHeight) {
defaultRowHeight = minRowHeight;
}
cTable.setBackground(parent.getDisplay().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
headerHeight = configMan.getIntParameter("Table.headerHeight");
if (headerHeight <= 0) {
headerHeight = DEFAULT_HEADER_HEIGHT;
}
FormData fd = Utils.getFilledFormData();
fd.height = headerHeight;
fd.bottom = null;
cHeaderArea.setLayoutData(fd);
fd = Utils.getFilledFormData();
fd.top = new FormAttachment(cHeaderArea);
cTable.setLayoutData(fd);
clientArea = cTable.getClientArea();
TableColumnCore[] tableColumns = getAllColumns();
TableColumnCore[] tmpColumnsOrdered = new TableColumnCore[tableColumns.length];
//Create all columns
int columnOrderPos = 0;
Arrays.sort(tableColumns,
TableColumnManager.getTableColumnOrderComparator());
for (int i = 0; i < tableColumns.length; i++) {
int position = tableColumns[i].getPosition();
if (position != -1 && tableColumns[i].isVisible()) {
//table.createNewColumn(SWT.NULL);
//System.out.println(i + "] " + tableColumns[i].getName() + ";" + position);
tmpColumnsOrdered[columnOrderPos++] = tableColumns[i];
}
}
//int numSWTColumns = table.getColumnCount();
//int iNewLength = numSWTColumns - (bSkipFirstColumn ? 1 : 0);
TableColumnCore[] columnsOrdered = new TableColumnCore[columnOrderPos];
System.arraycopy(tmpColumnsOrdered, 0, columnsOrdered, 0, columnOrderPos);
setColumnsOrdered(columnsOrdered);
cTable.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
swt_paintComposite(e);
}
});
menu = createMenu();
cTable.setMenu(menu);
cHeaderArea.setMenu(menu);
setupHeaderArea(cHeaderArea);
cTable.addControlListener(new ControlListener() {
public void controlResized(ControlEvent e) {
swt_calculateClientArea();
swt_fixupSize();
}
public void controlMoved(ControlEvent e) {
}
});
hBar = cTable.getHorizontalBar();
if (hBar != null) {
hBar.setValues(0, 0, 0, 10, 10, 100);
hBar.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
//swt_calculateClientArea();
cTable.redraw();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
vBar = cTable.getVerticalBar();
if (vBar != null) {
vBar.setValues(0, 0, 0, 50, getRowDefaultHeight(), 50);
vBar.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
swt_vBarChanged();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
if (DEBUG_WITH_SHELL) {
Shell shell = new Shell();
sCanvasImage = new Canvas(shell, SWT.DOUBLE_BUFFERED);
shell.setLayout(new FillLayout());
sCanvasImage.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
if (canvasImage == null) {
return;
}
e.gc.drawImage(canvasImage, 0, 0);
//System.out.println(System.currentTimeMillis() + "] Paint " + e.x + "x" + e.y + " " + e.width + "x" + e.height);
}
});
shell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
sCanvasImage = null;
}
});
shell.setVisible(true);
}
cTable.addMouseListener(tvSWTCommon);
cTable.addMouseMoveListener(tvSWTCommon);
cTable.addKeyListener(tvSWTCommon);
//composite.addSelectionListener(tvSWTCommon);
cTable.addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
e.doit = true;
}
});
SelectedContentManager.addCurrentlySelectedContentListener(new SelectedContentListener() {
public void currentlySelectedContentChanged(
ISelectedContent[] currentContent, String viewID) {
if ( cTable == null || cTable.isDisposed()){
SelectedContentManager.removeCurrentlySelectedContentListener( this );
}else{
redrawTable();
}
}
});
cTable.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
isFocused = false;
redrawTable();
}
public void focusGained(FocusEvent e) {
isFocused = true;
redrawTable();
}
});
isFocused = cTable.isFocusControl();
new TableTooltips(this, cTable);
TableColumnManager tcManager = TableColumnManager.getInstance();
String sSortColumn = tcManager.getDefaultSortColumnName(tableID);
if (sSortColumn == null || sSortColumn.length() == 0) {
sSortColumn = sDefaultSortOn;
}
TableColumnCore tc = tcManager.getTableColumnCore(tableID, sSortColumn);
if (tc == null && tableColumns.length > 0) {
tc = tableColumns[0];
}
setSortColumn(tc, false);
triggerLifeCycleListener(TableLifeCycleListener.EVENT_INITIALIZED);
configMan.addParameterListener("Graphics Update", this);
configMan.addParameterListener("ReOrder Delay", this);
configMan.addParameterListener("Table.extendedErase", this);
configMan.addParameterListener("Table.headerHeight", this);
Colors.getInstance().addColorsChangedListener(this);
// So all TableView objects of the same TableID have the same columns,
// and column widths, etc
TableStructureEventDispatcher.getInstance(tableID).addListener(this);
}
protected void swt_vBarChanged() {
if (DEBUG_SELECTION) {
debug("vBar changed " + vBar.getSelection() + " via " + Debug.getCompressedStackTrace());
}
swt_calculateClientArea();
cTable.update();
}
private void setupHeaderArea(final Canvas cHeaderArea) {
cHeaderArea.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
paintHeader(e);
}
});
Listener l = new Listener() {
boolean mouseDown = false;
TableColumnCore columnSizing;
int columnSizingStart = 0;
public void handleEvent(Event e) {
switch (e.type) {
case SWT.MouseDown: {
if (e.button != 1) {
return;
}
mouseDown = true;
columnSizing = null;
int x = -clientArea.x;
TableColumnCore[] visibleColumns = getVisibleColumns();
for (TableColumnCore column : visibleColumns) {
int w = column.getWidth();
x += w;
if (e.x >= x - 3 && e.x <= x + 3) {
columnSizing = column;
columnSizingStart = e.x;
break;
}
}
break;
}
case SWT.MouseUp: {
if (e.button != 1) {
return;
}
if (mouseDown && columnSizing == null) {
TableColumnCore column = getTableColumnByOffset(e.x);
if (column != null) {
setSortColumn(column, true);
}
}
columnSizing = null;
mouseDown = false;
break;
}
case SWT.MouseMove: {
if (columnSizing != null) {
int diff = (e.x - columnSizingStart);
columnSizing.setWidth(columnSizing.getWidth() + diff);
columnSizingStart = e.x;
} else {
int cursorID = SWT.CURSOR_HAND;
int x = -clientArea.x;
TableColumnCore[] visibleColumns = getVisibleColumns();
for (TableColumnCore column : visibleColumns) {
int w = column.getWidth();
x += w;
if (e.x >= x - 3 && e.x <= x + 3) {
cursorID = SWT.CURSOR_SIZEWE;
break;
}
}
cHeaderArea.setCursor(e.display.getSystemCursor(cursorID));
TableColumnCore column = getTableColumnByOffset(e.x);
if (column == null) {
cHeaderArea.setToolTipText(null);
} else {
String info = MessageText.getString(
column.getTitleLanguageKey() + ".info", (String) null);
if (column.showOnlyImage()) {
String tt = MessageText.getString(
column.getTitleLanguageKey());
if (info != null) {
tt += "\n" + info;
}
cHeaderArea.setToolTipText(tt);
} else {
cHeaderArea.setToolTipText(info);
}
}
}
}
}
}
};
cHeaderArea.addListener(SWT.MouseDown, l);
cHeaderArea.addListener(SWT.MouseUp, l);
cHeaderArea.addListener(SWT.MouseMove, l);
Transfer[] types = new Transfer[] {
TextTransfer.getInstance()
};
final DragSource ds = new DragSource(cHeaderArea, DND.DROP_MOVE);
ds.setTransfer(types);
ds.addDragListener(new DragSourceListener() {
private String eventData;
public void dragStart(DragSourceEvent event) {
Cursor cursor = cHeaderArea.getCursor();
if (cursor != null
&& cursor.equals(event.display.getSystemCursor(SWT.CURSOR_SIZEWE))) {
event.doit = false;
return;
}
cHeaderArea.setCursor(null);
TableColumnCore tc = getTableColumnByOffset(event.x);
isHeaderDragging = tc != null;
if (isHeaderDragging) {
eventData = tc.getName();
}
//System.out.println("drag " + eventData);
}
public void dragSetData(DragSourceEvent event) {
event.data = eventData;
}
public void dragFinished(DragSourceEvent event) {
isHeaderDragging = false;
eventData = null;
}
});
final DropTarget dt = new DropTarget(cHeaderArea, DND.DROP_MOVE);
dt.setTransfer(types);
dt.addDropListener(new DropTargetListener() {
public void dropAccept(DropTargetEvent event) {
}
public void drop(final DropTargetEvent event) {
if (event.data instanceof String) {
TableColumn tcOrig = getTableColumn((String) event.data);
Point pt = cTable.toControl(event.x, event.y);
TableColumn tcDest = getTableColumnByOffset(pt.x);
if (tcDest == null) {
TableColumnCore[] visibleColumns = getVisibleColumns();
if (visibleColumns != null && visibleColumns.length > 0) {
tcDest = visibleColumns[visibleColumns.length - 1];
}
}
if (tcOrig != null && tcDest != null) {
int destPos = tcDest.getPosition();
int origPos = tcOrig.getPosition();
final boolean moveRight = destPos > origPos;
TableColumnCore[] visibleColumns = getVisibleColumns();
((TableColumnCore) tcOrig).setPositionNoShift(destPos);
//System.out.println("Move " + origPos + " Right? " + moveRight + " of " + destPos);
Arrays.sort(visibleColumns, new Comparator<TableColumnCore>() {
public int compare(TableColumnCore o1, TableColumnCore o2) {
if (o1 == o2) {
return 0;
}
int diff = o1.getPosition() - o2.getPosition();
if (diff == 0) {
int i = o1.getName().equals(event.data) ? -1 : 1;
if (moveRight) {
i *= -1;
}
return i;
}
return diff;
}
});
for (int i = 0; i < visibleColumns.length; i++) {
TableColumnCore tc = visibleColumns[i];
tc.setPositionNoShift(i);
}
setColumnsOrdered(visibleColumns);
TableStructureEventDispatcher.getInstance(tableID).tableStructureChanged(
false, getDataSourceType());
}
}
}
public void dragOver(DropTargetEvent event) {
}
public void dragOperationChanged(DropTargetEvent event) {
}
public void dragLeave(DropTargetEvent event) {
}
public void dragEnter(DropTargetEvent event) {
}
});
cHeaderArea.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
Utils.disposeSWTObjects(new Object[] {
ds,
dt,
fontHeader,
fontHeaderSmall
});
}
});
}
@Override
public void tableStructureChanged(final boolean columnAddedOrRemoved,
final Class forPluginDataSourceType) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
TableViewPainted.super.tableStructureChanged(columnAddedOrRemoved, forPluginDataSourceType);
if (cHeaderArea != null && !cHeaderArea.isDisposed()) {
cHeaderArea.redraw();
}
redrawTable();
}
});
}
protected void swt_paintComposite(PaintEvent e) {
swt_calculateClientArea();
if (canvasImage == null) {
return;
}
//System.out.println(e.count + " paint " + e.gc.getClipping() + ";" + e.x + "," + e.y + "," + e.width + "," + e.height + " via " + Debug.getCompressedStackTrace());
e.gc.drawImage(canvasImage, -clientArea.x, 0);
// test line
//e.gc.drawLine(0, 0, cTable.getSize().x, canvasImage.getBounds().height);
}
protected void swt_paintCanvasImage(GC gc, Rectangle drawBounds) {
if (cTable == null || cTable.isDisposed()) {
return;
}
int end = drawBounds.y + drawBounds.height;
gc.setFont(cTable.getFont());
gc.setClipping(drawBounds);
TableRowCore oldRow = null;
int pos = -1;
Set<TableRowPainted> visibleRows = this.visibleRows;
for (TableRowPainted row : visibleRows) {
TableRowPainted paintedRow = row;
if (pos == -1) {
pos = row.getIndex();
} else {
pos++;
}
Point drawOffset = paintedRow.getDrawOffset();
int rowStartX = 0;
int rowStartY = drawOffset.y - clientArea.y;
int rowHeight = paintedRow.getHeight();
//debug("Paint " + drawBounds.x + "x" + drawBounds.y + " " + drawBounds.width + "x" + drawBounds.height + "; Row=" +row.getIndex() + ";clip=" + gc.getClipping() +";drawOffset=" + drawOffset);
if (drawBounds.intersects(rowStartX, rowStartY, 9999, rowHeight)) {
// ensure full row height
int diffY2 = (rowStartY + rowHeight) - (drawBounds.y + drawBounds.height);
if (diffY2 > 0 ) {
drawBounds.height += diffY2;
gc.setClipping(drawBounds);
}
paintedRow.swt_paintGC(gc, drawBounds, rowStartX, rowStartY, pos);
}
oldRow = row;
}
int h;
int yDirty;
if (oldRow == null) {
yDirty = drawBounds.y;
h = drawBounds.height;
} else {
yDirty = ((TableRowPainted) oldRow).getDrawOffset().y
+ ((TableRowPainted) oldRow).getFullHeight();
h = (drawBounds.y + drawBounds.height) - yDirty;
}
if (h > 0) {
int rowHeight = getRowDefaultHeight();
if (extendedErase) {
while (yDirty < end) {
pos++;
Color color = TableRowPainted.alternatingColors[pos % 2];
if (color != null) {
gc.setBackground(color);
}
if (color == null) {
gc.setBackground(gc.getDevice().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
}
gc.fillRectangle(drawBounds.x, yDirty, drawBounds.width, rowHeight);
yDirty += rowHeight;
}
} else {
gc.setBackground(gc.getDevice().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
gc.fillRectangle(drawBounds.x, yDirty, drawBounds.width, h);
}
}
//gc.setForeground(getColorLine());
TableColumnCore[] visibleColumns = getVisibleColumns();
int x = 0;
gc.setAlpha(20);
for (TableColumnCore column : visibleColumns) {
x += column.getWidth();
// Vertical lines between columns
gc.drawLine(x - 1, drawBounds.y, x - 1, drawBounds.y + drawBounds.height);
}
gc.setAlpha(255);
}
private Color getColorLine() {
if (colorLine == null) {
colorLine = cTable.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
HSLColor hslColor = new HSLColor();
hslColor.initHSLbyRGB(colorLine.getRed(), colorLine.getGreen(),
colorLine.getBlue());
int lum = hslColor.getLuminence();
if (lum > 127)
lum -= 25;
else
lum += 40;
hslColor.setLuminence(lum);
colorLine = new Color(cTable.getDisplay(), hslColor.getRed(),
hslColor.getGreen(), hslColor.getBlue());
}
return colorLine;
}
private void paintHeader(PaintEvent e) {
Rectangle ca = cHeaderArea.getClientArea();
Color c1 = e.display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
Color c2 = e.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
Color line = c2;
Color fg = e.display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
Pattern patternUp = new Pattern(e.display, 0, 0, 0, ca.height, c1, c2);
Pattern patternDown = new Pattern(e.display, 0, -ca.height , 0, 0, c2, c1);
//e.gc.setBackgroundPattern(patternUp);
//e.gc.fillRectangle(ca);
e.gc.setForeground(line);
//e.gc.drawLine(0, 0, clientArea.width, 0);
e.gc.drawLine(0, headerHeight - 1, clientArea.width, headerHeight - 1);
TableColumnCore[] visibleColumns = getVisibleColumns();
GCStringPrinter sp;
TableColumnCore sortColumn = getSortColumn();
int x = -clientArea.x;
for (TableColumnCore column : visibleColumns) {
int w = column.getWidth();
//squeeze last column's text into available visible space
if (x + w > ca.width) {
w = ca.width - x;
if (w <= 16) {
break;
}
}
boolean isSortColumn = column.equals(sortColumn);
e.gc.setBackgroundPattern(isSortColumn ? patternDown : patternUp);
e.gc.fillRectangle(x, 1, w, headerHeight - 2);
e.gc.setForeground(line);
e.gc.drawLine(x + w - 1, 0, x + w - 1, headerHeight - 1);
e.gc.setForeground(fg);
int yOfs = 0;
int wText = w;
/* Top Center
if (isSortColumn) {
int arrowY = 2;
int arrowHeight = 6;
yOfs = 8;
// draw sort indicator
int middle = w / 2;
int y1, y2;
int arrowHalfW = 4;
if (column.isSortAscending()) {
y2 = arrowY;
y1 = y2 + arrowHeight;
} else {
y1 = arrowY;
y2 = y1 + arrowHeight;
}
e.gc.setAntialias(SWT.ON);
e.gc.setBackground(ColorCache.getColor(e.display, 0, 0, 0));
e.gc.fillPolygon(new int[] {
x + middle - arrowHalfW,
y1,
x + middle + arrowHalfW,
y1,
x + middle,
y2
});
}
*/
if (isSortColumn) {
// draw sort indicator
int arrowHeight = 6;
int arrowY = (headerHeight / 2) - (arrowHeight / 2);
int arrowHalfW = 4;
int middle = w - arrowHalfW - 4;
wText = w - (arrowHalfW * 2) - 5;
int y1, y2;
if (column.isSortAscending()) {
y2 = arrowY;
y1 = y2 + arrowHeight;
} else {
y1 = arrowY;
y2 = y1 + arrowHeight;
}
e.gc.setAntialias(SWT.ON);
e.gc.setBackground(fg);
e.gc.fillPolygon(new int[] {
x + middle - arrowHalfW,
y1,
x + middle + arrowHalfW,
y1,
x + middle,
y2
});
}
int xOfs = x + 2;
boolean onlyShowImage = column.showOnlyImage();
String text = "";
if (!onlyShowImage) {
text = MessageText.getString(column.getTitleLanguageKey());
}
int style = SWT.WRAP | SWT.CENTER;
Image image = null;
String imageID = column.getIconReference();
if (imageID != null) {
image = ImageLoader.getInstance().getImage(imageID);
if (ImageLoader.isRealImage(image)) {
if (onlyShowImage) {
text = null;
Rectangle imageBounds = image.getBounds();
e.gc.drawImage(image, (int) (x + (w / 2.0) - (imageBounds.width / 2.0) + 0.5),
(headerHeight / 2) - (imageBounds.height / 2));
} else {
text = "%0 " + text;
}
} else {
image = null;
}
}
if (text != null) {
sp = new GCStringPrinter(e.gc, text, new Rectangle(xOfs, yOfs - 1,
wText - 4, headerHeight - yOfs + 2), true, false,style);
if (image != null) {
sp.setImages(new Image[] { image } );
}
sp.calculateMetrics();
if (sp.isWordCut() || sp.isCutoff()) {
Font font = e.gc.getFont();
e.gc.setFont(fontHeaderSmall);
sp.printString();
e.gc.setFont(font);
} else {
sp.printString();
}
}
if (imageID != null) {
ImageLoader.getInstance().releaseImage(imageID);
}
x += w;
}
e.gc.setBackgroundPattern(patternUp);
e.gc.fillRectangle(x, 1, clientArea.width - x, headerHeight - 2);
patternUp.dispose();
patternDown.dispose();
e.gc.setBackgroundPattern(null);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#obfusticatedImage(org.eclipse.swt.graphics.Image)
*/
public Image obfusticatedImage(Image image) {
TableColumnCore[] visibleColumns = getVisibleColumns();
TableRowPainted[] visibleRows = this.visibleRows.toArray(new TableRowPainted[0]);
for (TableRowPainted row : visibleRows) {
if (row == null || row.isRowDisposed()) {
continue;
}
for (TableColumnCore tc : visibleColumns) {
if (tc == null || !tc.isObfusticated()) {
continue;
}
TableCellPainted cell = (TableCellPainted) row.getTableCell(tc.getName());
if (cell == null) {
continue;
}
String text = cell.getObfusticatedText();
if (text != null) {
final Rectangle cellBounds = cell.getBoundsOnDisplay();
Point ptDisplay = cTable.getShell().getLocation();
cellBounds.x -= ptDisplay.x;
cellBounds.y -= ptDisplay.y;
Rectangle boundsRaw = cell.getBoundsRaw();
if (boundsRaw.y + cellBounds.height > clientArea.y
+ clientArea.height) {
cellBounds.height -= (boundsRaw.y + cellBounds.height)
- (clientArea.y + clientArea.height);
}
int tableWidth = cTable.getClientArea().width;
if (boundsRaw.x + cellBounds.width > clientArea.x
+ tableWidth) {
cellBounds.width -= (boundsRaw.x + cellBounds.width)
- (clientArea.x + tableWidth);
}
UIDebugGenerator.obfusticateArea(image, cellBounds, text);
}
}
}
UISWTViewCore view = tvTabsCommon == null ? null
: tvTabsCommon.getActiveSubView();
if (view instanceof ObfusticateImage) {
try {
((ObfusticateImage) view).obfusticatedImage(image);
} catch (Exception e) {
Debug.out("Obfuscating " + view, e);
}
}
return image;
}
protected TableViewSWTPanelCreator getMainPanelCreator() {
return mainPanelCreator;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#setMainPanelCreator(org.gudy.azureus2.ui.swt.views.table.TableViewSWTPanelCreator)
*/
public void setMainPanelCreator(TableViewSWTPanelCreator mainPanelCreator) {
this.mainPanelCreator = mainPanelCreator;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#setRowDefaultIconSize(org.eclipse.swt.graphics.Point)
*/
public void setRowDefaultIconSize(Point size) {
setRowDefaultHeight(size.y);
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableCell(int, int)
*/
public TableCellCore getTableCell(int x, int y) {
TableRowSWT row = getTableRow(x, y, true);
if (row == null) {
return null;
}
TableColumnCore column = getTableColumnByOffset(x);
if (column == null) {
return null;
}
return row.getTableCellCore(column.getName());
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableCellMouseOffset(org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
*/
public Point getTableCellMouseOffset(TableCellSWT tableCell) {
if (tableCell == null) {
return null;
}
Point pt = cTable.getDisplay().getCursorLocation();
pt = cTable.toControl(pt);
Rectangle bounds = tableCell.getBounds();
int x = pt.x - bounds.x;
if (x < 0 || x > bounds.width) {
return null;
}
int y = pt.y - bounds.y;
if (y < 0 || y > bounds.height) {
return null;
}
return new Point(x, y);
}
// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#enableFilterCheck(org.eclipse.swt.widgets.Text, com.aelitis.azureus.ui.common.table.TableViewFilterCheck)
public void enableFilterCheck(Text txtFilter,
TableViewFilterCheck<Object> filterCheck) {
TableViewSWTFilter<?> filter = getSWTFilter();
if (filter != null) {
if (filter.widget != null && !filter.widget.isDisposed()) {
filter.widget.removeKeyListener(tvSWTCommon);
filter.widget.removeModifyListener(filter.widgetModifyListener);
}
} else {
this.filter = filter = new TableViewSWTFilter();
}
filter.widget = txtFilter;
if (txtFilter != null) {
txtFilter.addKeyListener(tvSWTCommon);
filter.widgetModifyListener = new ModifyListener() {
public void modifyText(ModifyEvent e) {
setFilterText(((Text) e.widget).getText());
}
};
txtFilter.addModifyListener(filter.widgetModifyListener);
if (txtFilter.getText().length() == 0) {
txtFilter.setText(filter.text);
} else {
filter.text = filter.nextText = txtFilter.getText();
}
} else {
filter.text = filter.nextText = "";
}
filter.checker = filterCheck;
filter.checker.filterSet(filter.text);
refilter();
}
public void disableFilterCheck() {
TableViewSWTFilter<?> filter = getSWTFilter();
if ( filter == null ){
return;
}
if (filter.widget != null && !filter.widget.isDisposed()) {
filter.widget.removeKeyListener(tvSWTCommon);
filter.widget.removeModifyListener(filter.widgetModifyListener);
}
filter = null;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#setFilterText(java.lang.String)
*/
public void setFilterText(String s) {
if (tvSWTCommon != null) {
tvSWTCommon.setFilterText(s);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#enableSizeSlider(org.eclipse.swt.widgets.Composite, int, int)
*/
public boolean enableSizeSlider(Composite composite, int min, int max) {
// TODO
return false;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#disableSizeSlider()
*/
public void disableSizeSlider() {
// TODO
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addRowPaintListener(org.gudy.azureus2.ui.swt.views.table.TableRowSWTPaintListener)
*/
public void addRowPaintListener(TableRowSWTPaintListener listener) {
if (tvSWTCommon != null) {
tvSWTCommon.addRowPaintListener(listener);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#removeRowPaintListener(org.gudy.azureus2.ui.swt.views.table.TableRowSWTPaintListener)
*/
public void removeRowPaintListener(TableRowSWTPaintListener listener) {
if (tvSWTCommon != null) {
tvSWTCommon.removeRowPaintListener(listener);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#invokePaintListeners(org.eclipse.swt.graphics.GC, com.aelitis.azureus.ui.common.table.TableRowCore, com.aelitis.azureus.ui.common.table.TableColumnCore, org.eclipse.swt.graphics.Rectangle)
*/
public void invokePaintListeners(GC gc, TableRowCore row,
TableColumnCore column, Rectangle cellArea) {
if (tvSWTCommon != null) {
tvSWTCommon.invokePaintListeners(gc, row, column, cellArea);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener)
*/
public void addRowMouseListener(TableRowMouseListener listener) {
if (tvSWTCommon != null) {
tvSWTCommon.addRowMouseListener(listener);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#removeRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener)
*/
public void removeRowMouseListener(TableRowMouseListener listener) {
if (tvSWTCommon != null) {
tvSWTCommon.removeRowMouseListener(listener);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#invokeRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent)
*/
public void invokeRowMouseListener(TableRowMouseEvent event) {
if (tvSWTCommon != null) {
tvSWTCommon.invokeRowMouseListener(event);
}
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableOrTreeSWT()
*/
public TableOrTreeSWT getTableOrTreeSWT() {
return null;
}
/* (non-Javadoc)
* @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#packColumns()
*/
public void packColumns() {
// TODO
}
/* (non-Javadoc)
* @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String)
*/
public void parameterChanged(String parameterName) {
boolean invalidate = parameterName == null;
if (parameterName == null || parameterName.equals("Graphics Update")) {
graphicsUpdate = configMan.getIntParameter("Graphics Update");
}
if (parameterName == null || parameterName.equals("ReOrder Delay")) {
reOrderDelay = configMan.getIntParameter("ReOrder Delay");
}
if (parameterName == null || parameterName.equals("Table.extendedErase")) {
extendedErase = configMan.getBooleanParameter("Table.extendedErase");
invalidate = true;
}
if (parameterName == null || parameterName.equals("Table.headerHeight")) {
headerHeight = configMan.getIntParameter("Table.headerHeight");
if (headerHeight == 0) {
headerHeight = DEFAULT_HEADER_HEIGHT;
}
setHeaderVisible(getHeaderVisible());
}
if (parameterName == null || parameterName.startsWith("Color")) {
tableInvalidate();
}
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#createNewRow(java.lang.Object)
*/
@Override
public TableRowCore createNewRow(Object object) {
return new TableRowPainted(null, this, object, true);
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#visibleRowsChanged()
*/
@Override
public void visibleRowsChanged() {
swt_visibleRowsChanged();
}
private void swt_visibleRowsChanged() {
final List<TableRowSWT> newlyVisibleRows = new ArrayList<TableRowSWT>();
final List<TableRowSWT> nowInVisibleRows;
final ArrayList<TableRowSWT> rowsStayedVisibleButMoved = new ArrayList<TableRowSWT>();
List<TableRowSWT> newVisibleRows;
if (isVisible()) {
// this makes a copy.. slower
TableRowCore[] rows = getRows();
newVisibleRows = new ArrayList<TableRowSWT>();
recalculateVisibleRows(rows, 0, newVisibleRows,
rowsStayedVisibleButMoved);
} else {
newVisibleRows = Collections.emptyList();
}
nowInVisibleRows = new ArrayList<TableRowSWT>(0);
synchronized (visibleRows_sync) {
if (visibleRows != null) {
nowInVisibleRows.addAll(visibleRows);
}
}
LinkedHashSet<TableRowPainted> rows = new LinkedHashSet<TableRowPainted>(newVisibleRows.size());
for (TableRowSWT row : newVisibleRows) {
rows.add((TableRowPainted) row);
boolean removed = nowInVisibleRows.remove(row);
if (!removed) {
newlyVisibleRows.add(row);
}
}
synchronized (visibleRows_sync) {
visibleRows = rows;
}
if (DEBUG_ROWCHANGE) {
debug("visRowsChanged; shown=" + visibleRows.size() + "; +"
+ newlyVisibleRows.size() + "/-" + nowInVisibleRows.size() + "/"
+ rowsStayedVisibleButMoved.size() + " via "
+ Debug.getCompressedStackTrace(8));
}
Utils.getOffOfSWTThread(new AERunnable() {
public void runSupport() {
boolean bTableUpdate = false;
for (TableRowSWT row : newlyVisibleRows) {
// no need to refres, the redraw will do it
//row.refresh(true, true);
row.setShown(true, false);
rowsStayedVisibleButMoved.remove(row);
if (Constants.isOSX) {
bTableUpdate = true;
}
}
for (TableRowSWT row : rowsStayedVisibleButMoved) {
row.invalidate();
redrawRow((TableRowPainted) row, false);
}
for (TableRowSWT row : nowInVisibleRows) {
row.setShown(false, false);
}
if (bTableUpdate) {
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (cTable != null && !cTable.isDisposed()) {
cTable.update();
}
}
});
}
}
});
}
private void recalculateVisibleRows(TableRowCore[] rows, int yStart,
List<TableRowSWT> newVisibleRows,
List<TableRowSWT> rowsStayedVisibleButMoved) {
Rectangle bounds = clientArea;
int y = yStart;
String sDebug;
if (DEBUG_ROWCHANGE) {
sDebug = "Visible Rows: ";
}
for (TableRowCore row : rows) {
if (row == null) {
continue;
}
TableRowPainted rowSWT = ((TableRowPainted) row);
int rowHeight = rowSWT.getHeight();
int rowFullHeight = rowSWT.getFullHeight();
if ((y < bounds.y + bounds.height) && (y + rowFullHeight > bounds.y)) {
// this row or subrows are visible
boolean offsetChanged = rowSWT.setDrawOffset(new Point(bounds.x, y));
// check if this row
if (y + rowHeight > bounds.y) {
if (DEBUG_ROWCHANGE) {
sDebug += (rowSWT.getParentRowCore() == null ? ""
: rowSWT.getParentRowCore().getIndex() + ".")
+ rowSWT.getIndex()
+ "(ofs=" + (offsetChanged ? "*" : "")
+ y
+ ";rh="
+ rowHeight + "/" + rowFullHeight + ")" + ", ";
}
if (offsetChanged) {
rowsStayedVisibleButMoved.add(rowSWT);
}
newVisibleRows.add(rowSWT);
}
// check if subrows
if (row.isExpanded()) {
TableRowCore[] subRowsWithNull = row.getSubRowsWithNull();
if (subRowsWithNull.length > 0) {
recalculateVisibleRows(subRowsWithNull, y + rowHeight,
newVisibleRows, rowsStayedVisibleButMoved);
}
}
} else if (newVisibleRows.size() > 0) {
if (DEBUG_ROWCHANGE) {
sDebug += "break(ofs=" + y + ";bounds=" + bounds + ";rh=" + rowFullHeight + ")";
}
break;
}
y += rowFullHeight;
}
if (DEBUG_ROWCHANGE) {
if (yStart == 0) {
debug(sDebug);
}
}
}
@Override
public int uiGuessMaxVisibleRows() {
return (clientArea.height / defaultRowHeight) + 1;
}
@Override
public void uiRemoveRows(TableRowCore[] rows, Integer[] rowIndexes) {
if (focusedRow != null) {
for (TableRowCore row : rows) {
if (row == focusedRow) {
setFocusedRow(null);
break;
}
}
}
int bottomIndex = getRowCount() - 1;
if (bottomIndex < 0) {
redrawTable();
} else {
TableRowCore rowBottom = getLastVisibleRow();
if (rowBottom != null) {
while (rowBottom.getParentRowCore() != null) {
rowBottom = rowBottom.getParentRowCore();
}
if (indexOf(rowBottom) < 0) {
redrawTable();
}
}
}
}
private TableRowPainted getLastVisibleRow() {
synchronized (visibleRows_sync) {
if (visibleRows == null || visibleRows.size() == 0) {
return null;
}
TableRowPainted rowBottom = null;
for (TableRowPainted row : visibleRows) {
rowBottom = row;
}
return rowBottom;
}
}
@Override
public void getOffUIThread(AERunnable runnable) {
Utils.getOffOfSWTThread(runnable);
}
protected void swt_calculateClientArea() {
if (cTable == null || cTable.isDisposed()) {
return;
}
Rectangle oldClientArea = clientArea;
Rectangle newClientArea = cTable.getClientArea();
newClientArea.x = hBar.getSelection();
newClientArea.y = vBar.getSelection();
int w = 0;
TableColumnCore[] visibleColumns = getVisibleColumns();
for (TableColumnCore column : visibleColumns) {
w += column.getWidth();
}
columnsWidth = w;
w = newClientArea.width = Math.max(newClientArea.width, w);
boolean refreshTable = false;
boolean changedX;
boolean changedY;
//boolean changedW;
boolean changedH;
if (oldClientArea != null) {
changedX = oldClientArea.x != newClientArea.x;
changedY = oldClientArea.y != newClientArea.y;
//changedW = oldClientArea.width != newClientArea.width;
changedH = oldClientArea.height != newClientArea.height;
} else {
changedX = changedY = changedH = true;
//changedX = changedY = changedW = changedH = true;
}
clientArea = newClientArea;
if (tvSWTCommon != null) {
tvSWTCommon.xAdj = -clientArea.x;
}
//System.out.println("CA=" + clientArea + " via " + Debug.getCompressedStackTrace());
boolean needRedraw = false;
if (changedY || changedH) {
visibleRowsChanged();
if (changedY && oldClientArea != null) {
Set<TableRowPainted> visibleRows = this.visibleRows;
if (visibleRows.size() > 0) {
if (canvasImage != null && !canvasImage.isDisposed() && !changedH) {
int yDiff = oldClientArea.y - newClientArea.y;
if (Math.abs(yDiff) < clientArea.height) {
boolean wasIn = in_swt_updateCanvasImage;
in_swt_updateCanvasImage = true;
try{
GC gc = new GC(canvasImage);
try{
Rectangle bounds = canvasImage.getBounds();
//System.out.println("moving y " + yDiff + ";cah=" + clientArea.height);
if (yDiff > 0) {
gc.copyArea(0, 0, bounds.width, bounds.height, 0, yDiff, false);
swt_paintCanvasImage(gc, new Rectangle(0, 0, 9999, yDiff));
gc.setClipping((Rectangle) null);
} else {
gc.copyArea(0, -yDiff, bounds.width, bounds.height , 0, 0, false);
int h = -yDiff;
TableRowPainted row = getLastVisibleRow();
if (row != null) {
//row.invalidate();
h += row.getHeight();
}
swt_paintCanvasImage(gc, new Rectangle(0, bounds.height - h, 9999, h));
gc.setClipping((Rectangle) null);
}
}finally{
gc.dispose();
}
}catch( Throwable e ){
// seen an exception here caused, I think, by canvasImage already being
// selected into a GC by code 'further down the stack'...
refreshTable = true;
}finally{
in_swt_updateCanvasImage = wasIn;
}
needRedraw = true;
} else {
refreshTable = true;
}
}
}
}
}
if (changedX) {
cHeaderArea.redraw();
}
Image newImage = canvasImage;
//List<TableRowSWT> visibleRows = getVisibleRows();
int h = 0;
synchronized (visibleRows_sync) {
TableRowPainted lastRow = getLastVisibleRow();
if (lastRow != null) {
h = lastRow.getDrawOffset().y - clientArea.y + lastRow.getHeight();
if (h < clientArea.height && lastRow.isExpanded()) {
TableRowCore[] subRows = lastRow.getSubRowsWithNull();
for (TableRowCore subRow : subRows) {
if (subRow == null) {
continue;
}
TableRowPainted subRowP = (TableRowPainted) subRow;
h += subRowP.getFullHeight();
if (h >= clientArea.height) {
break;
}
}
}
}
}
if (h < clientArea.height) {
h = clientArea.height;
}
int oldH = canvasImage == null || canvasImage.isDisposed() ? 0
: canvasImage.getBounds().height;
int oldW = canvasImage == null || canvasImage.isDisposed() ? 0
: canvasImage.getBounds().width;
if (canvasImage == null || oldW != w || h > oldH) {
//System.out.println("oldW=" + oldW + ";" + w+ ";h=" + h + ";" + oldH);
if (h <= 0 || clientArea.width <= 0) {
newImage = null;
} else {
newImage = new Image(shell.getDisplay(), w, h);
}
}
boolean canvasChanged = (canvasImage != newImage);
if (canvasChanged) {
Image oldImage = canvasImage;
canvasImage = newImage;
if (oldImage != null && !oldImage.isDisposed()) {
oldImage.dispose();
}
}
// paint event will handle any changedX or changedW
if (changedH || canvasChanged || refreshTable) {
//System.out.println(changedX + ";" + changedY + ";" + changedH + ";" + canvasChanged);
//System.out.println("Redraw " + Debug.getCompressedStackTrace());
// run refreshTable on SWT (this) thread to ensure rows have been
// refreshed for the updateCanvasImage call immediately after it
__refreshTable(false);
// refreshtable will call swt_updateCanvasImage for each visible row
if (canvasChanged) {
swt_updateCanvasImage(false);
}
}
// System.out.println("imgBounds = " + canvasImage.getBounds() + ";ca="
// + clientArea + ";" + composite.getClientArea() + ";h=" + h + ";oh="
// + oldH + " via " + Debug.getCompressedStackTrace(3));
if (needRedraw) {
cTable.redraw();
}
}
public void swt_updateCanvasImage(boolean immediateRedraw) {
if (canvasImage != null && !canvasImage.isDisposed()) {
swt_updateCanvasImage(canvasImage.getBounds(), immediateRedraw);
}
}
private boolean in_swt_updateCanvasImage = false;
protected void swt_updateCanvasImage(final Rectangle bounds, final boolean immediateRedraw) {
// no need to sync around in_swt_updateCanvasImage, we are assumed to always
// be on SWT thread and in_swt_updateCanvasImage is only used here
if (in_swt_updateCanvasImage) {
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
swt_updateCanvasImage(bounds, immediateRedraw);
}
});
return;
}
in_swt_updateCanvasImage = true;
try {
if (canvasImage == null || canvasImage.isDisposed() || bounds == null) {
return;
}
//System.out.println("UpdateCanvasImage " + bounds + "; via " + Debug.getCompressedStackTrace());
GC gc = new GC(canvasImage);
swt_paintCanvasImage(gc, bounds);
gc.dispose();
if (cTable != null && !cTable.isDisposed()) {
cTable.redraw(bounds.x - clientArea.x, bounds.y, bounds.width, bounds.height, false);
if (immediateRedraw) {
cTable.update();
}
}
if ( DEBUG_WITH_SHELL ){
if (sCanvasImage != null) {
sCanvasImage.getShell().setSize(canvasImage.getBounds().width, canvasImage.getBounds().height);
sCanvasImage.redraw(bounds.x, bounds.y, bounds.width, bounds.height, true);
sCanvasImage.update();
}
}
} finally {
in_swt_updateCanvasImage = false;
}
}
public Rectangle getClientArea() {
return clientArea;
}
public boolean isVisible() {
if (!Utils.isThisThreadSWT()) {
return isVisible;
}
boolean wasVisible = isVisible;
isVisible = cTable != null && !cTable.isDisposed() && cTable.isVisible()
&& !shell.getMinimized();
if (isVisible != wasVisible) {
visibleRowsChanged();
UISWTViewCore view = tvTabsCommon == null ? null
: tvTabsCommon.getActiveSubView();
if (isVisible) {
loopFactor = 0;
if (view != null) {
view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
}
} else {
if (view != null) {
view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
}
}
}
return isVisible;
}
public void removeAllTableRows() {
if (DEBUG_ROWCHANGE) {
debug("RemoveAlLRows");
}
super.removeAllTableRows();
synchronized (visibleRows_sync) {
visibleRows = new LinkedHashSet<TableRowPainted>();
}
setFocusedRow(null);
totalHeight = 0;
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (cTable == null || cTable.isDisposed()) {
return;
}
swt_fixupSize();
swt_updateCanvasImage(false);
if (DEBUG_ROWCHANGE) {
debug("RemoveAllRows done");
}
}
});
}
protected void swt_fixupSize() {
//debug("Set minSize to " + columnsWidth + "x" + totalHeight + ";ca=" + clientArea + ";" + Debug.getCompressedStackTrace());
boolean vBarValid = vBar != null && !vBar.isDisposed();
if (vBarValid) {
int tableSize = clientArea.height;
int max = totalHeight;
if (max < tableSize) {
vBar.setSelection(0);
vBar.setEnabled(false);
vBar.setVisible(false);
} else {
if (!vBar.isVisible()) {
vBar.setVisible(true);
vBar.setEnabled(true);
}
if (vBar.getMaximum() != max) {
vBar.setMaximum(max);
swt_vBarChanged();
}
vBar.setThumb(tableSize);
vBar.setPageIncrement(tableSize);
}
}
if (hBar != null && !hBar.isDisposed()) {
int tableSize = cTable.getSize().x;
int max = columnsWidth;
if (vBarValid && vBar.isVisible() && getScrollbarsMode() == SWT.NONE) {
int vBarW = vBar.getSize().x;
max += vBarW;
}
if (max < tableSize) {
hBar.setSelection(0);
hBar.setEnabled(false);
hBar.setVisible(false);
} else {
if (!hBar.isVisible()) {
hBar.setVisible(true);
hBar.setEnabled(true);
}
hBar.setValues(hBar.getSelection(), 0, max, tableSize, 50, tableSize);
}
if (vBarValid && hBar.isVisible()) {
int hBarW = getScrollbarsMode() == SWT.NONE ? hBar.getSize().y : 0;
vBar.setThumb(clientArea.height - hBarW);
vBar.setMaximum(totalHeight - hBarW);
vBar.setPageIncrement(vBar.getPageIncrement() - hBarW);
}
}
}
private int getScrollbarsMode() {
if (hasGetScrollBarMode) {
return cTable.getScrollbarsMode();
}
return SWT.NONE;
}
@Override
protected void uiChangeColumnIndicator() {
Utils.execSWTThread(new AERunnable() {
@Override
public void runSupport() {
if (cHeaderArea != null && !cHeaderArea.isDisposed()) {
cHeaderArea.redraw();
}
}
});
}
public TableColumnCore getTableColumnByOffset(int mouseX) {
int x = -clientArea.x;
TableColumnCore[] visibleColumns = getVisibleColumns();
for (TableColumnCore column : visibleColumns) {
int w = column.getWidth();
if (mouseX >= x && mouseX < x + w) {
return column;
}
x += w;
}
return null;
}
// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableRow(int, int, boolean)
public TableRowSWT getTableRow(int x, int y, boolean anyX) {
return (TableRowSWT) getRow(anyX ? 2 : x, clientArea.y + y);
}
@Override
public void setSelectedRows(TableRowCore[] newSelectionArray, boolean trigger) {
super.setSelectedRows(newSelectionArray, trigger);
boolean focusInSelection = false;
for (TableRowCore row : newSelectionArray) {
if (row == null) {
continue;
}
if (row.equals(focusedRow)) {
focusInSelection = true;
break;
}
}
if (!focusInSelection) {
setFocusedRow(newSelectionArray.length == 0 ? null : newSelectionArray[0]);
}
}
public void setRowSelected(final TableRowCore row, boolean selected,
boolean trigger) {
if (selected && !isSelected(row)) {
setFocusedRow(row);
}
super.setRowSelected(row, selected, trigger);
if (row instanceof TableRowSWT) {
((TableRowSWT) row).setWidgetSelected(selected);
}
}
public void editCell(TableColumnCore column, int row) {
//TODO
}
public boolean isDragging() {
return isDragging;
}
public TableViewSWTFilter<?> getSWTFilter() {
return (TableViewSWTFilter<?>) filter;
}
public void openFilterDialog() {
if (filter == null) {
return;
}
SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow();
entryWindow.initTexts("MyTorrentsView.dialog.setFilter.title", null,
"MyTorrentsView.dialog.setFilter.text", new String[] {
MessageText.getString(getTableID() + "View" + ".header")
});
entryWindow.setPreenteredText(filter.text, false);
entryWindow.prompt();
if (!entryWindow.hasSubmittedInput()) {
return;
}
String message = entryWindow.getSubmittedInput();
if (message == null) {
message = "";
}
setFilterText(message);
}
public boolean isSingleSelection() {
return !isMultiSelect;
}
public void expandColumns() {
//TODO
}
@Override
public void triggerTabViewsDataSourceChanged(boolean sendParent) {
if (tvTabsCommon != null) {
tvTabsCommon.triggerTabViewsDataSourceChanged(sendParent);
}
}
public TableViewSWT_TabsCommon getTabsCommon() {
return( tvTabsCommon );
}
@Override
public void uiSelectionChanged(final TableRowCore[] newlySelectedRows,
final TableRowCore[] deselectedRows) {
//System.out.println("Redraw " + Debug.getCompressedStackTrace());
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
for (TableRowCore row : deselectedRows) {
row.invalidate();
redrawRow((TableRowPainted) row, false);
}
for (TableRowCore row : newlySelectedRows) {
row.invalidate();
redrawRow((TableRowPainted) row, false);
}
}
});
}
public void delete() {
triggerLifeCycleListener(TableLifeCycleListener.EVENT_DESTROYED);
if (tvTabsCommon != null) {
tvTabsCommon.delete();
tvTabsCommon = null;
}
TableStructureEventDispatcher.getInstance(tableID).removeListener(this);
TableColumnManager tcManager = TableColumnManager.getInstance();
if (tcManager != null) {
tcManager.saveTableColumns(getDataSourceType(), tableID);
}
Utils.disposeSWTObjects(new Object[] {
cTable
});
cTable = null;
removeAllTableRows();
configMan.removeParameterListener("ReOrder Delay", this);
configMan.removeParameterListener("Graphics Update", this);
configMan.removeParameterListener("Table.extendedErase", this);
configMan.removeParameterListener("Table.headerHeight", this);
Colors.getInstance().removeColorsChangedListener(this);
super.delete();
MessageText.removeListener(this);
}
@Override
public void generate(IndentWriter writer) {
super.generate(writer);
if (tvTabsCommon != null) {
tvTabsCommon.generate(writer);
}
}
private Menu createMenu() {
if (!isMenuEnabled()) {
return null;
}
final Menu menu = new Menu(shell, SWT.POP_UP);
cTable.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
if (event.widget == cHeaderArea) {
menu.setData("inBlankArea", false);
menu.setData("isHeader", true);
} else {
boolean noRow = getTableRowWithCursor() == null;
menu.setData("inBlankArea", noRow);
menu.setData("isHeader", false);
}
Point pt = cHeaderArea.toControl(event.x, event.y);
menu.setData("column", getTableColumnByOffset(pt.x));
}
});
cHeaderArea.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
menu.setData("inBlankArea", false);
menu.setData("isHeader", true);
Point pt = cHeaderArea.toControl(event.x, event.y);
menu.setData("column", getTableColumnByOffset(pt.x));
}
});
MenuBuildUtils.addMaintenanceListenerForMenu(menu,
new MenuBuildUtils.MenuBuilder() {
public void buildMenu(Menu menu, MenuEvent menuEvent) {
Object oIsHeader = menu.getData("isHeader");
boolean isHeader = (oIsHeader instanceof Boolean)
? ((Boolean) oIsHeader).booleanValue() : false;
Object oInBlankArea = menu.getData("inBlankArea");
boolean inBlankArea = (oInBlankArea instanceof Boolean)
? ((Boolean) oInBlankArea).booleanValue() : false;
TableColumnCore column = (TableColumnCore) menu.getData("column");
if (isHeader) {
tvSWTCommon.fillColumnMenu(menu, column, false);
} else if (inBlankArea) {
tvSWTCommon.fillColumnMenu(menu, column, true);
} else {
tvSWTCommon.fillMenu(menu, column);
}
}
});
return menu;
}
public void showColumnEditor() {
if (tvSWTCommon != null) {
tvSWTCommon.showColumnEditor();
}
}
@Override
public TableRowCore getFocusedRow() {
return focusedRow;
}
public void setFocusedRow(TableRowCore row) {
TableRowPainted oldFocusedRow = focusedRow;
if (!(row instanceof TableRowPainted)) {
row = null;
}
focusedRow = (TableRowPainted) row;
if (focusedRow != null) {
if (focusedRow.isVisible()
&& focusedRow.getDrawOffset().y + focusedRow.getHeight() <= clientArea.y + clientArea.height
&& focusedRow.getDrawOffset().y >= clientArea.y) {
// redraw for BG color change
redrawRow(focusedRow, false);
} else {
showRow(focusedRow);
}
}
if (oldFocusedRow != null) {
redrawRow(oldFocusedRow, false);
}
}
public void showRow(final TableRowCore rowToShow) {
// scrollto
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (isDisposed()) {
return;
}
if (rowToShow.isVisible()) {
// draw offset is valid, use that to scroll
int y = ((TableRowPainted) rowToShow).getDrawOffset().y;
if (y + rowToShow.getHeight() > clientArea.y + clientArea.height) {
y -= (clientArea.height - rowToShow.getHeight());
}
vBar.setSelection(y);
swt_vBarChanged();
} else {
TableRowCore parentFocusedRow = rowToShow;
while (parentFocusedRow.getParentRowCore() != null) {
parentFocusedRow = parentFocusedRow.getParentRowCore();
}
TableRowCore[] rows = getRows();
int y = 0;
for (TableRowCore row : rows) {
if (row == parentFocusedRow) {
if (parentFocusedRow != rowToShow) {
y += row.getHeight();
TableRowCore[] subRowsWithNull = parentFocusedRow.getSubRowsWithNull();
for (TableRowCore subrow : subRowsWithNull) {
if (subrow == rowToShow) {
break;
}
y += ((TableRowPainted) subrow).getFullHeight();
}
}
break;
}
y += ((TableRowPainted) row).getFullHeight();
}
if (y + rowToShow.getHeight() > clientArea.y + clientArea.height) {
y -= (clientArea.height - rowToShow.getHeight());
}
// y now at top of focused row
vBar.setSelection(y);
swt_vBarChanged();
}
}
});
}
boolean qdRowHeightChanged = false;
public void rowHeightChanged(final TableRowCore row, int oldHeight,
int newHeight) {
synchronized (heightChangeSync) {
totalHeight += (newHeight - oldHeight);
//System.out.println("Height delta: " + (newHeight - oldHeight) + ";ttl=" + totalHeight);
if (qdRowHeightChanged) {
return;
}
qdRowHeightChanged = true;
}
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
synchronized (heightChangeSync) {
qdRowHeightChanged = false;
}
// if moving visibleRowsChanged(), make sure subrows being resized on
// add trigger work properly
visibleRowsChanged();
swt_fixupSize();
}
});
}
public void redrawTable() {
synchronized (TableViewPainted.this) {
if (redrawTableScheduled) {
return;
}
redrawTableScheduled = true;
}
visibleRowsChanged();
Utils.execSWTThreadLater(0, new AERunnable() {
public void runSupport() {
synchronized (TableViewPainted.this) {
redrawTableScheduled = false;
}
if (canvasImage != null && !canvasImage.isDisposed()) {
canvasImage.dispose();
canvasImage = null;
}
swt_calculateClientArea();
}
});
}
private String prettyIndex(TableRowCore row) {
String s = "" + row.getIndex();
if (row.getParentRowCore() != null) {
s = row.getParentRowCore().getIndex() + "." + s;
}
return s;
}
public void redrawRow(final TableRowPainted row, final boolean immediateRedraw) {
if (row == null) {
return;
}
if (TableRowPainted.DEBUG_ROW_PAINT) {
System.out.println(SystemTime.getCurrentTime() + "} redraw "
+ prettyIndex(row) + " scheduled via " + Debug.getCompressedStackTrace());
}
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (!isVisible || !row.isVisible()) {
return;
}
Rectangle bounds = row.getDrawBounds();
if (TableRowPainted.DEBUG_ROW_PAINT) {
System.out.println(SystemTime.getCurrentTime() + "] redraw "
+ prettyIndex(row) + " @ " + bounds);
}
if (bounds != null) {
Composite composite = getComposite();
if (composite != null && !composite.isDisposed()) {
int h = isLastRow(row) ? composite.getSize().y - bounds.y
: bounds.height;
//row.debug("isLastRow?" + isLastRow(row) + ";" + bounds + ";" + h);
swt_updateCanvasImage(new Rectangle(bounds.x, bounds.y, bounds.width, h), immediateRedraw);
}
}
}
});
}
public Object getSyncObject() {
return lock;
}
@Override
public boolean isTableSelected() {
TableView tv = SelectedContentManager.getCurrentlySelectedTableView();
return tv == this || (tv == null && isFocused);
}
}