jtreetable.java

来自「Rapla是一个灵活的多用户资源管理系统。它提供的一些功能有:日历GUI」· Java 代码 · 共 731 行 · 第 1/2 页

JAVA
731
字号
        }

        public void removeCellEditorListener(CellEditorListener listener) {
            delegate.removeCellEditorListener(listener);
        }

        public void cancelCellEditing() {
            delegate.cancelCellEditing();
        }

        public Object getCellEditorValue() {
            return delegate.getCellEditorValue();
        }

        public boolean stopCellEditing() {
            return delegate.stopCellEditing();

        }

        public boolean shouldSelectCell(EventObject anEvent) {
            return true;
        }

        private int getTextOffset(Object value,boolean isSelected,int row) {
            int gap = delegate.getGap(tree,value,isSelected,row);
            TreePath path = tree.getPathForRow(row);
            return tree.getUI().getPathBounds(tree,path).x + gap;
        }

        public boolean inHitRegion(int x,int y) {
            int row = tree.getRowForLocation(x,y);
            TreePath path = tree.getPathForRow(row);
            if (path == null)
                return false;
            int gap =  (delegate != null) ?
                delegate.getGap(tree,null,false,row)
                :16;

            return (x - gap >= tree.getUI().getPathBounds(tree,path).x  || x<0);
        }

        public Component getTableCellEditorComponent(JTable table, Object value,
                                                     boolean isSelected,
                                                     int row,
                                                     int column)
        {
            JTreeTable.this.tree.rowToPaint = row;
            JComponent comp = (JComponent) delegate.getEditorComponent(tree,value,isSelected,row);
            if (lastComp != comp) {
                if (comp != null)
                    comp.removeMouseListener(mouseListener);
                comp.addMouseListener(mouseListener);
            }
            lastComp = comp;

            textOffset = getTextOffset(value,isSelected,row);
            Border outerBorder = new TreeBorder(0, textOffset , 0, 0,row);
            Border editBorder = UIManager.getBorder("Tree.editorBorder");
            Border border = new CompoundBorder(outerBorder
                                               ,editBorder
                                               );
            comp.setBorder(border);
            return comp;
        }

        public boolean isCellEditable( EventObject evt ) {
            int col = getTreeColumnNumber();
            if( evt instanceof MouseEvent ) {
                MouseEvent me = (MouseEvent)evt;
                if (col >= 0) {
                    int xPosRelativeToCell = me.getX() - getCellRect(0, col, true).x;
                    if (me.getClickCount() > 1
                        && inHitRegion(xPosRelativeToCell,me.getY())
                        && isCellRealEditable(tree.getRowForLocation(me.getX(),me.getY())
                                              ,convertColumnIndexToModel(col)))
                        return true;
                    MouseEvent newME = new MouseEvent(tree, me.getID(),
                                                      me.getWhen(), me.getModifiers(),
                                                      xPosRelativeToCell,
                                                      me.getY(), me.getClickCount(),
                                                      me.isPopupTrigger());
                    if (! inHitRegion(xPosRelativeToCell,me.getY()) || me.getClickCount() > 1)
                        tree.dispatchEvent(newME);
                }
                return false;
            }

            if (delegate != null && isCellRealEditable(focusedRow,convertColumnIndexToModel(col)))
                return delegate.isCellEditable(evt);
            else
                return false;
        }
    }


    class TreeBorder implements Border {
        int row;
        Insets insets;

        public TreeBorder(int top,int left,int bottom,int right,int row) {
            this.row = row;
            insets = new Insets(top,left,bottom,right);
        }

        public Insets getBorderInsets(Component c) {
            return insets;
        }

        public void paintBorder(Component c,Graphics g,int x,int y,int width,int height) {
            Shape originalClip = g.getClip();
            g.clipRect(0,0,insets.left -1 ,tree.getHeight());
            tree.paintEditorBackground(g,row);
            g.setClip(originalClip);
        }

        public boolean isBorderOpaque() {
            return false;
        }

    }



    /**
     * ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel
     * to listen for changes in the ListSelectionModel it maintains. Once
     * a change in the ListSelectionModel happens, the paths are updated
     * in the DefaultTreeSelectionModel.
     */
    class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel implements ListSelectionListener{
        private static final long serialVersionUID = 1L;

        /** Set to true when we are updating the ListSelectionModel. */
        protected boolean         updatingListSelectionModel;

        public ListToTreeSelectionModelWrapper() {
            super();
            getListSelectionModel().addListSelectionListener
                                    (createListSelectionListener());
        }

        /**
         * Returns the list selection model. ListToTreeSelectionModelWrapper
         * listens for changes to this model and updates the selected paths
         * accordingly.
         */
        ListSelectionModel getListSelectionModel() {
            return listSelectionModel;
        }

        /**
         * This is overridden to set <code>updatingListSelectionModel</code>
         * and message super. This is the only place DefaultTreeSelectionModel
         * alters the ListSelectionModel.
         */
        public void resetRowSelection() {
            if(!updatingListSelectionModel) {
                updatingListSelectionModel = true;
                try {
                    super.resetRowSelection();
                }
                finally {
                    updatingListSelectionModel = false;
                }
            }
            // Notice how we don't message super if
            // updatingListSelectionModel is true. If
            // updatingListSelectionModel is true, it implies the
            // ListSelectionModel has already been updated and the
            // paths are the only thing that needs to be updated.
        }

        /**
         * Creates and returns an instance of ListSelectionHandler.
         */
        protected ListSelectionListener createListSelectionListener() {
            return this;
        }

        /**
         * If <code>updatingListSelectionModel</code> is false, this will
         * reset the selected paths from the selected rows in the list
         * selection model.
         */
        protected void updateSelectedPathsFromSelectedRows() {
            if(!updatingListSelectionModel) {
                updatingListSelectionModel = true;
                try {
                    // This is way expensive, ListSelectionModel needs an
                    // enumerator for iterating.
                    int        min = listSelectionModel.getMinSelectionIndex();
                    int        max = listSelectionModel.getMaxSelectionIndex();

                    clearSelection();
                    if(min != -1 && max != -1) {
                        for(int counter = min; counter <= max; counter++) {
                            if(listSelectionModel.isSelectedIndex(counter)) {
                                TreePath     selPath = tree.getPathForRow
                                                            (counter);

                                if(selPath != null) {
                                    addSelectionPath(selPath);
                                }
                            }
                        }
                    }
                } finally {
                    updatingListSelectionModel = false;
                }
            }
        }
        /** Implemention of ListSelectionListener Interface:
         * Class responsible for calling updateSelectedPathsFromSelectedRows
         * when the selection of the list changse.
         */
        public void valueChanged(ListSelectionEvent e) {
            updateSelectedPathsFromSelectedRows();
        }
    }

    class TreeTableModelAdapter extends AbstractTableModel implements TreeExpansionListener,TreeModelListener
    {
        private static final long serialVersionUID = 1L;

        TreeTableModel treeTableModel;
        public TreeTableModelAdapter(TreeTableModel treeTableModel) {
            this.treeTableModel = treeTableModel;

            tree.addTreeExpansionListener(this);
            // Install a TreeModelListener that can update the table when
            // tree changes. We use delayedFireTableDataChanged as we can
            // not be guaranteed the tree will have finished processing
            // the event before us.
            treeTableModel.addTreeModelListener(this);
        }


        // Implementation of TreeExpansionListener
        public void treeExpanded(TreeExpansionEvent event) {
            int row = tree.getRowForPath(event.getPath());
            if (row + 1 < tree.getRowCount())
                fireTableRowsInserted(row + 1,row + 1);
        }
        public void treeCollapsed(TreeExpansionEvent event) {
            int row = tree.getRowForPath(event.getPath());
            if (row  < getRowCount())
                fireTableRowsDeleted(row  + 1,row + 1);
        }

        // Implementation of TreeModelLstener
        public void treeNodesChanged(TreeModelEvent e) {
            int firstRow = 0;
            int lastRow = tree.getRowCount() -1;
            delayedFireTableRowsUpdated(firstRow,lastRow);
        }

        public void treeNodesInserted(TreeModelEvent e) {
            delayedFireTableDataChanged();
        }

        public void treeNodesRemoved(TreeModelEvent e) {
            delayedFireTableDataChanged();
        }

        public void treeStructureChanged(TreeModelEvent e) {
            delayedFireTableDataChanged();
        }

        // Wrappers, implementing TableModel interface.
        public int getColumnCount() {
            return treeTableModel.getColumnCount();
        }

        public String getColumnName(int column) {
            return treeTableModel.getColumnName(column);
        }

        public Class getColumnClass(int column) {
            return treeTableModel.getColumnClass(column);
        }

        public int getRowCount() {
            return tree.getRowCount();
        }

        private Object nodeForRow(int row) {
            TreePath treePath = tree.getPathForRow(row);
            if (treePath == null)
                return null;
            return treePath.getLastPathComponent();
        }

        public Object getValueAt(int row, int column) {
            Object node = nodeForRow(row);
            if (node == null)
                return null;
            return treeTableModel.getValueAt(node, column);
        }

        public boolean isCellEditable(int row, int column) {
            if (getColumnClass(column) == TreeTableModel.class) {
                return true;
            } else {
                Object node = nodeForRow(row);
                if (node == null)
                    return false;
                return treeTableModel.isCellEditable(node, column);
            }
        }

        public void setValueAt(Object value, int row, int column) {
            Object node = nodeForRow(row);
            if (node == null)
                return;
            treeTableModel.setValueAt(value, node, column);
        }

        /**
         * Invokes fireTableDataChanged after all the pending events have been
         * processed. SwingUtilities.invokeLater is used to handle this.
         */
        protected void delayedFireTableRowsUpdated(int firstRow,int lastRow) {
            SwingUtilities.invokeLater(new UpdateRunnable(firstRow,lastRow));
        }

        class UpdateRunnable implements Runnable {
            int lastRow;
            int firstRow;
            UpdateRunnable(int firstRow,int lastRow) {
                this.firstRow = firstRow;
                this.lastRow = lastRow;
            }
            public void run() {
                fireTableRowsUpdated(firstRow,lastRow);
            }
        }
        /**
         * Invokes fireTableDataChanged after all the pending events have been
         * processed. SwingUtilities.invokeLater is used to handle this.
         */
        protected void delayedFireTableDataChanged() {
            SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        fireTableDataChanged();
                    }
                });
                
        }
    }


    /*
    public void paintComponent(Graphics g) {
        super.paintComponent( g );
        Rectangle r = g.getClipBounds();
        g.setColor( Color.white);
        g.fillRect(0,0, r.width, r.height );
        
    }
    */
        
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?