📄 tableview.java
字号:
/*
* Created on 2004/Apr/18
*
* Copyright (C) 2004, 2005, 2006 Aelitis SAS, 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.
*
* 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 ( see the LICENSE file ).
*
* 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 46,603.30 euros,
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*/
package org.gudy.azureus2.ui.swt.views;
import java.util.*;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
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.config.impl.ConfigurationManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.util.Timer;
import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl;
import org.gudy.azureus2.ui.swt.Messages;
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.plugins.UISWTGraphic;
import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
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.TableCellImpl;
import org.gudy.azureus2.ui.swt.views.table.impl.TableRowImpl;
import org.gudy.azureus2.ui.swt.views.table.utils.*;
import org.gudy.azureus2.ui.swt.views.utils.VerticalAligner;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
import org.gudy.azureus2.plugins.ui.Graphic;
import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent;
import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
/**
* An IView with a sortable table. Handles composite/menu/table creation
* and management.
* <P>
* Usage of this class is rather haphazard. Sometimes, you can set a
* variable to change behavior. Other times you call a function. Some
* functions are meant for extending or implementing, others are meant as
* normal functions.
*
* @author Olivier (Original PeersView/MyTorrentsView/etc code)
* @author TuxPaper
* 2004/Apr/20: Remove need for tableItemToObject
* 2005/Oct/07: Virtual Table
* 2005/Nov/16: Moved TableSorter into TableView
*
* @todo Remove TableSorter.java, SortableTable.java from CVS
*
* @note From TableSorter.java:<br>
* <li>2004/Apr/20: Remove need for tableItemToObject (store object in tableItem.setData)
* <li>2004/May/11: Use Comparable instead of SortableItem
* <li>2004/May/14: moved from org.gudy.azureus2.ui.swt.utils
* <li>2005/Oct/10: v2307 : Sort SWT.VIRTUAL Tables, Column Indicator
*
* @future TableView should be split into two. One for non SWT functions, and
* the other extending the first, with extra SWT stuff.
*
* @future dataSourcesToRemove should be removed after a certain amount of time
* has passed. Currently, dataSourcesToRemove is processed every
* refresh IF the table is visible, or it is processed when we collect
* 20 items to remove.
*/
public class TableView
extends AbstractIView
implements ParameterListener,
ITableStructureModificationListener, ObfusticateImage
{
private final static LogIDs LOGID = LogIDs.GUI;
/** Helpfull output when trying to debug add/removal of rows */
public final static boolean DEBUGADDREMOVE = false;
/** Virtual Tables still a work in progress */
// Non-Virtual tables scroll faster with they keyboard
// Virtual tables don't flicker when updating a cell (Windows)
private final static boolean DISABLEVIRTUAL = !Constants.isWindows
|| SWT.getVersion() < 3138;
private final static boolean COLUMN_CLICK_DELAY = Constants.isOSX
&& SWT.getVersion() >= 3221 && SWT.getVersion() <= 3222;
private static final boolean DEBUG_SORTER = 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 long IMMEDIATE_ADDREMOVE_DELAY = 150;
private static final long IMMEDIATE_ADDREMOVE_MAXDELAY = 2000;
private static final long BREAKOFF_ADDTOMAP = 1000;
private static final long BREAKOFF_ADDROWSTOSWT = 800;
/** TableID (from {@link org.gudy.azureus2.plugins.ui.tables.TableManager})
* of the table this class is
* handling. Config settings are stored with the prefix of
* "Table.<i>TableID</i>"
*/
protected String sTableID;
/** Prefix for retrieving text from the properties file (MessageText)
* Typically <i>TableID</i> + "View"
*/
protected String sPropertiesPrefix;
/** Column name to sort on if user hasn't chosen one yet
*/
protected String sDefaultSortOn;
/** 1st column gap problem (Eclipse Bug 43910). Set to true when table is
* using TableItem.setImage
*/
private boolean bSkipFirstColumn;
private Point ptIconSize = null;
/** Basic (pre-defined) Column Definitions */
private TableColumnCore[] basicItems;
/** All Column Definitions. The array is not necessarily in column order */
private TableColumnCore[] tableColumns;
/** Composite for IView implementation */
private Composite mainComposite;
/** Composite that stores the table (sometimes the same as mainComposite) */
private Composite tableComposite;
/** Table for SortableTable implementation */
private Table table;
/** SWT style options for the creation of the Table */
protected int iTableStyle;
/** Whether the Table is Virtual */
private boolean bTableVirtual;
/** Context Menu */
private Menu menu;
/** Context Menu specific to the column the mouse was on */
private Menu menuThisColumn;
/** Link DataSource to their row in the table.
* key = DataSource
* value = TableRowCore
*/
private Map dataSourceToRow;
private AEMonitor dataSourceToRow_mon = new AEMonitor( "TableView:OTSI" );
private List sortedRows;
private AEMonitor sortedRows_mon = new AEMonitor( "TableView:sR" );
private AEMonitor sortColumn_mon = new AEMonitor( "TableView:sC" );
/** Sorting functions */
protected TableColumnCore sortColumn;
/** TimeStamp of when last sorted all the rows was */
private long lLastSortedOn;
/* position of mouse in table. Used for context menu. */
private int iMouseX = -1;
/** For updating GUI.
* Some UI objects get updating every X cycles (user configurable)
*/
protected int loopFactor;
/** How often graphic cells get updated
*/
protected int graphicsUpdate = configMan.getIntParameter("Graphics Update");
protected int reOrderDelay = configMan.getIntParameter("ReOrder Delay");
/** Check Column Widths every 10 seconds on Pre 3.0RC1 on OSX if view is active.
* Other OSes can capture column width changes automatically */
private int checkColumnWidthsEvery = (Constants.isOSX && SWT.getVersion() < 3054) ?
10000 / configMan.getIntParameter("GUI Refresh") :
0;
/**
* Cache of selected table items to bypass insufficient drawing on Mac OS X
*/
//private ArrayList oldSelectedItems;
/** We need to remember the order of the columns at the time we added them
* in case the user drags the columns around.
*/
private TableColumnCore[] columnsOrdered;
private ColumnMoveListener columnMoveListener = new ColumnMoveListener();
/** 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 Timer timerProcessDataSources = new Timer("Process Data Sources");
private TimerEvent timerEventProcessDS;
private boolean bReallyAddingDataSources = false;
/** TabViews */
public boolean bEnableTabViews = false;
/** TabViews */
private CTabFolder tabFolder;
/** TabViews */
private ArrayList tabViews = new ArrayList(1);
private int lastTopIndex = 0;
private int lastBottomIndex = -1;
protected IView[] coreTabViews = null;
private long lCancelSelectionTriggeredOn = -1;
// XXX Remove after column selection is no longered triggered on column resize (OSX)
private long lLastColumnResizeOn = -1;
/**
* 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 TableView(String _sTableID,
String _sPropertiesPrefix,
TableColumnCore[] _basicItems,
String _sDefaultSortOn,
int _iTableStyle) {
sTableID = _sTableID;
basicItems = _basicItems;
sPropertiesPrefix = _sPropertiesPrefix;
sDefaultSortOn = _sDefaultSortOn;
iTableStyle = _iTableStyle | SWT.V_SCROLL;
if (DISABLEVIRTUAL)
iTableStyle &= ~(SWT.VIRTUAL);
bTableVirtual = (iTableStyle & SWT.VIRTUAL) != 0;
dataSourceToRow = new HashMap();
sortedRows = new ArrayList();
}
/**
* Main Initializer. Table Style will be SWT.SINGLE | SWT.FULL_SELECTION
*
* @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
*/
public TableView(String _sTableID,
String _sPropertiesPrefix,
TableColumnCore[] _basicItems,
String _sDefaultSortOn) {
this(_sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn,
SWT.SINGLE | SWT.FULL_SELECTION | SWT.VIRTUAL);
}
private void initializeColumnDefs() {
// XXX Adding Columns only has to be done once per TableID.
// Doing it more than once won't harm anything, but it's a waste.
TableColumnManager tcManager = TableColumnManager.getInstance();
if (tcManager.getTableColumnCount(sTableID) != basicItems.length) {
for (int i = 0; i < basicItems.length; i++) {
tcManager.addColumn(basicItems[i]);
}
}
// fixup order
tcManager.ensureIntegrety(sTableID);
tableColumns = tcManager.getAllTableColumnCoreAsArray(sTableID);
}
// AbstractIView::initialize
public void initialize(Composite composite) {
composite.setRedraw(false);
mainComposite = createSashForm(composite);
menu = createMenu();
table = createTable(tableComposite);
initializeTable(table);
configMan.addParameterListener("Graphics Update", this);
configMan.addParameterListener("ReOrder Delay", this);
Colors.getInstance().addColorsChangedListener(this);
// So all TableView objects of the same TableID have the same columns,
// and column widths, etc
TableStructureEventDispatcher.getInstance(sTableID).addListener(this);
composite.setRedraw(true);
}
private Composite createSashForm(final Composite composite) {
if (!bEnableTabViews) {
tableComposite = createMainPanel(composite);
return tableComposite;
}
int iNumViews = coreTabViews == null ? 0 : coreTabViews.length;
UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
Map pluginViews = null;
if (uiFunctions != null) {
UISWTInstanceImpl pluginUI = uiFunctions.getSWTPluginInstanceImpl();
if (pluginUI != null) {
pluginViews = pluginUI.getViewListeners(sTableID);
if (pluginViews != null)
iNumViews += pluginViews.size();
}
}
if (iNumViews == 0) {
tableComposite = createMainPanel(composite);
return tableComposite;
}
FormData formData;
final Composite form = new Composite(composite, SWT.NONE);
FormLayout flayout = new FormLayout();
flayout.marginHeight = 0;
flayout.marginWidth = 0;
form.setLayout(flayout);
GridData gridData;
gridData = new GridData(GridData.FILL_BOTH);
form.setLayoutData(gridData);
// Create them in reverse order, so we can have the table auto-grow, and
// set the tabFolder's height manually
final int TABHEIGHT = 20;
tabFolder = new CTabFolder(form, SWT.TOP | SWT.BORDER);
tabFolder.setMinimizeVisible(true);
tabFolder.setTabHeight(TABHEIGHT);
final int iFolderHeightAdj = tabFolder.computeSize(SWT.DEFAULT, 0).y;
final Sash sash = new Sash(form, SWT.HORIZONTAL);
tableComposite = createMainPanel(form);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginHeight = 0;
layout.marginWidth = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -