001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.tasklist.ui;
043:
044: import java.awt.Color;
045: import java.awt.Component;
046: import java.awt.FontMetrics;
047: import java.awt.Image;
048: import java.awt.Insets;
049: import java.awt.Point;
050: import java.awt.Rectangle;
051: import java.awt.Toolkit;
052: import java.awt.event.ActionEvent;
053: import java.awt.event.KeyEvent;
054: import java.awt.event.MouseAdapter;
055: import java.awt.event.MouseEvent;
056: import java.util.HashMap;
057: import java.util.Map;
058: import javax.swing.AbstractAction;
059: import javax.swing.Action;
060: import javax.swing.ActionMap;
061: import javax.swing.BorderFactory;
062: import javax.swing.Icon;
063: import javax.swing.ImageIcon;
064: import javax.swing.InputMap;
065: import javax.swing.JLabel;
066: import javax.swing.JPopupMenu;
067: import javax.swing.JTable;
068: import javax.swing.KeyStroke;
069: import javax.swing.ListSelectionModel;
070: import javax.swing.SwingConstants;
071: import javax.swing.UIManager;
072: import javax.swing.plaf.TableHeaderUI;
073: import javax.swing.plaf.TableUI;
074: import javax.swing.plaf.UIResource;
075: import javax.swing.table.DefaultTableCellRenderer;
076: import javax.swing.table.JTableHeader;
077: import javax.swing.table.TableCellRenderer;
078: import javax.swing.table.TableColumn;
079: import javax.swing.table.TableColumnModel;
080: import javax.swing.table.TableModel;
081: import org.netbeans.modules.tasklist.impl.OpenTaskAction;
082: import org.netbeans.modules.tasklist.ui.Util;
083: import org.netbeans.spi.tasklist.Task;
084: import org.netbeans.modules.tasklist.trampoline.TaskGroup;
085: import org.openide.util.NbBundle;
086:
087: /**
088: *
089: * @author S. Aubrecht
090: */
091: class TaskListTable extends JTable {
092:
093: private TableCellRenderer foldingGroupRenderer;
094: private TableCellRenderer groupRenderer;
095:
096: private Action defaultAction = new DefaultAction();
097:
098: private Action nextTaskAction = new TaskNavigationAction(true);
099: private Action prevTaskAction = new TaskNavigationAction(false);
100:
101: /** Creates a new instance of TaskListTable */
102: public TaskListTable() {
103: addMouseListener(new MouseAdapter() {
104: @Override
105: public void mousePressed(MouseEvent e) {
106: maybePopup(e);
107: }
108:
109: @Override
110: public void mouseReleased(MouseEvent e) {
111: maybePopup(e);
112: }
113:
114: @Override
115: public void mouseClicked(MouseEvent e) {
116: int row = rowAtPoint(e.getPoint());
117: if (isFoldingModel()) {
118: FoldingTaskListModel foldingModel = getFoldingModel();
119: if (e.getClickCount() == 2) {
120: //handle group collapse/expand
121: if (foldingModel.isGroupRow(row)) {
122: foldingModel.toggleGroupExpanded(row);
123: return;
124: }
125: } else if (e.getClickCount() == 1) {
126: if (foldingModel.isGroupRow(row)) {
127: maybeExpandGroup(e.getPoint());
128: return;
129: }
130: }
131: }
132: if (e.getClickCount() == 2) {
133: defaultAction.actionPerformed(null);
134: }
135: }
136: });
137: setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
138: setBorder(BorderFactory.createEmptyBorder());
139:
140: setAutoCreateColumnsFromModel(false);
141:
142: int requiredRowHeight = 16 + 2 + 2 * getIntercellSpacing().height;
143: setRowHeight(Math.max(getRowHeight(), requiredRowHeight));
144:
145: InputMap inputMap = getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
146: Object right = inputMap.get(KeyStroke.getKeyStroke(
147: KeyEvent.VK_RIGHT, 0));
148: Object left = inputMap.get(KeyStroke.getKeyStroke(
149: KeyEvent.VK_LEFT, 0));
150: inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
151: "defaultAction"); // NOI18N
152:
153: getInputMap(JTable.WHEN_FOCUSED).put(
154: KeyStroke.getKeyStroke(KeyEvent.VK_F10,
155: KeyEvent.SHIFT_DOWN_MASK),
156: "org.openide.actions.PopupAction"); //NOI18N
157: getActionMap().put("org.openide.actions.PopupAction",
158: new PopupAction()); //NOI18N
159:
160: ActionMap actionMap = getActionMap();
161: Action actionLeft = actionMap.get(left);
162: Action actionRight = actionMap.get(right);
163:
164: actionMap.put(left, new ToggleGroupAction(false, actionLeft));
165: actionMap.put(right, new ToggleGroupAction(true, actionRight));
166: actionMap.put("defaultAction", defaultAction); // NOI18N
167:
168: actionMap.put("jumpPrev", prevTaskAction); // NOI18N
169: actionMap.put("jumpNext", nextTaskAction); // NOI18N
170: // actionMap.put (FindAction.class.getName (), this.findAction);
171: // actionMap.put (javax.swing.text.DefaultEditorKit.copyAction, this.copyAction);
172: }
173:
174: @Override
175: public void createDefaultColumnsFromModel() {
176: TableModel m = getModel();
177: if (m != null) {
178: // Remove any current columns
179: TableColumnModel cm = getColumnModel();
180: while (cm.getColumnCount() > 0) {
181: cm.removeColumn(cm.getColumn(0));
182: }
183:
184: // Create new columns from the data model info
185: for (int i = 0; i < m.getColumnCount(); i++) {
186: TableColumn newColumn = new MyTableColumn(i);
187: if (i == TaskListModel.COL_LOCATION)
188: newColumn.setCellRenderer(new LeftDotRenderer());
189: else if (i != TaskListModel.COL_GROUP)
190: newColumn.setCellRenderer(new TooltipRenderer());
191: addColumn(newColumn);
192: }
193: }
194: }
195:
196: @Override
197: public void removeNotify() {
198: if (getModel() instanceof TaskListModel)
199: storeColumnState();
200: super .removeNotify();
201: }
202:
203: @Override
204: protected JTableHeader createDefaultTableHeader() {
205: return new MyTableHeader(columnModel);
206: }
207:
208: @Override
209: public TableCellRenderer getCellRenderer(int row, int col) {
210: if (col == 0) {
211: if (isFoldingModel() && getFoldingModel().isGroupRow(row))
212: return getFoldingGroupRenderer();
213: return getGroupRenderer();
214: }
215: return super .getCellRenderer(row, col);
216: }
217:
218: private void maybePopup(MouseEvent e) {
219: if (e.isPopupTrigger()) {
220: e.consume();
221: int row = rowAtPoint(e.getPoint());
222: if (row >= 0)
223: getSelectionModel().setSelectionInterval(row, row);
224: JPopupMenu popup = Util.createPopup(this );
225: popup.show(this , e.getX(), e.getY());
226: }
227: }
228:
229: private TableCellRenderer getFoldingGroupRenderer() {
230: if (null == foldingGroupRenderer)
231: foldingGroupRenderer = new FoldingTaskGroupRenderer();
232: return foldingGroupRenderer;
233: }
234:
235: private TableCellRenderer getGroupRenderer() {
236: if (null == groupRenderer)
237: groupRenderer = new TaskGroupRenderer();
238: return groupRenderer;
239: }
240:
241: private void maybeExpandGroup(Point point) {
242: int row = rowAtPoint(point);
243: int col = columnAtPoint(point);
244: if (0 != col)
245: return;
246: Rectangle rect = getCellRect(row, col, false);
247: TableCellRenderer renderer = getCellRenderer(row, col);
248: prepareRenderer(renderer, row, col);
249: if (renderer instanceof FoldingTaskGroupRenderer) {
250: Icon icon = ((FoldingTaskGroupRenderer) renderer).getIcon();
251: rect.grow(0,
252: -(rect.height - openedIcon.getIconHeight()) / 2);
253: rect.x = getColumnModel().getColumnMargin(); //rect.width - icon.getIconWidth();
254: rect.width = openedIcon.getIconWidth();
255: if (rect.contains(point)) {
256: FoldingTaskListModel foldingModel = getFoldingModel();
257: foldingModel.toggleGroupExpanded(row);
258: }
259: }
260: }
261:
262: private void storeColumnState() {
263: int count = getColumnModel().getColumnCount();
264: for (int i = 0; i < count; i++) {
265: TableColumn tc = getColumnModel().getColumn(i);
266: if (tc instanceof MyTableColumn) {
267: ((MyTableColumn) tc).storeState();
268: }
269: }
270: }
271:
272: @Override
273: public void setUI(TableUI ui) {
274: super .setUI(new TaskListTableUI());
275: setTableHeader(createDefaultTableHeader());
276: }
277:
278: @Override
279: public void setModel(TableModel newModel) {
280: if (getModel() instanceof TaskListModel
281: && newModel != getModel()) {
282: storeColumnState();
283: ((TaskListModel) getModel()).detach();
284: }
285:
286: if (newModel instanceof TaskListModel) {
287: ((TaskListModel) newModel).attach();
288: }
289: super .setModel(newModel);
290: createDefaultColumnsFromModel();
291: }
292:
293: private boolean isFoldingModel() {
294: return getModel() instanceof FoldingTaskListModel;
295: }
296:
297: private FoldingTaskListModel getFoldingModel() {
298: return isFoldingModel() ? (FoldingTaskListModel) getModel()
299: : null;
300: }
301:
302: @Override
303: public String getToolTipText(MouseEvent e) {
304: int hitRowIndex = rowAtPoint(e.getPoint());
305: if (isFoldingModel()
306: && getFoldingModel().isGroupRow(hitRowIndex)) {
307: return getFoldingModel().getGroupAtRow(hitRowIndex)
308: .getGroup().getDescription();
309: }
310: return super .getToolTipText(e);
311: }
312:
313: Task getSelectedTask() {
314: int selRow = getSelectedRow();
315: if (selRow < 0)
316: return null;
317: return ((TaskListModel) getModel()).getTaskAtRow(selRow);
318: }
319:
320: int getSortColumn() {
321: return ((TaskListModel) getModel()).getSortingColumnn();
322: }
323:
324: void setSortColumn(int col) {
325: ((TaskListModel) getModel()).toggleSort(col);
326: }
327:
328: boolean isAscendingSort() {
329: return ((TaskListModel) getModel()).isAscendingSort();
330: }
331:
332: void setAscendingSort(boolean asc) {
333: ((TaskListModel) getModel()).setAscendingSort(asc);
334: }
335:
336: // @Override
337: // public Rectangle getCellRect( int row, int col, boolean includeSpacing ) {
338: // Rectangle res = super.getCellRect( row, col, includeSpacing );
339: // if( isFoldingModel() && getFoldingModel().isGroupRow(row) ) {
340: // res.x = 0;
341: // res.width = getWidth();
342: // if( !includeSpacing )
343: // res.width -= getColumnModel().getColumnMargin();
344: // }
345: // return res;
346: // }
347:
348: private static final Icon openedIcon = (Icon) UIManager
349: .get("Tree.expandedIcon"); // NOI18N
350: private static final Icon closedIcon = (Icon) UIManager
351: .get("Tree.collapsedIcon"); // NOI18N
352:
353: private static Map<Image, ImageIcon> iconCache = new HashMap<Image, ImageIcon>(
354: 10);
355:
356: private class TaskGroupRenderer extends DefaultTableCellRenderer {
357:
358: @Override
359: public Component getTableCellRendererComponent(JTable table,
360: Object value, boolean isSelected, boolean hasFocus,
361: int row, int column) {
362: Component res = super .getTableCellRendererComponent(table,
363: value, isSelected, hasFocus, row, column);
364: if (res instanceof JLabel) {
365: if (value instanceof TaskGroup) {
366: TaskGroup tg = (TaskGroup) value;
367: JLabel renderer = (JLabel) res;
368: renderer.setText(null);
369: ImageIcon icon = iconCache.get(tg.getIcon());
370: if (null == icon) {
371: icon = new ImageIcon(tg.getIcon());
372: iconCache.put(tg.getIcon(), icon);
373: }
374: renderer.setIcon(icon);
375: renderer.setToolTipText(tg.getDescription());
376: renderer.setHorizontalAlignment(JLabel.RIGHT);
377: }
378: }
379: return res;
380: }
381: }
382:
383: private class FoldingTaskGroupRenderer extends
384: DefaultTableCellRenderer {
385:
386: private final Color GTK_BK_COLOR = new Color(184, 207, 229);
387: private final Color AQUA_BK_COLOR = new Color(225, 235, 240);
388:
389: private final boolean isGTK = "GTK".equals(UIManager
390: .getLookAndFeel().getID()); // NOI18N
391: private final boolean isAqua = "Aqua".equals(UIManager
392: .getLookAndFeel().getID()); // NOI18N
393:
394: public FoldingTaskGroupRenderer() {
395: //force initialization of PropSheet look'n'feel values
396: UIManager.get("nb.propertysheet"); // NOI18N
397: setOpaque(true);
398: }
399:
400: @Override
401: public Component getTableCellRendererComponent(JTable table,
402: Object value, boolean isSelected, boolean hasFocus,
403: int row, int column) {
404:
405: if (getFoldingModel().isGroupRow(row)) {
406: hasFocus = table.isFocusOwner() && isSelected;
407: }
408: Component res = super .getTableCellRendererComponent(table,
409: value, isSelected, hasFocus, row, column);
410: if (res instanceof JLabel) {
411: if (value instanceof FoldingTaskListModel.FoldingGroup) {
412: FoldingTaskListModel.FoldingGroup fg = (FoldingTaskListModel.FoldingGroup) value;
413: JLabel renderer = (JLabel) res;
414: renderer.setText(fg.getGroup().getDisplayName()
415: + " (" + fg.getTaskCount() + ")");
416: Icon treeIcon = fg.isExpanded() ? openedIcon
417: : closedIcon;
418: renderer.setIcon(treeIcon);
419: renderer.setToolTipText(fg.getGroup()
420: .getDescription());
421: renderer.setHorizontalAlignment(JLabel.LEFT);
422: if (!isSelected)
423: renderer.setBackground(getBackgroundColor());
424: }
425: }
426: return res;
427: }
428:
429: public Color getBackgroundColor() {
430: if (isGTK) {
431: return GTK_BK_COLOR;
432: } else if (isAqua) {
433: return AQUA_BK_COLOR;
434: } else {
435: return UIManager.getColor("PropSheet.setBackground"); //NOI18N
436: }
437: }
438: }
439:
440: private class ToggleGroupAction extends AbstractAction {
441: private Action defaultAction;
442: private boolean expand;
443:
444: public ToggleGroupAction(boolean expand, Action defaultAction) {
445: this .defaultAction = defaultAction;
446: this .expand = expand;
447: }
448:
449: public void actionPerformed(ActionEvent e) {
450: if (isFoldingModel()) {
451: FoldingTaskListModel foldingModel = getFoldingModel();
452: int selRow = getSelectedRow();
453: if (selRow >= 0) {
454: FoldingTaskListModel.FoldingGroup group = foldingModel
455: .getGroupAtRow(selRow);
456: if (null != group && group.isExpanded() != expand) {
457: group.setExpanded(expand);
458: return;
459: }
460: }
461: }
462: defaultAction.actionPerformed(e);
463: }
464: }
465:
466: private class MyTableHeader extends JTableHeader {
467:
468: public MyTableHeader(TableColumnModel model) {
469: super (model);
470: addMouseListener(new MouseAdapter() {
471: public void mouseClicked(MouseEvent e) {
472: if (e.getClickCount() != 1)
473: return;
474: int column = columnAtPoint(e.getPoint());
475: if (column > 0
476: && getModel() instanceof TaskListModel) {
477: ((TaskListModel) getModel()).toggleSort(column);
478: repaint();
479: }
480: }
481: });
482: this .setReorderingAllowed(false);
483: }
484:
485: @Override
486: public void setDraggedColumn(TableColumn aColumn) {
487: if (null != aColumn && aColumn.getModelIndex() == 0)
488: return; //don't allow the first column to be dragged
489: super .setDraggedColumn(aColumn);
490: }
491:
492: @Override
493: public void setDefaultRenderer(TableCellRenderer defaultRenderer) {
494: if (!(defaultRenderer instanceof SortingHeaderRenderer))
495: defaultRenderer = new SortingHeaderRenderer(
496: defaultRenderer);
497: super .setDefaultRenderer(defaultRenderer);
498: }
499:
500: @Override
501: public void setUI(TableHeaderUI ui) {
502: super .setUI(ui);
503: setDefaultRenderer(createDefaultRenderer());
504: }
505:
506: @Override
507: public void setResizingColumn(TableColumn col) {
508: if (null != getResizingColumn() && null == col) {
509: storeColumnState();
510: }
511: super .setResizingColumn(col);
512: }
513: }
514:
515: private class DefaultAction extends AbstractAction {
516:
517: public void actionPerformed(ActionEvent arg0) {
518: Task t = getSelectedTask();
519: if (null != t) {
520: Action a = Util.getDefaultAction(t);
521: if (a.isEnabled()) {
522: a.actionPerformed(null);
523: } else {
524: Toolkit.getDefaultToolkit().beep();
525: }
526: }
527: }
528: }
529:
530: private class TaskNavigationAction extends AbstractAction {
531: private boolean navigateToNextTask;
532:
533: public TaskNavigationAction(boolean navigateToNextTask) {
534: super (navigateToNextTask ? NbBundle.getMessage(
535: TaskListTable.class, "LBL_NextTask") //NOI18N
536: : NbBundle.getMessage(TaskListTable.class,
537: "LBL_PrevTask")); //NOI18N
538: this .navigateToNextTask = navigateToNextTask;
539: }
540:
541: public void actionPerformed(ActionEvent e) {
542: if (0 == getModel().getRowCount())
543: return;
544:
545: int currentRow = getSelectedRow();
546: if (currentRow < 0) {
547: currentRow = 0;
548: } else if (!(isFoldingModel() && getFoldingModel()
549: .isGroupRow(currentRow))) {
550: currentRow += (navigateToNextTask ? 1 : -1);
551: }
552:
553: TaskListModel tlm = (TaskListModel) getModel();
554: while (true) {
555: if (currentRow < 0)
556: currentRow = tlm.getRowCount() - 1;
557: else if (currentRow >= tlm.getRowCount())
558: currentRow = 0;
559: Task t = tlm.getTaskAtRow(currentRow);
560: if (null != t) {
561: getSelectionModel().setSelectionInterval(
562: currentRow, currentRow);
563: scrollRectToVisible(getCellRect(currentRow, 0, true));
564: Action a = new OpenTaskAction(t);
565: if (a.isEnabled()) {
566: a.actionPerformed(e);
567: } else {
568: TaskListTopComponent.findInstance()
569: .requestActive();
570: }
571: break;
572: } else if (isFoldingModel()) {
573: FoldingTaskListModel.FoldingGroup fg = getFoldingModel()
574: .getGroupAtRow(currentRow);
575: if (!fg.isExpanded())
576: fg.setExpanded(true);
577: }
578: currentRow += (navigateToNextTask ? 1 : -1);
579: }
580: }
581: }
582:
583: private class MyTableColumn extends TableColumn {
584: private float ratio;
585:
586: public MyTableColumn(int index) {
587: super (index);
588: if (index == TaskListModel.COL_GROUP) {
589: setWidth(isFoldingModel() ? 35 : 20);
590: setMinWidth(isFoldingModel() ? 35 : 20);
591: setMaxWidth(isFoldingModel() ? 35 : 20);
592: setResizable(false);
593: } else {
594: switch (modelIndex) {
595: case TaskListModel.COL_DESCRIPTION:
596: ratio = 0.65f;
597: break;
598: case TaskListModel.COL_LOCATION:
599: ratio = 0.2f;
600: break;
601: case TaskListModel.COL_FILE:
602: ratio = 0.1f;
603: break;
604: case TaskListModel.COL_LINE:
605: ratio = 0.05f;
606: break;
607: }
608: ratio = Settings.getDefault().getPreferredColumnWidth(
609: index, isFoldingModel(), ratio);
610: }
611: }
612:
613: @Override
614: public int getPreferredWidth() {
615: int modelIndex = this .getModelIndex();
616: if (isFoldingModel()
617: && modelIndex == TaskListModel.COL_GROUP)
618: return getWidth();
619:
620: int totalWidth = getParent().getWidth();
621: return (int) (totalWidth * ratio);
622: }
623:
624: public void storeState() {
625: float totalWidth = TaskListTable.this .getWidth();
626: if (totalWidth > 0) {
627: ratio = this .getWidth() / totalWidth;
628: Settings.getDefault().setPreferredColumnWidth(
629: getModelIndex(), isFoldingModel(), ratio);
630: }
631: }
632: }
633:
634: private static class LeftDotRenderer extends
635: DefaultTableCellRenderer {
636: public Component getTableCellRendererComponent(JTable table,
637: Object value, boolean isSelected, boolean hasFocus,
638: int row, int column) {
639:
640: super .getTableCellRendererComponent(table, value,
641: isSelected, hasFocus, row, column);
642:
643: int availableWidth = table.getColumnModel().getColumn(
644: column).getWidth();
645: availableWidth -= table.getIntercellSpacing().getWidth();
646: Insets borderInsets = getBorder().getBorderInsets(
647: (Component) this );
648: availableWidth -= (borderInsets.left + borderInsets.right);
649: String cellText = getText();
650: FontMetrics fm = getFontMetrics(getFont());
651:
652: if (fm.stringWidth(cellText) > availableWidth) {
653: setToolTipText(value.toString());
654: String dots = "..."; //NOI18N
655: int textWidth = fm.stringWidth(dots);
656: int nChars = cellText.length() - 1;
657: for (; nChars > 0; nChars--) {
658: textWidth += fm.charWidth(cellText.charAt(nChars));
659:
660: if (textWidth > availableWidth) {
661: break;
662: }
663: }
664:
665: setText(dots + cellText.substring(nChars + 1));
666: } else {
667: setToolTipText(null);
668: }
669:
670: return this ;
671: }
672: }
673:
674: private static class TooltipRenderer extends
675: DefaultTableCellRenderer {
676: public Component getTableCellRendererComponent(JTable table,
677: Object value, boolean isSelected, boolean hasFocus,
678: int row, int column) {
679:
680: super .getTableCellRendererComponent(table, value,
681: isSelected, hasFocus, row, column);
682:
683: int availableWidth = table.getColumnModel().getColumn(
684: column).getWidth();
685: availableWidth -= table.getIntercellSpacing().getWidth();
686: Insets borderInsets = getBorder().getBorderInsets(
687: (Component) this );
688: availableWidth -= (borderInsets.left + borderInsets.right);
689: String cellText = getText();
690: FontMetrics fm = getFontMetrics(getFont());
691:
692: if (fm.stringWidth(cellText) > availableWidth) {
693: setToolTipText(cellText);
694:
695: } else {
696: setToolTipText(null);
697: }
698:
699: return this ;
700: }
701: }
702:
703: private class SortingHeaderRenderer implements TableCellRenderer,
704: UIResource {
705:
706: private TableCellRenderer origRenderer;
707:
708: private static final String SORT_ASC_ICON = "org/netbeans/modules/tasklist/ui/resources/columnsSortedAsc.gif"; // NOI18N
709: private static final String SORT_DESC_ICON = "org/netbeans/modules/tasklist/ui/resources/columnsSortedDesc.gif"; // NOI18N
710:
711: SortingHeaderRenderer(TableCellRenderer origRenderer) {
712: this .origRenderer = origRenderer;
713: }
714:
715: /** Overrides superclass method. */
716: public Component getTableCellRendererComponent(JTable table,
717: Object value, boolean isSelected, boolean hasFocus,
718: int row, int column) {
719: Component comp = origRenderer
720: .getTableCellRendererComponent(table, value,
721: isSelected, hasFocus, row, column);
722:
723: if (comp instanceof JLabel) {
724: JLabel label = (JLabel) comp;
725: TaskListModel tlm = (TaskListModel) getModel();
726: if (column == tlm.getSortingColumnn()) {
727: label
728: .setIcon(getProperIcon(!tlm
729: .isAscendingSort()));
730: label
731: .setHorizontalTextPosition(SwingConstants.LEFT);
732: } else {
733: label.setIcon(null);
734: }
735: }
736:
737: return comp;
738: }
739:
740: private ImageIcon getProperIcon(boolean descending) {
741: if (descending) {
742: return new ImageIcon(org.openide.util.Utilities
743: .loadImage(SORT_DESC_ICON));
744: } else {
745: return new ImageIcon(org.openide.util.Utilities
746: .loadImage(SORT_ASC_ICON));
747: }
748: }
749: }
750:
751: private class PopupAction extends AbstractAction {
752: public PopupAction() {
753: super ("Popup"); //NOI18N
754: }
755:
756: public void actionPerformed(ActionEvent e) {
757: Point p = getPositionForPopup();
758:
759: if (p == null) {
760: //we're going to create a popup menu for the root node
761: p = new Point(0, 0);
762: }
763:
764: JPopupMenu popup = Util.createPopup(TaskListTable.this );
765: popup.show(TaskListTable.this , p.x, p.y);
766: }
767:
768: public boolean isEnabled() {
769: return TaskListTable.this .isFocusOwner();
770: }
771: }
772:
773: private Point getPositionForPopup() {
774: int selRow = getSelectedRow();
775:
776: if (selRow < 0) {
777: return null;
778: }
779:
780: Rectangle rect = getCellRect(selRow, 0, true);
781:
782: if (rect == null) {
783: return null;
784: }
785:
786: return new Point(0, rect.y + rect.height);
787: }
788: }
|