1 /**
2  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
3  *
4  * Date: July 14, 2004
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details ( see the LICENSE file ).
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 package com.aelitis.azureus.ui.common.table.impl;
22 
23 import java.io.UnsupportedEncodingException;
24 import java.util.*;
25 
26 import org.gudy.azureus2.core3.config.COConfigurationManager;
27 import org.gudy.azureus2.core3.internat.MessageText;
28 import org.gudy.azureus2.core3.util.*;
29 
30 import com.aelitis.azureus.ui.UIFunctions;
31 import com.aelitis.azureus.ui.UIFunctionsManager;
32 import com.aelitis.azureus.ui.common.table.*;
33 
34 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
35 import org.gudy.azureus2.plugins.download.Download;
36 import org.gudy.azureus2.plugins.download.DownloadTypeComplete;
37 import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete;
38 import org.gudy.azureus2.plugins.peers.Peer;
39 import org.gudy.azureus2.plugins.sharing.ShareResource;
40 import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
41 import org.gudy.azureus2.plugins.ui.UIRuntimeException;
42 import org.gudy.azureus2.plugins.ui.config.Parameter;
43 import org.gudy.azureus2.plugins.ui.tables.*;
44 import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl;
45 
46 /**
47  * Table Column definition and modification routines.
48  * Implements both the plugin API and the core API.
49  * <P>
50  * A column is defined in relation to a table.  When one column is in
51  * multiple tables of different table ids, each table has it's own column
52  * instance
53  *
54  * @author TuxPaper
55  *
56  * @see com.aelitis.azureus.ui.common.table.impl.TableColumnManager
57  */
58 public class TableColumnImpl
59 	implements TableColumnCore
60 {
61 	private static final String CFG_SORTDIRECTION 		= "config.style.table.defaultSortOrder";
62 
63 	private static final String ATTRIBUTE_NAME_OVERIDE =  "tablecolumn.nameoverride";
64 
65 	private static UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
66 
67 	private static int
adjustPXForDPI( int px )68 	adjustPXForDPI(
69 		int	px )
70 	{
71 		if ( uiFunctions == null ){
72 
73 			return( px );
74 		}
75 
76 		return( uiFunctions.adjustPXForDPI( px ));
77 	}
78 
79 	/** Internal Name/ID of the column **/
80 	private String sName;
81 
82 	/** key of the displayed title for the column.  If null, uses default calc */
83 	private String sTitleLanguageKey = null;
84 
85 	private int iAlignment;
86 
87 	private int	iDefaultAlignment = -1;
88 
89 	private int iType;
90 
91 	private int iPosition;
92 
93 	private int iWidth;
94 
95 	private int iDefaultWidth;
96 
97 	private int iInterval;
98 
99 	private long lLastSortValueChange;
100 
101 	/** Table the column belongs to */
102 	private String sTableID;
103 
104 	private boolean bColumnAdded;
105 
106 	private boolean bCoreDataSource;
107 
108 	private TableCellInplaceEditorListener cellEditorListener;
109 
110 	private ArrayList<TableCellRefreshListener> cellRefreshListeners;
111 
112 	private ArrayList<TableCellAddedListener> cellAddedListeners;
113 
114 	private ArrayList<TableCellDisposeListener> cellDisposeListeners;
115 
116 	private ArrayList<TableCellToolTipListener> cellToolTipListeners;
117 
118 	private ArrayList<TableCellMouseListener> cellMouseListeners;
119 
120 	private ArrayList<TableCellMouseMoveListener> cellMouseMoveListeners;
121 
122 	private ArrayList<TableCellVisibilityListener> cellVisibilityListeners;
123 
124 	private ArrayList<TableCellClipboardListener> cellClipboardListeners;
125 
126 	private ArrayList<TableColumnExtraInfoListener> columnExtraInfoListeners;
127 
128 	private Map<String, List<Object>> mapOtherCellListeners;
129 
130 	private int iConsecutiveErrCount;
131 
132 	private ArrayList<TableContextMenuItem> menuItemsHeader;
133 
134 	private ArrayList<TableContextMenuItem> menuItemsColumn;
135 
136 	private boolean bObfusticateData;
137 
138 	protected AEMonitor this_mon = new AEMonitor("TableColumn");
139 
140 	private boolean bSortValueLive;
141 
142 	private long lStatsRefreshTotalTime;
143 
144 	private long lStatsRefreshCount = 0;
145 
146 	private long lStatsRefreshZeroCount = 0;
147 
148 	private boolean bSortAscending;
149 	private boolean bDefaultSortAscending;
150 
151 	private int iMinWidth = -1;
152 
153 	private int iMaxWidth = -1;
154 
155 	private boolean bVisible;
156 
157 	private boolean bMaxWidthAuto = false;
158 
159 	private boolean bWidthAuto;
160 
161 	private int iPreferredWidth;
162 
163 	private boolean bPreferredWidthAuto = true;
164 
165 	private int iPreferredWidthMax = -1;
166 
167 	private boolean auto_tooltip = false;
168 
169 	private Map userData;
170 
171 	private boolean removed;
172 
173 	private List<Class<?>> forPluginDataSourceTypes = new ArrayList<Class<?>>();
174 
175 	private String iconID;
176 
177 	private boolean firstLoad;
178 
179 	private boolean showOnlyImage;
180 
TableColumnImpl(String tableID, String columnID)181 	public TableColumnImpl(String tableID, String columnID) {
182 		init(tableID, columnID);
183 	}
184 
185 
init(String tableID, String columnID)186 	private void init(String tableID,
187 			String columnID) {
188 		sTableID = tableID;
189 		sName = columnID;
190 		iType = TYPE_TEXT_ONLY;
191 		iWidth = 50;
192 		iAlignment = ALIGN_LEAD;
193 		bColumnAdded = false;
194 		bCoreDataSource = false;
195 		iInterval = INTERVAL_INVALID_ONLY;
196 		iConsecutiveErrCount = 0;
197 		lLastSortValueChange = 0;
198 		bVisible = false;
199 		iMinWidth = adjustPXForDPI(16);
200 		iPosition = POSITION_INVISIBLE;
201 		int iSortDirection = COConfigurationManager.getIntParameter(CFG_SORTDIRECTION);
202 		bSortAscending = iSortDirection == 1 ? false : true;
203 	}
204 
initialize(int iAlignment, int iPosition, int iWidth, int iInterval)205 	public void initialize(int iAlignment, int iPosition, int iWidth,
206 			int iInterval) {
207 		if (bColumnAdded) {
208 			throw (new UIRuntimeException("Can't set properties. Column '" + sName
209 					+ " already added"));
210 		}
211 
212 		this.iAlignment = this.iDefaultAlignment =  iAlignment;
213 		setPosition(iPosition);
214 		this.iWidth = this.iDefaultWidth = adjustPXForDPI(iWidth);
215 		this.iMinWidth = adjustPXForDPI(16);
216 		this.iInterval = iInterval;
217 	}
218 
initialize(int iAlignment, int iPosition, int iWidth)219 	public void initialize(int iAlignment, int iPosition, int iWidth) {
220 		if (bColumnAdded) {
221 			throw (new UIRuntimeException("Can't set properties. Column '" + sName
222 					+ " already added"));
223 		}
224 
225 		this.iAlignment = this.iDefaultAlignment = iAlignment;
226 		setPosition(iPosition);
227 		this.iWidth = this.iDefaultWidth = adjustPXForDPI(iWidth);
228 		this.iMinWidth = adjustPXForDPI(16);
229 	}
230 
getName()231 	public String getName() {
232 		return sName;
233 	}
234 
getNameOverride()235 	public String getNameOverride()
236 	{
237 		return getUserDataString( ATTRIBUTE_NAME_OVERIDE );
238 	}
239 
setNameOverride( String name )240 	public void setNameOverride( String name )
241 	{
242 		setUserData( ATTRIBUTE_NAME_OVERIDE, name );
243 	}
244 
getTableID()245 	public String getTableID() {
246 		return sTableID;
247 	}
248 
setType(int type)249 	public void setType(int type) {
250 		if (bColumnAdded) {
251 			throw (new UIRuntimeException("Can't set properties. Column '" + sName
252 					+ " already added"));
253 		}
254 
255 		iType = type;
256 	}
257 
getType()258 	public int getType() {
259 		return iType;
260 	}
261 
setWidth(int realPXWidth)262 	public void setWidth(int realPXWidth) {
263 		setWidthPX(adjustPXForDPI(realPXWidth));
264 	}
265 
setWidthPX(int width)266 	public void setWidthPX(int width) {
267 		if (width == iWidth || width < 0) {
268 			return;
269 		}
270 
271 		if (iMinWidth > 0 && width < iMinWidth) {
272 			return;
273 		}
274 
275 		if (iMaxWidth > 0 && width > iMaxWidth) {
276 			if (width == iMaxWidth) {
277 				return;
278 			}
279 			width = iMaxWidth;
280 		}
281 
282 		if (iMinWidth < 0) {
283 			iMinWidth = width;
284 		}
285 
286 		//		if (iPreferredWidth <= 0) {
287 		//			iPreferredWidth = iWidth;
288 		//		}
289 
290 		int diff = width - iWidth;
291 		iWidth = width;
292 		if (iDefaultWidth == 0) {
293 			iDefaultWidth = width;
294 		}
295 
296 		if (bColumnAdded && bVisible) {
297 			triggerColumnSizeChange(diff);
298 		}
299 	}
300 
triggerColumnSizeChange(int diff)301 	public void triggerColumnSizeChange(int diff) {
302 		TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID);
303 		tsed.columnSizeChanged(this, diff);
304 		if (iType == TYPE_GRAPHIC) {
305 			invalidateCells();
306 		}
307 	}
308 
getWidth()309 	public int getWidth() {
310 		return iWidth;
311 	}
312 
setPosition(int position)313 	public void setPosition(int position) {
314 		if (bColumnAdded) {
315 			throw (new UIRuntimeException("Can't set properties. Column '" + sName
316 					+ " already added"));
317 		}
318 
319 		if (iPosition == POSITION_INVISIBLE && position != POSITION_INVISIBLE) {
320 			setVisible(true);
321 		}
322 		iPosition = position;
323 		if (position == POSITION_INVISIBLE) {
324 			setVisible(false);
325 		}
326 	}
327 
getPosition()328 	public int getPosition() {
329 		return iPosition;
330 	}
331 
setAlignment(int alignment)332 	public void setAlignment(int alignment) {
333 		/*
334 		if (bColumnAdded) {
335 			throw (new UIRuntimeException("Can't set properties. Column '" + sName
336 					+ " already added"));
337 		}
338 		*/
339 
340 		if (alignment == -1) {
341 			if (iDefaultAlignment != -1) {
342 				iAlignment = iDefaultAlignment;
343 			}
344 		} else {
345 			iAlignment = alignment;
346 
347 			if (iDefaultAlignment == -1) {
348 				iDefaultAlignment = alignment;
349 			}
350 		}
351 
352 		// Commented out because size hasn't changed!
353 		//if (bColumnAdded && bVisible) {
354 		//	triggerColumnSizeChange();
355 		//}
356 	}
357 
getAlignment()358 	public int getAlignment() {
359 		return iAlignment;
360 	}
361 
addCellRefreshListener(TableCellRefreshListener listener)362 	public void addCellRefreshListener(TableCellRefreshListener listener) {
363 		try {
364 			this_mon.enter();
365 
366 			if (cellRefreshListeners == null) {
367 				cellRefreshListeners = new ArrayList<TableCellRefreshListener>(1);
368 			}
369 
370 			cellRefreshListeners.add(listener);
371 			//System.out.println(this + " :: addCellRefreshListener " + listener + ". " + cellRefreshListeners.size());
372 
373 		} finally {
374 
375 			this_mon.exit();
376 		}
377 	}
378 
getCellRefreshListeners()379 	public List<TableCellRefreshListener> getCellRefreshListeners() {
380 		try {
381 			this_mon.enter();
382 
383 			if (cellRefreshListeners == null) {
384 				return (new ArrayList<TableCellRefreshListener>(0));
385 			}
386 
387 			return (new ArrayList<TableCellRefreshListener>(cellRefreshListeners));
388 
389 		} finally {
390 
391 			this_mon.exit();
392 		}
393 	}
394 
removeCellRefreshListener(TableCellRefreshListener listener)395 	public void removeCellRefreshListener(TableCellRefreshListener listener) {
396 		try {
397 			this_mon.enter();
398 
399 			if (cellRefreshListeners == null) {
400 				return;
401 			}
402 
403 			cellRefreshListeners.remove(listener);
404 		} finally {
405 			this_mon.exit();
406 		}
407 	}
408 
hasCellRefreshListener()409 	public boolean hasCellRefreshListener() {
410 		return cellRefreshListeners != null && cellRefreshListeners.size() > 0;
411 	}
412 
setRefreshInterval(int interval)413 	public void setRefreshInterval(int interval) {
414 		iInterval = interval;
415 	}
416 
getRefreshInterval()417 	public int getRefreshInterval() {
418 		return iInterval;
419 	}
420 
addCellAddedListener(TableCellAddedListener listener)421 	public void addCellAddedListener(TableCellAddedListener listener) {
422 		try {
423 			this_mon.enter();
424 
425 			if (cellAddedListeners == null) {
426 				cellAddedListeners = new ArrayList<TableCellAddedListener>(1);
427 			}
428 
429 			cellAddedListeners.add(listener);
430 
431 		} finally {
432 
433 			this_mon.exit();
434 		}
435 	}
436 
addCellOtherListener(String listenerID, Object listener)437 	public void addCellOtherListener(String listenerID, Object listener) {
438 		try {
439 			this_mon.enter();
440 
441 			if (mapOtherCellListeners == null) {
442 				mapOtherCellListeners = new HashMap<String, List<Object>>(1);
443 			}
444 
445 			List<Object> list = mapOtherCellListeners.get(listenerID);
446 			if (list == null) {
447 				list = new ArrayList<Object>(1);
448 				mapOtherCellListeners.put(listenerID, list);
449 			}
450 
451 			list.add(listener);
452 
453 		} finally {
454 
455 			this_mon.exit();
456 		}
457 	}
458 
removeCellOtherListener(String listenerID, Object l)459 	public void removeCellOtherListener(String listenerID, Object l) {
460 		try {
461 			this_mon.enter();
462 
463   		if (mapOtherCellListeners == null) {
464   			return;
465   		}
466 
467   		mapOtherCellListeners.remove(listenerID);
468 
469 		} finally {
470 
471 			this_mon.exit();
472 		}
473 
474 	}
475 
getCellOtherListeners(String listenerID)476 	public Object[] getCellOtherListeners(String listenerID) {
477 		if (mapOtherCellListeners == null) {
478 			return null;
479 		}
480 
481 		List<Object> list = mapOtherCellListeners.get(listenerID);
482 		if (list == null) {
483 			return null;
484 		}
485 		return list.toArray();
486 	}
487 
488 	// @see com.aelitis.azureus.ui.common.table.TableColumnCore#hasCellOtherListeners(java.lang.String)
hasCellOtherListeners(String listenerID)489 	public boolean hasCellOtherListeners(String listenerID) {
490 		return mapOtherCellListeners != null
491 				&& mapOtherCellListeners.get(listenerID) != null;
492 	}
493 
getCellAddedListeners()494 	public List getCellAddedListeners() {
495 		try {
496 			this_mon.enter();
497 
498 			if (cellAddedListeners == null) {
499 				return Collections.emptyList();
500 			}
501 
502 			return (new ArrayList(cellAddedListeners));
503 
504 		} finally {
505 
506 			this_mon.exit();
507 		}
508 	}
509 
removeCellAddedListener(TableCellAddedListener listener)510 	public void removeCellAddedListener(TableCellAddedListener listener) {
511 		try {
512 			this_mon.enter();
513 
514 			if (cellAddedListeners == null) {
515 				return;
516 			}
517 
518 			cellAddedListeners.remove(listener);
519 
520 		} finally {
521 
522 			this_mon.exit();
523 		}
524 	}
525 
addCellDisposeListener(TableCellDisposeListener listener)526 	public void addCellDisposeListener(TableCellDisposeListener listener) {
527 		try {
528 			this_mon.enter();
529 
530 			if (cellDisposeListeners == null) {
531 				cellDisposeListeners = new ArrayList<TableCellDisposeListener>(1);
532 			}
533 
534 			cellDisposeListeners.add(listener);
535 		} finally {
536 
537 			this_mon.exit();
538 		}
539 	}
540 
removeCellDisposeListener(TableCellDisposeListener listener)541 	public void removeCellDisposeListener(TableCellDisposeListener listener) {
542 		try {
543 			this_mon.enter();
544 
545 			if (cellDisposeListeners == null) {
546 				return;
547 			}
548 
549 			cellDisposeListeners.remove(listener);
550 		} finally {
551 
552 			this_mon.exit();
553 		}
554 	}
555 
addCellToolTipListener(TableCellToolTipListener listener)556 	public void addCellToolTipListener(TableCellToolTipListener listener) {
557 		try {
558 			this_mon.enter();
559 
560 			if (cellToolTipListeners == null) {
561 				cellToolTipListeners = new ArrayList<TableCellToolTipListener>(1);
562 			}
563 
564 			cellToolTipListeners.add(listener);
565 
566 		} finally {
567 			this_mon.exit();
568 		}
569 	}
570 
removeCellToolTipListener(TableCellToolTipListener listener)571 	public void removeCellToolTipListener(TableCellToolTipListener listener) {
572 		try {
573 			this_mon.enter();
574 
575 			if (cellToolTipListeners == null) {
576 				return;
577 			}
578 
579 			cellToolTipListeners.remove(listener);
580 		} finally {
581 			this_mon.exit();
582 		}
583 	}
584 
addCellMouseListener(TableCellMouseListener listener)585 	public void addCellMouseListener(TableCellMouseListener listener) {
586 		try {
587 			this_mon.enter();
588 
589 			if (cellMouseListeners == null) {
590 				cellMouseListeners = new ArrayList<TableCellMouseListener>(1);
591 			}
592 
593 			cellMouseListeners.add(listener);
594 
595 		} finally {
596 			this_mon.exit();
597 		}
598 	}
599 
removeCellMouseListener(TableCellMouseListener listener)600 	public void removeCellMouseListener(TableCellMouseListener listener) {
601 		try {
602 			this_mon.enter();
603 
604 			if (cellMouseListeners == null) {
605 				return;
606 			}
607 
608 			cellMouseListeners.remove(listener);
609 
610 		} finally {
611 			this_mon.exit();
612 		}
613 	}
614 
hasCellMouseMoveListener()615 	public boolean hasCellMouseMoveListener() {
616 		return cellMouseMoveListeners != null && cellMouseMoveListeners.size() > 0;
617 	}
618 
addCellMouseMoveListener(TableCellMouseMoveListener listener)619 	public void addCellMouseMoveListener(TableCellMouseMoveListener listener) {
620 		try {
621 			this_mon.enter();
622 
623 			if (cellMouseMoveListeners == null) {
624 				cellMouseMoveListeners = new ArrayList<TableCellMouseMoveListener>(1);
625 			}
626 
627 			cellMouseMoveListeners.add(listener);
628 
629 		} finally {
630 			this_mon.exit();
631 		}
632 	}
633 
removeCellMouseMoveListener(TableCellMouseMoveListener listener)634 	public void removeCellMouseMoveListener(TableCellMouseMoveListener listener) {
635 		try {
636 			this_mon.enter();
637 
638 			if (cellMouseMoveListeners == null) {
639 				return;
640 			}
641 
642 			cellMouseMoveListeners.remove(listener);
643 
644 		} finally {
645 			this_mon.exit();
646 		}
647 	}
648 
addCellClipboardListener(TableCellClipboardListener listener)649 	public void addCellClipboardListener(TableCellClipboardListener listener) {
650 		try {
651 			this_mon.enter();
652 
653 			if (cellClipboardListeners == null) {
654 				cellClipboardListeners = new ArrayList<TableCellClipboardListener>(1);
655 			}
656 
657 			cellClipboardListeners.add(listener);
658 
659 		} finally {
660 			this_mon.exit();
661 		}
662 	}
663 
removeCellClipboardListener(TableCellClipboardListener listener)664 	public void removeCellClipboardListener(TableCellClipboardListener listener) {
665 		try {
666 			this_mon.enter();
667 
668 			if (cellClipboardListeners == null) {
669 				return;
670 			}
671 
672 			cellClipboardListeners.remove(listener);
673 
674 		} finally {
675 			this_mon.exit();
676 		}
677 	}
678 
addCellVisibilityListener(TableCellVisibilityListener listener)679 	public void addCellVisibilityListener(TableCellVisibilityListener listener) {
680 		try {
681 			this_mon.enter();
682 
683 			if (cellVisibilityListeners == null) {
684 				cellVisibilityListeners = new ArrayList<TableCellVisibilityListener>(1);
685 			}
686 
687 			cellVisibilityListeners.add(listener);
688 
689 		} finally {
690 			this_mon.exit();
691 		}
692 	}
693 
removeCellVisibilityListener(TableCellVisibilityListener listener)694 	public void removeCellVisibilityListener(TableCellVisibilityListener listener) {
695 		try {
696 			this_mon.enter();
697 
698 			if (cellVisibilityListeners == null) {
699 				return;
700 			}
701 
702 			cellVisibilityListeners.remove(listener);
703 
704 		} finally {
705 			this_mon.exit();
706 		}
707 	}
708 
getColumnExtraInfoListeners()709 	public List<TableColumnExtraInfoListener> getColumnExtraInfoListeners() {
710 		try {
711 			this_mon.enter();
712 
713 			if (columnExtraInfoListeners == null) {
714 				return (new ArrayList<TableColumnExtraInfoListener>(0));
715 			}
716 
717 			return (new ArrayList<TableColumnExtraInfoListener>(columnExtraInfoListeners));
718 
719 		} finally {
720 
721 			this_mon.exit();
722 		}
723 	}
724 
addColumnExtraInfoListener(TableColumnExtraInfoListener listener)725 	public void addColumnExtraInfoListener(TableColumnExtraInfoListener listener) {
726 		try {
727 			this_mon.enter();
728 
729 			if (columnExtraInfoListeners == null) {
730 				columnExtraInfoListeners = new ArrayList<TableColumnExtraInfoListener>(1);
731 			}
732 
733 			columnExtraInfoListeners.add(listener);
734 
735 		} finally {
736 			this_mon.exit();
737 		}
738 	}
739 
removeColumnExtraInfoListener(TableColumnExtraInfoListener listener)740 	public void removeColumnExtraInfoListener(TableColumnExtraInfoListener listener) {
741 		try {
742 			this_mon.enter();
743 
744 			if (columnExtraInfoListeners == null) {
745 				return;
746 			}
747 
748 			columnExtraInfoListeners.remove(listener);
749 
750 		} finally {
751 			this_mon.exit();
752 		}
753 	}
754 
invalidateCells()755 	public void invalidateCells() {
756 		TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID);
757 		tsed.columnInvalidate(this);
758 	}
759 
invalidateCell(Object data_source)760 	public void invalidateCell(Object data_source) {
761 		TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID);
762 		tsed.cellInvalidate(this, data_source);
763 	}
764 
addListeners(Object listenerObject)765 	public void addListeners(Object listenerObject) {
766 		if (listenerObject instanceof TableCellDisposeListener) {
767 			addCellDisposeListener((TableCellDisposeListener) listenerObject);
768 		}
769 
770 		if (listenerObject instanceof TableCellRefreshListener) {
771 			addCellRefreshListener((TableCellRefreshListener) listenerObject);
772 		}
773 
774 		if (listenerObject instanceof TableCellToolTipListener) {
775 			addCellToolTipListener((TableCellToolTipListener) listenerObject);
776 		}
777 
778 		if (listenerObject instanceof TableCellAddedListener) {
779 			addCellAddedListener((TableCellAddedListener) listenerObject);
780 		}
781 
782 		if (listenerObject instanceof TableCellMouseMoveListener) {
783 			addCellMouseMoveListener((TableCellMouseMoveListener) listenerObject);
784 		}
785 
786 		if (listenerObject instanceof TableCellMouseListener) {
787 			addCellMouseListener((TableCellMouseListener) listenerObject);
788 		}
789 
790 		if (listenerObject instanceof TableCellVisibilityListener) {
791 			addCellVisibilityListener((TableCellVisibilityListener) listenerObject);
792 		}
793 
794 		if (listenerObject instanceof TableColumnExtraInfoListener) {
795 			addColumnExtraInfoListener((TableColumnExtraInfoListener) listenerObject);
796 		}
797 
798 		if (listenerObject instanceof TableCellClipboardListener) {
799 			addCellClipboardListener((TableCellClipboardListener) listenerObject);
800 		}
801 	}
802 
803 	/* Start of not plugin public API functions */
804 	//////////////////////////////////////////////
setColumnAdded()805 	public void setColumnAdded() {
806 		if (bColumnAdded) {
807 			return;
808 		}
809 		preAdd();
810 		bColumnAdded = true;
811 	}
812 
getColumnAdded()813 	public boolean getColumnAdded() {
814 		return bColumnAdded;
815 	}
816 
setUseCoreDataSource(boolean bCoreDataSource)817 	public void setUseCoreDataSource(boolean bCoreDataSource) {
818 		this.bCoreDataSource = bCoreDataSource;
819 	}
820 
getUseCoreDataSource()821 	public boolean getUseCoreDataSource() {
822 		return bCoreDataSource;
823 	}
824 
invokeCellRefreshListeners(TableCell cell, boolean fastRefresh)825 	public void invokeCellRefreshListeners(TableCell cell, boolean fastRefresh) throws Throwable {
826 		//System.out.println(this + " :: invokeCellRefreshListeners" + cellRefreshListeners);
827 		if (cellRefreshListeners == null || cell == null || cell.isDisposed()) {
828 			return;
829 		}
830 
831 		Throwable firstError = null;
832 
833 		//System.out.println(this + " :: invokeCellRefreshListeners" + cellRefreshListeners.size());
834 		for (int i = 0; i < cellRefreshListeners.size(); i++) {
835 
836 			TableCellRefreshListener l = cellRefreshListeners.get(i);
837 
838 			try {
839 				if(l instanceof TableCellLightRefreshListener)
840 					((TableCellLightRefreshListener)l).refresh(cell, fastRefresh);
841 				else
842 					l.refresh(cell);
843 			} catch (Throwable e) {
844 
845 				if (firstError == null) {
846 					firstError = e;
847 				}
848 				Debug.printStackTrace(e);
849 			}
850 		}
851 
852 		if (firstError != null) {
853 			throw firstError;
854 		}
855 	}
856 
invokeCellAddedListeners(TableCell cell)857 	public void invokeCellAddedListeners(TableCell cell) {
858 		if (cellAddedListeners == null) {
859 			return;
860 		}
861 		for (int i = 0; i < cellAddedListeners.size(); i++) {
862 
863 			try {
864 				((TableCellAddedListener) (cellAddedListeners.get(i))).cellAdded(cell);
865 
866 			} catch (Throwable e) {
867 
868 				Debug.printStackTrace(e);
869 			}
870 		}
871 	}
872 
invokeCellDisposeListeners(TableCell cell)873 	public void invokeCellDisposeListeners(TableCell cell) {
874 		if (cellDisposeListeners == null) {
875 			return;
876 		}
877 		for (int i = 0; i < cellDisposeListeners.size(); i++) {
878 			try {
879 				((TableCellDisposeListener) (cellDisposeListeners.get(i))).dispose(cell);
880 
881 			} catch (Throwable e) {
882 
883 				Debug.printStackTrace(e);
884 			}
885 		}
886 	}
887 
getClipboardText(TableCell cell)888 	public String getClipboardText(TableCell cell) {
889 		if (cellClipboardListeners == null) {
890 			return null;
891 		}
892 		for (int i = 0; i < cellClipboardListeners.size(); i++) {
893 			try {
894 				String text = ((TableCellClipboardListener) (cellClipboardListeners.get(i))).getClipboardText(cell);
895 
896 				if (text != null) {
897 					return text;
898 				}
899 
900 			} catch (Throwable e) {
901 
902 				Debug.printStackTrace(e);
903 			}
904 		}
905 
906 		return null;
907 	}
908 
invokeCellToolTipListeners(TableCellCore cell, int type)909 	public void invokeCellToolTipListeners(TableCellCore cell, int type) {
910 		if (cellToolTipListeners == null) {
911 			return;
912 		}
913 		if (type == TableCellCore.TOOLTIPLISTENER_HOVER) {
914 			for (int i = 0; i < cellToolTipListeners.size(); i++) {
915 				try {
916 					((TableCellToolTipListener) (cellToolTipListeners.get(i))).cellHover(cell);
917 				} catch (Throwable e) {
918 
919 					Debug.printStackTrace(e);
920 				}
921 			}
922 		} else {
923 			for (int i = 0; i < cellToolTipListeners.size(); i++) {
924 
925 				try {
926 					((TableCellToolTipListener) (cellToolTipListeners.get(i))).cellHoverComplete(cell);
927 				} catch (Throwable e) {
928 
929 					Debug.printStackTrace(e);
930 				}
931 			}
932 		}
933 	}
934 
invokeCellMouseListeners(TableCellMouseEvent event)935 	public void invokeCellMouseListeners(TableCellMouseEvent event) {
936 		ArrayList<?> listeners = event.eventType == TableCellMouseEvent.EVENT_MOUSEMOVE
937 				? cellMouseMoveListeners : this.cellMouseListeners;
938 		if (listeners == null) {
939 			return;
940 		}
941 
942 		for (int i = 0; i < listeners.size(); i++) {
943 			try {
944 				TableCellMouseListener l = (TableCellMouseListener) (listeners.get(i));
945 
946 				l.cellMouseTrigger(event);
947 
948 			} catch (Throwable e) {
949 				Debug.printStackTrace(e);
950 			}
951 		}
952 	}
953 
invokeCellVisibilityListeners(TableCellCore cell, int visibility)954 	public void invokeCellVisibilityListeners(TableCellCore cell, int visibility) {
955 		if (cellVisibilityListeners == null) {
956 			return;
957 		}
958 
959 		for (int i = 0; i < cellVisibilityListeners.size(); i++) {
960 			try {
961 				TableCellVisibilityListener l = (TableCellVisibilityListener) (cellVisibilityListeners.get(i));
962 
963 				l.cellVisibilityChanged(cell, visibility);
964 
965 			} catch (Throwable e) {
966 				Debug.printStackTrace(e);
967 			}
968 		}
969 	}
970 
setPositionNoShift(int position)971 	public void setPositionNoShift(int position) {
972 		//if (iPosition < 0 && position >= 0) {
973 		//	setVisible(true);
974 		//}
975 		iPosition = position;
976 		//if (position < 0) {
977 		//	setVisible(false);
978 		//}
979 	}
980 
getUserData(String key)981 	public Object getUserData(String key) {
982 		if(userData != null)
983 			return userData.get(key);
984 		return null;
985 	}
986 
getUserDataString(String key)987 	public String getUserDataString(String key) {
988 		if(userData != null) {
989 			Object o = userData.get(key);
990 			if (o instanceof String) {
991 				return (String) o;
992 			} else if (o instanceof byte[]) {
993 				try {
994 					String s = new String((byte[]) o, "utf-8");
995 					// write it back to the map, so we don't continually create new String objects
996 					userData.put(key, s);
997 					return( s );
998 				} catch (UnsupportedEncodingException e) {
999 				}
1000 			}
1001 		}
1002 		return null;
1003 	}
1004 
setUserData(String key, Object value)1005 	public void setUserData(String key, Object value) {
1006 		if(userData == null)
1007 			userData = new LightHashMap(2);
1008 		userData.put(key, value);
1009 	}
1010 
removeUserData(String key)1011 	public void removeUserData(String key) {
1012 		if(userData == null)
1013 			return;
1014 		userData.remove(key);
1015 		if(userData.size() < 1)
1016 			userData = null;
1017 	}
1018 
1019 	public void
remove()1020 	remove()
1021 	{
1022 		removed = true;
1023 
1024 		TableColumnManager.getInstance().removeColumns( new TableColumnCore[]{ this });
1025 
1026 		TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(sTableID);
1027 
1028 		for (Class<?> cla : forPluginDataSourceTypes) {
1029 			tsed.tableStructureChanged(true, cla);
1030 		}
1031 	}
1032 
1033 	public boolean
isRemoved()1034 	isRemoved()
1035 	{
1036 		return( removed );
1037 	}
1038 
loadSettings(Map mapSettings)1039 	public final void loadSettings(Map mapSettings) {
1040 		// Format: Key = [TableID].column.[columnname]
1041 		// Value[] = { visible, width, position, autotooltip, sortorder, userData, align }
1042 
1043 		String itemPrefix = "Column." + sName;
1044 		String oldItemPrefix = "Table." + sTableID + "." + sName;
1045 		Object object = mapSettings.get(itemPrefix);
1046 		Object[] list;
1047 		if (object instanceof List) {
1048 			list = ((List) object).toArray();
1049 		} else {
1050 			list = new String[0];
1051 		}
1052 
1053 		int pos = 0;
1054 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1055 			boolean vis = ((Number) list[pos]).intValue() == 1;
1056 			setVisible(vis);
1057 		}
1058 
1059 		pos++;
1060 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1061 			int position = ((Number) list[pos]).intValue();
1062 			setPositionNoShift(position);
1063 		} else {
1064 			int position = COConfigurationManager.getIntParameter(oldItemPrefix + ".position",
1065 					iPosition);
1066 			if (iPosition == POSITION_INVISIBLE && position != POSITION_INVISIBLE) {
1067 				setVisible(true);
1068 			}
1069 			setPositionNoShift(position);
1070 			if (position == POSITION_INVISIBLE) {
1071 				setVisible(false);
1072 			}
1073 		}
1074 
1075 		pos++;
1076 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1077 			int width = ((Number) list[pos]).intValue();
1078 			setWidthPX(width);
1079 		} else {
1080 			String key = oldItemPrefix + ".width";
1081 			if (COConfigurationManager.hasParameter(key, true)) {
1082   			setWidth(COConfigurationManager.getIntParameter(key));
1083 			}
1084 		}
1085 
1086 		pos++;
1087 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1088 			boolean autoTooltip = ((Number) list[pos]).intValue() == 1;
1089 			setAutoTooltip(autoTooltip);
1090 		} else {
1091 			setAutoTooltip(COConfigurationManager.getBooleanParameter(oldItemPrefix
1092 					+ ".auto_tooltip", auto_tooltip));
1093 		}
1094 
1095 		pos++;
1096 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1097 			int sortOrder = ((Number) list[pos]).intValue();
1098 			if (sortOrder >= 0) {
1099 				// dont call setSordOrder, since it will change lLastSortValueChange
1100 				// which we shouldn't do if we aren't the sorting column
1101 				bSortAscending = sortOrder == 1;
1102 			}
1103 		}else{
1104 			bSortAscending = bDefaultSortAscending;
1105 		}
1106 
1107 		pos++;
1108 		if (list.length >= (pos + 1) && (list[pos] instanceof Map)) {
1109 			Map loadedUserData = (Map)list[pos];
1110 			if (userData == null || userData.size() == 0) {
1111 				userData = loadedUserData;
1112 			} else {
1113 				for (Object key : loadedUserData.keySet()) {
1114 					userData.put(key, loadedUserData.get(key));
1115 				}
1116 			}
1117 		}
1118 		pos++;
1119 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
1120 			int align = ((Number) list[pos]).intValue();
1121 			setAlignment( align );
1122 		}
1123 		firstLoad = list.length == 0;
1124 		postConfigLoad();
1125 	}
1126 
isFirstLoad()1127 	public boolean isFirstLoad() {
1128 		return firstLoad;
1129 	}
1130 
1131 	/* (non-Javadoc)
1132 	 * @see org.gudy.azureus2.plugins.ui.tables.TableColumn#postLoad()
1133 	 */
postConfigLoad()1134 	public void postConfigLoad() {}
1135 
preAdd()1136 	public void preAdd() {}
1137 
preConfigSave()1138 	public void preConfigSave() {}
1139 
saveSettings(Map mapSettings)1140 	public final void saveSettings(Map mapSettings) {
1141 		preConfigSave();
1142 
1143 		if (mapSettings == null) {
1144 			mapSettings = TableColumnManager.getInstance().getTableConfigMap(sTableID);
1145 			if (mapSettings == null) {
1146 				return;
1147 			}
1148 		}
1149 		String sItemPrefix = "Column." + sName;
1150 		mapSettings.put(sItemPrefix, Arrays.asList(new Object[] {
1151 			new Integer(bVisible ? 1 : 0),
1152 			new Integer(iPosition),
1153 			new Integer(iWidth),
1154 			new Integer(auto_tooltip ? 1 : 0),
1155 			new Integer(lLastSortValueChange == 0 ? -1 : (bSortAscending ? 1 : 0)),
1156 			userData != null ? userData : Collections.EMPTY_MAP,
1157 			new Integer(iAlignment == iDefaultAlignment ? -1 : iAlignment)
1158 		}));
1159 		// cleanup old config
1160 		sItemPrefix = "Table." + sTableID + "." + sName;
1161 		if (COConfigurationManager.hasParameter(sItemPrefix + ".width", true)) {
1162 			COConfigurationManager.removeParameter(sItemPrefix + ".position");
1163 			COConfigurationManager.removeParameter(sItemPrefix + ".width");
1164 			COConfigurationManager.removeParameter(sItemPrefix + ".auto_tooltip");
1165 		}
1166 	}
1167 
getTitleLanguageKey()1168 	public String getTitleLanguageKey() {
1169 		return( getTitleLanguageKey( true ));
1170 	}
1171 
getTitleLanguageKey( boolean with_renames )1172 	public String getTitleLanguageKey( boolean with_renames ) {
1173 		try {
1174 			this_mon.enter();
1175 
1176 			if ( with_renames ){
1177 				String name_override = getNameOverride();
1178 
1179 				if ( name_override != null ){
1180 
1181 					return( "!" + name_override + "!" );
1182 				}
1183 			}
1184 
1185 			if (sTitleLanguageKey == null) {
1186 				if (MessageText.keyExists(sTableID + ".column." + sName)) {
1187 					sTitleLanguageKey = sTableID + ".column." + sName;
1188 					return sTitleLanguageKey;
1189 				}
1190 
1191 				String sKeyPrefix;
1192 				// Support "Old Style" language keys, which have a prefix of TableID + "View."
1193 				// Also, "MySeeders" is actually stored in "MyTorrents"..
1194 				sKeyPrefix = (sTableID.equals(TableManager.TABLE_MYTORRENTS_COMPLETE)
1195 						? TableManager.TABLE_MYTORRENTS_INCOMPLETE : sTableID)
1196 						+ "View.";
1197 				if (MessageText.keyExists(sKeyPrefix + sName)) {
1198 					sTitleLanguageKey = sKeyPrefix + sName;
1199 					return sTitleLanguageKey;
1200 				}
1201 
1202 				// The "all peers" view should just share the same peer columns, so reuse them.
1203 				if (sTableID.equals(TableManager.TABLE_ALL_PEERS)) {
1204 					sKeyPrefix = TableManager.TABLE_TORRENT_PEERS + ".column.";
1205 					if (MessageText.keyExists(sKeyPrefix + sName)) {
1206 						sTitleLanguageKey = sKeyPrefix + sName;
1207 						return sTitleLanguageKey;
1208 					}
1209 
1210 					// Or try "PeersView".
1211 					sKeyPrefix = "PeersView.";
1212 					if (MessageText.keyExists(sKeyPrefix + sName)) {
1213 						sTitleLanguageKey = sKeyPrefix + sName;
1214 						return sTitleLanguageKey;
1215 					}
1216 				}
1217 
1218 				// Try a generic one of "TableColumn." + columnid
1219 				sKeyPrefix = "TableColumn.header.";
1220 				if (MessageText.keyExists(sKeyPrefix + sName)) {
1221 					sTitleLanguageKey = sKeyPrefix + sName;
1222 					return sTitleLanguageKey;
1223 				}
1224 
1225 				// another "Old Style"
1226 				// 99% sure this can be removed now, but why risk it..
1227 				sKeyPrefix = "MyTorrentsView." + sName;
1228 				//System.out.println(sKeyPrefix + ";" + MessageText.getString(sKeyPrefix));
1229 				if (MessageText.keyExists(sKeyPrefix)) {
1230 					sTitleLanguageKey = sKeyPrefix;
1231 					return sTitleLanguageKey;
1232 				}
1233 
1234 				sTitleLanguageKey = "!" + sName + "!";
1235 			}
1236 			return sTitleLanguageKey;
1237 		} finally {
1238 
1239 			this_mon.exit();
1240 		}
1241 	}
1242 
getConsecutiveErrCount()1243 	public int getConsecutiveErrCount() {
1244 		return iConsecutiveErrCount;
1245 	}
1246 
setConsecutiveErrCount(int iCount)1247 	public void setConsecutiveErrCount(int iCount) {
1248 		iConsecutiveErrCount = iCount;
1249 	}
1250 
removeContextMenuItem(TableContextMenuItem menuItem)1251 	public void removeContextMenuItem(TableContextMenuItem menuItem) {
1252 		if (menuItemsColumn != null) {
1253 			menuItemsColumn.remove(menuItem);
1254 		}
1255 		if (menuItemsHeader != null) {
1256 			menuItemsHeader.remove(menuItem);
1257 		}
1258 	}
1259 
1260 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#addContextMenuItem(java.lang.String, int)
addContextMenuItem(String key)1261 	public TableContextMenuItem addContextMenuItem(String key) {
1262 		return addContextMenuItem(key, MENU_STYLE_COLUMN_DATA);
1263 	}
1264 
addContextMenuItem(String key, int menuStyle)1265 	public TableContextMenuItem addContextMenuItem(String key, int menuStyle) {
1266 		ArrayList<TableContextMenuItem> menuItems;
1267 		if (menuStyle == MENU_STYLE_COLUMN_DATA) {
1268 			if (menuItemsColumn == null) {
1269 				menuItemsColumn = new ArrayList<TableContextMenuItem>();
1270 			}
1271 			menuItems = menuItemsColumn;
1272 		} else {
1273 			if (menuItemsHeader == null) {
1274 				menuItemsHeader = new ArrayList<TableContextMenuItem>();
1275 			}
1276 			menuItems = menuItemsHeader;
1277 		}
1278 
1279 		// Hack.. should be using our own implementation..
1280 		TableContextMenuItemImpl item = new TableContextMenuItemImpl(null,"", key);
1281 		menuItems.add(item);
1282 		return item;
1283 	}
1284 
getContextMenuItems(int menuStyle)1285 	public TableContextMenuItem[] getContextMenuItems(int menuStyle) {
1286 		ArrayList<TableContextMenuItem> menuItems;
1287 		if (menuStyle == MENU_STYLE_COLUMN_DATA) {
1288 			menuItems = menuItemsColumn;
1289 		} else {
1290 			menuItems = menuItemsHeader;
1291 		}
1292 
1293 		if (menuItems == null) {
1294 			return new TableContextMenuItem[0];
1295 		}
1296 
1297 		return menuItems.toArray(new TableContextMenuItem[0]);
1298 	}
1299 
isObfusticated()1300 	public boolean isObfusticated() {
1301 		return bObfusticateData;
1302 	}
1303 
setObfustication(boolean hideData)1304 	public void setObfustication(boolean hideData) {
1305 		bObfusticateData = hideData;
1306 	}
1307 
getLastSortValueChange()1308 	public long getLastSortValueChange() {
1309 		if (bSortValueLive) {
1310 			return SystemTime.getCurrentTime();
1311 		}
1312 		return lLastSortValueChange;
1313 	}
1314 
setLastSortValueChange(long lastSortValueChange)1315 	public void setLastSortValueChange(long lastSortValueChange) {
1316 		//System.out.println(getName() + "] setlastSortValueChange via " + Debug.getCompressedStackTrace());
1317 		lLastSortValueChange = lastSortValueChange;
1318 	}
1319 
isSortValueLive()1320 	public boolean isSortValueLive() {
1321 		return bSortValueLive;
1322 	}
1323 
setSortValueLive(boolean live)1324 	public void setSortValueLive(boolean live) {
1325 		//		if (live && !bSortValueLive) {
1326 		//			System.out.println("Setting " + sTableID + ": " + sName + " to live sort value");
1327 		//		}
1328 		bSortValueLive = live;
1329 	}
1330 
addRefreshTime(long ms)1331 	public void addRefreshTime(long ms) {
1332 		if (ms == 0) {
1333 			lStatsRefreshZeroCount++;
1334 		} else {
1335 			lStatsRefreshTotalTime += ms;
1336 			lStatsRefreshCount++;
1337 		}
1338 	}
1339 
generateDiagnostics(IndentWriter writer)1340 	public void generateDiagnostics(IndentWriter writer) {
1341 		writer.println("Column " + sTableID + ":" + sName
1342 				+ (bSortValueLive ? " (Live Sort)" : ""));
1343 		try {
1344 			writer.indent();
1345 
1346 			if (lStatsRefreshCount > 0) {
1347 				writer.println("Avg refresh time (" + lStatsRefreshCount
1348 						+ " samples): " + (lStatsRefreshTotalTime / lStatsRefreshCount)
1349 						+ " (" + lStatsRefreshZeroCount
1350 						+ " zero ms refreshes not included)");
1351 			}
1352 			writer.println("Listeners: refresh="
1353 					+ getListCountString(cellRefreshListeners) + "; dispose="
1354 					+ getListCountString(cellDisposeListeners) + "; mouse="
1355 					+ getListCountString(cellMouseListeners) + "; mm="
1356 					+ getListCountString(cellMouseMoveListeners) + "; vis="
1357 					+ getListCountString(cellVisibilityListeners) + "; added="
1358 					+ getListCountString(cellAddedListeners) + "; tooltip="
1359 					+ getListCountString(cellToolTipListeners));
1360 
1361 			writer.println("lLastSortValueChange=" + lLastSortValueChange);
1362 		} catch (Exception e) {
1363 		} finally {
1364 			writer.exdent();
1365 		}
1366 	}
1367 
getListCountString(List<?> l)1368 	private String getListCountString(List<?> l) {
1369 		if (l == null) {
1370 			return "-0";
1371 		}
1372 		return "" + l.size();
1373 	}
1374 
setTableID(String tableID)1375 	public void setTableID(String tableID) {
1376 		sTableID = tableID;
1377 	}
1378 
1379 	// @see java.util.Comparator#compare(T, T)
compare(Object arg0, Object arg1)1380 	public int compare(Object arg0, Object arg1) {
1381 		TableCellCore cell0 = ((TableRowCore) arg0).getTableCellCore(sName);
1382 		TableCellCore cell1 = ((TableRowCore) arg1).getTableCellCore(sName);
1383 
1384 		Comparable c0 = (cell0 == null) ? "" : cell0.getSortValue();
1385 		Comparable c1 = (cell1 == null) ? "" : cell1.getSortValue();
1386 
1387 		// Put nulls and empty strings at bottom.
1388 		boolean c0_is_null = (c0 == null || c0.equals(""));
1389 		boolean c1_is_null = (c1 == null || c1.equals(""));
1390 		if (c1_is_null)  {
1391 			return (c0_is_null) ? 0 : -1;
1392 		}
1393 		else if (c0_is_null) {
1394 			return 1;
1395 		}
1396 
1397 		try {
1398 			boolean c0isString = c0 instanceof String;
1399 			boolean c1isString = c1 instanceof String;
1400 			if (c0isString && c1isString) {
1401 				if (bSortAscending) {
1402 					return ((String) c0).compareToIgnoreCase((String) c1);
1403 				}
1404 
1405 				return ((String) c1).compareToIgnoreCase((String) c0);
1406 			}
1407 
1408 			int val;
1409 			if (c0isString && !c1isString) {
1410 				val = -1;
1411 			} else if (c1isString && !c0isString) {
1412 				val = 1;
1413 			} else {
1414 				val = c1.compareTo(c0);
1415 			}
1416 			return bSortAscending ? -val : val;
1417 		} catch (ClassCastException e) {
1418 			int c0_index = (cell0 == null) ? -999 : cell0.getTableRowCore().getIndex();
1419 			int c1_index = (cell1 == null) ? -999 : cell1.getTableRowCore().getIndex();
1420 			System.err.println("Can't compare " + c0.getClass().getName() + "("
1421 					+ c0.toString() + ") from row #" + c0_index
1422 					+ " to " + c1.getClass().getName() + "(" + c1.toString()
1423 					+ ") from row #" + c1_index
1424 					+ " while sorting column " + sName);
1425 			e.printStackTrace();
1426 			return 0;
1427 		}
1428 	}
1429 
1430 	/**
1431 	 * @param bAscending The bAscending to set.
1432 	 */
setSortAscending(boolean bAscending)1433 	public void setSortAscending(boolean bAscending) {
1434 		if (this.bSortAscending == bAscending) {
1435 			return;
1436 		}
1437 		setLastSortValueChange(SystemTime.getCurrentTime());
1438 
1439 		this.bSortAscending = bAscending;
1440 	}
1441 
1442 	/**
1443 	 * @return Returns the bAscending.
1444 	 */
isSortAscending()1445 	public boolean isSortAscending() {
1446 		return bSortAscending;
1447 	}
1448 
setDefaultSortAscending( boolean bAscending )1449 	public void setDefaultSortAscending( boolean bAscending ){
1450 		bDefaultSortAscending = bAscending;
1451 		if ( isFirstLoad()){
1452 			bSortAscending = bAscending;
1453 		}
1454 	}
1455 
1456 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getMinWidth()
getMinWidth()1457 	public int getMinWidth() {
1458 		if (iMinWidth < 0) {
1459 			return iWidth;
1460 		}
1461 
1462 		return iMinWidth;
1463 	}
1464 
1465 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMinWidth(int)
setMinWidth(int minwidth)1466 	public void setMinWidth(int minwidth) {
1467 		// :(
1468 		minwidth = adjustPXForDPI(minwidth);
1469 		if (minwidth > iMaxWidth && iMaxWidth >= 0) {
1470 			iMaxWidth = minwidth;
1471 		}
1472 		if (iPreferredWidth > 0 && iPreferredWidth < minwidth) {
1473 			iPreferredWidth = minwidth;
1474 		}
1475 		iMinWidth = minwidth;
1476 		if (iWidth < minwidth) {
1477 			setWidthPX(minwidth);
1478 		}
1479 	}
1480 
1481 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getMaxWidth()
getMaxWidth()1482 	public int getMaxWidth() {
1483 		return iMaxWidth;
1484 	}
1485 
1486 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMaxWidth(int)
setMaxWidth(int maxwidth)1487 	public void setMaxWidth(int maxwidth) {
1488 		// :(
1489 		maxwidth = adjustPXForDPI(maxwidth);
1490 		if (maxwidth >= 0 && maxwidth < iMinWidth) {
1491 			iMinWidth = maxwidth;
1492 		}
1493 		if (iPreferredWidth > maxwidth) {
1494 			iPreferredWidth = maxwidth;
1495 		}
1496 		iMaxWidth = maxwidth;
1497 		if (maxwidth >= 0 && iWidth > iMaxWidth) {
1498 			setWidthPX(maxwidth);
1499 		}
1500 	}
1501 
1502 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setWidthLimits(int, int)
setWidthLimits(int min, int max)1503 	public void setWidthLimits(int min, int max) {
1504 		setMinWidth(min);
1505 		setMaxWidth(max);
1506 	}
1507 
1508 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isVisible()
isVisible()1509 	public boolean isVisible() {
1510 		return bVisible;
1511 	}
1512 
1513 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setVisible(boolean)
setVisible(boolean visible)1514 	public void setVisible(boolean visible) {
1515 		if (bVisible == visible) {
1516 			return;
1517 		}
1518 
1519 		//System.out.println("set " + sTableID + "/" + sName + " to " + visible
1520 		//		+ " via " + Debug.getCompressedStackTrace());
1521 
1522 		bVisible = visible;
1523 		if (bVisible && iPosition == POSITION_INVISIBLE) {
1524 			TableColumnCore[] allColumns = TableColumnManager.getInstance().getAllTableColumnCoreAsArray(
1525 					null, sTableID);
1526 			iPosition = 0;
1527 			for (TableColumnCore tableColumnCore : allColumns) {
1528 				if (tableColumnCore.getPosition() > iPosition) {
1529 					iPosition = tableColumnCore.getPosition() + 1;
1530 				}
1531 			}
1532 		}
1533 		invalidateCells();
1534 	}
1535 
1536 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isMaxWidthAuto()
isMaxWidthAuto()1537 	public boolean isMaxWidthAuto() {
1538 		return bMaxWidthAuto;
1539 	}
1540 
1541 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMaxWidthAuto(boolean)
setMaxWidthAuto(boolean automaxwidth)1542 	public void setMaxWidthAuto(boolean automaxwidth) {
1543 		bMaxWidthAuto = automaxwidth;
1544 	}
1545 
1546 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isMinWidthAuto()
isMinWidthAuto()1547 	public boolean isMinWidthAuto() {
1548 		return bWidthAuto;
1549 	}
1550 
1551 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setMinWidthAuto(boolean)
setMinWidthAuto(boolean autominwidth)1552 	public void setMinWidthAuto(boolean autominwidth) {
1553 		bWidthAuto = autominwidth;
1554 	}
1555 
1556 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getPreferredWidth()
getPreferredWidth()1557 	public int getPreferredWidth() {
1558 		return iPreferredWidth;
1559 	}
1560 
1561 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setPreferredWidthAuto(boolean)
setPreferredWidthAuto(boolean auto)1562 	public void setPreferredWidthAuto(boolean auto) {
1563 		bPreferredWidthAuto = auto;
1564 	}
1565 
1566 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#isPreferredWidthAuto()
isPreferredWidthAuto()1567 	public boolean isPreferredWidthAuto() {
1568 		return bPreferredWidthAuto;
1569 	}
1570 
1571     //  dead
setPreferredWidthMax(int maxprefwidth)1572 	public void setPreferredWidthMax(int maxprefwidth) {
1573 		iPreferredWidthMax = maxprefwidth;
1574 		if (iPreferredWidth > iPreferredWidthMax) {
1575 			setPreferredWidth(maxprefwidth);
1576 		}
1577 	}
1578 
1579     //  dead
getPreferredWidthMax()1580 	public int getPreferredWidthMax() {
1581 		return iPreferredWidthMax;
1582 	}
1583 
1584 	// @see org.gudy.azureus2.plugins.ui.tables.TableColumn#setPreferredWidth(int)
setPreferredWidth(int width)1585 	public void setPreferredWidth(int width) {
1586 		if (iPreferredWidthMax > 0 && width > iPreferredWidthMax) {
1587 			width = iPreferredWidthMax;
1588 		}
1589 
1590 		if (width < iMinWidth) {
1591 			iPreferredWidth = iMinWidth;
1592 		} else if (iMaxWidth > 0 && width > iMaxWidth) {
1593 			iPreferredWidth = iMaxWidth;
1594 		} else {
1595 			iPreferredWidth = width;
1596 		}
1597 
1598 		// Commented out because size hasn't changed!
1599 		//if (bColumnAdded && bVisible) {
1600 		//	triggerColumnSizeChange();
1601 		//}
1602 	}
1603 
setAutoTooltip(boolean auto_tooltip)1604 	public void setAutoTooltip(boolean auto_tooltip) {
1605 		this.auto_tooltip = auto_tooltip;
1606 	}
1607 
doesAutoTooltip()1608 	public boolean doesAutoTooltip() {
1609 		return this.auto_tooltip;
1610 	}
1611 
setInplaceEditorListener(TableCellInplaceEditorListener l)1612 	public void setInplaceEditorListener(TableCellInplaceEditorListener l) {
1613 		cellEditorListener = l;
1614 	}
1615 
hasInplaceEditorListener()1616 	public boolean hasInplaceEditorListener() {
1617 		return cellEditorListener != null;
1618 	}
1619 
getInplaceEditorListener()1620 	public TableCellInplaceEditorListener getInplaceEditorListener() {
1621 		return cellEditorListener;
1622 	}
1623 
getForDataSourceTypes()1624 	public Class[] getForDataSourceTypes() {
1625 		if (forPluginDataSourceTypes.isEmpty()) {
1626 			// Guess forPluginDataSourceType based on tableID
1627 			Class<?> forPluginDataSourceType = null;
1628 			if (TableManager.TABLE_MYTORRENTS_ALL_BIG.equals(sTableID)
1629 					|| TableManager.TABLE_MYTORRENTS_UNOPENED.equals(sTableID)
1630 					|| TableManager.TABLE_MYTORRENTS_UNOPENED_BIG.equals(sTableID)) {
1631 				forPluginDataSourceType = Download.class;
1632 			} else if (TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG.equals(sTableID)
1633 					|| TableManager.TABLE_MYTORRENTS_INCOMPLETE.equals(sTableID)) {
1634 				forPluginDataSourceType = DownloadTypeIncomplete.class;
1635 			} else if (TableManager.TABLE_MYTORRENTS_COMPLETE.equals(sTableID)
1636 					|| TableManager.TABLE_MYTORRENTS_COMPLETE_BIG.equals(sTableID)) {
1637 				forPluginDataSourceType = DownloadTypeComplete.class;
1638 			} else if (TableManager.TABLE_TORRENT_PEERS.equals(sTableID)) {
1639 				forPluginDataSourceType = Peer.class;
1640 			} else if (TableManager.TABLE_TORRENT_FILES.equals(sTableID)) {
1641 				forPluginDataSourceType = DiskManagerFileInfo.class;
1642 			} else if (TableManager.TABLE_MYTRACKER.equals(sTableID)) {
1643 				forPluginDataSourceType = TrackerTorrent.class;
1644 			} else if (TableManager.TABLE_MYSHARES.equals(sTableID)) {
1645 				forPluginDataSourceType = ShareResource.class;
1646 			}
1647 			if (forPluginDataSourceType != null) {
1648 				forPluginDataSourceTypes.add(forPluginDataSourceType);
1649 			}
1650 		}
1651 		return forPluginDataSourceTypes.toArray(new Class[0]);
1652 	}
1653 
reset()1654 	public void reset() {
1655 		if (iDefaultWidth != 0) {
1656 			setWidthPX(iDefaultWidth);
1657 		}
1658 		if ( iDefaultAlignment != -1 ){
1659 			setAlignment( iDefaultAlignment );
1660 		}
1661 		setNameOverride( null );
1662 	}
1663 
1664 	/* (non-Javadoc)
1665 	 * @see com.aelitis.azureus.ui.common.table.TableColumnCore#addDataSourceType(java.lang.Class)
1666 	 */
addDataSourceType(Class<?> cla)1667 	public void addDataSourceType(Class<?> cla) {
1668 		if (cla == null) {
1669 			return;
1670 		}
1671 		if (cla == org.gudy.azureus2.core3.disk.DiskManagerFileInfo.class) {
1672 			cla = DiskManagerFileInfo.class;
1673 		}
1674 		forPluginDataSourceTypes.add(cla);
1675 	}
1676 
addDataSourceTypes(Class[] datasourceTypes)1677 	public void addDataSourceTypes(Class[] datasourceTypes) {
1678 		if (datasourceTypes == null) {
1679 			return;
1680 		}
1681 		for (Class cla : datasourceTypes) {
1682 			addDataSourceType(cla);
1683 		}
1684 	}
1685 
handlesDataSourceType(Class<?> cla)1686 	public boolean handlesDataSourceType(Class<?> cla) {
1687 		Class[] forPluginDataSourceTypes = getForDataSourceTypes();
1688 		for (Class<?> forClass : forPluginDataSourceTypes) {
1689 			if (forClass.isAssignableFrom(cla)) {
1690 				return true;
1691 			}
1692 		}
1693 		return false;
1694 	}
1695 
1696 	/* (non-Javadoc)
1697 	 * @see org.gudy.azureus2.plugins.ui.tables.TableColumn#getForDataSourceType()
1698 	 */
getForDataSourceType()1699 	public Class getForDataSourceType() {
1700 		Class[] forPluginDataSourceTypes = getForDataSourceTypes();
1701 		return forPluginDataSourceTypes.length > 0 ? forPluginDataSourceTypes[0] : null;
1702 	}
1703 
setIconReference(String iconID, boolean showOnlyIcon)1704 	public void setIconReference(String iconID, boolean showOnlyIcon) {
1705 		this.iconID = iconID;
1706 		this.showOnlyImage = showOnlyIcon;
1707 	}
1708 
getIconReference()1709 	public String getIconReference() {
1710 		return iconID;
1711 	}
1712 
setMinimumRequiredUserMode(int mode)1713 	public void setMinimumRequiredUserMode(int mode) {
1714 
1715 		TableColumnInfo info = TableColumnManager.getInstance().getColumnInfo( this );
1716 
1717 		if ( info != null ){
1718 			byte	prof;
1719 			if ( mode == Parameter.MODE_BEGINNER ){
1720 				prof = TableColumnInfo.PROFICIENCY_BEGINNER;
1721 			}else if ( mode == Parameter.MODE_INTERMEDIATE ){
1722 				prof = TableColumnInfo.PROFICIENCY_INTERMEDIATE;
1723 			}else{
1724 				prof = TableColumnInfo.PROFICIENCY_ADVANCED;
1725 			}
1726 			info.setProficiency( prof );
1727 		}
1728 	}
1729 
1730 
showOnlyImage()1731 	public boolean showOnlyImage() {
1732 		return showOnlyImage;
1733 	}
1734 }
1735