OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 142 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.task;

import static org.openconcerto.task.TM.getTM;

import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowListRSH;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.users.User;
import org.openconcerto.sql.users.UserManager;
import org.openconcerto.sql.users.UserTableCellRenderer;
import org.openconcerto.task.ui.UserComboBox;
import org.openconcerto.task.ui.UserTableCellEditor;
import org.openconcerto.ui.JMultiLineToolTip;
import org.openconcerto.ui.LightEventJTable;
import org.openconcerto.ui.ReloadPanel;
import org.openconcerto.ui.TitledSeparator;
import org.openconcerto.ui.table.AlternateTableCellRenderer;
import org.openconcerto.ui.table.IconTableCellRenderer;
import org.openconcerto.ui.table.JCheckBoxTableCellRender;
import org.openconcerto.ui.table.TablePopupMouseListener;
import org.openconcerto.ui.table.TimestampTableCellEditor;
import org.openconcerto.ui.table.TimestampTableCellRenderer;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.TableSorter;
import org.openconcerto.utils.cc.ITransformer;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolTip;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class TodoListPanel extends JPanel implements ModelStateListener {

    private final UserManager uMngr;
    // Actions
    private final JCheckBox detailCheckBox;
    private final JCheckBox hideOldCheckBox;
    private JMenu comboUser;
    private final JButton addButton, removeButton;

    // Table
    private final LightEventJTable t;
    private final TodoListModel model;
    private final TimestampTableCellRenderer timestampTableCellRendererCreated;
    private final TimestampTableCellRenderer timestampTableCellRendererDone;
    private final TimestampTableCellRenderer timestampTableCellRendererDeadLine;
    private final IconTableCellRenderer iconEditor, iconRenderer;
    private final UserTableCellRenderer userTableCellRenderer;
    private final JCheckBoxTableCellRender a = new JCheckBoxTableCellRender();
    private final ImageIcon iconTache, iconPriorite;
    private TimestampTableCellEditor timestampTableCellEditorDeadLine;
    private TimestampTableCellEditor timestampTableCellEditorCreated;
    private TimestampTableCellEditor timestampTableCellEditorDone;
    private final Vector<User> users = new Vector<User>();
    final ReloadPanel reloadPanel = new ReloadPanel();
    TableSorter sorter;

    public TodoListPanel(final UserManager uMngr) {
        this.uMngr = uMngr;
        this.setOpaque(false);
        this.iconTache = new ImageIcon(TodoListPanel.class.getResource("tache.png"));
        this.iconPriorite = new ImageIcon(TodoListPanel.class.getResource("priorite.png"));
        this.userTableCellRenderer = new UserTableCellRenderer(uMngr);
        this.timestampTableCellRendererCreated = new TimestampTableCellRenderer();
        this.timestampTableCellRendererDone = new TimestampTableCellRenderer();
        this.timestampTableCellRendererDeadLine = new TimestampTableCellRenderer(true);
        this.timestampTableCellEditorCreated = new TimestampTableCellEditor();
        this.timestampTableCellEditorDone = new TimestampTableCellEditor();
        this.timestampTableCellEditorDeadLine = new TimestampTableCellEditor();
        // Icon renderer
        List<URL> l = new Vector<URL>();
        l.add(TodoListPanel.class.getResource("empty.png"));
        l.add(TodoListPanel.class.getResource("high.png"));
        l.add(TodoListPanel.class.getResource("normal.png"));
        l.add(TodoListPanel.class.getResource("low.png"));
        this.iconEditor = new IconTableCellRenderer(l);
        this.iconRenderer = new IconTableCellRenderer(l);

        final User currentUser = uMngr.getCurrentUser();
        this.model = new TodoListModel(uMngr);
        this.sorter = new TableSorter(this.model);
        this.t = new LightEventJTable(this.sorter) {
            public JToolTip createToolTip() {
                return new JMultiLineToolTip();
            }

            @Override
            public String getToolTipText(MouseEvent event) {
                String r = null;
                TodoListElement task = getTaskAt(event.getPoint());

                if (task != null && task.getCreatorId() > 1) {
                    final String comment = task.getComment();
                    if (comment != null) {
                        r = comment;
                        r += "\n\n";
                    } else {
                        r = "";
                    }
                    r += getTM().trM("assignedBy", "user", uMngr.getUser(task.getCreatorId()).getFullName(), "date", task.getDate());
                }

                return r;
            }

        };
        this.sorter.setTableHeader(this.t.getTableHeader());

        this.model.setTable(this.t);

        this.comboUser = new JMenu(TM.tr("showTaskAssignedTo"));
        initViewableUsers(currentUser);

        // L'utilisateur courant doit voir ses taches + toutes les taches dont il a les droits
        this.model.addIdListenerSilently(Integer.valueOf(currentUser.getId()));

        final int size = this.users.size();
        for (int i = 0; i < size; i++) {
            Integer id = Integer.valueOf((this.users.get(i)).getId());
            if (this.model.listenToId(id)) {
                ((JCheckBoxMenuItem) this.comboUser.getMenuComponent(i)).setState(true);
            } else {
                ((JCheckBoxMenuItem) this.comboUser.getMenuComponent(i)).setState(false);
            }
        }

        this.addButton = new JButton(TM.tr("addTask"));
        this.removeButton = new JButton();
        this.removeButton.setOpaque(false);
        updateDeleteBtn();
        this.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(2, 2, 1, 2);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 1;
        c.weighty = 0;
        c.gridwidth = 6;
        // SEP
        TitledSeparator sep = new TitledSeparator(currentUser.getFirstName() + " " + currentUser.getName().toUpperCase());
        this.add(sep, c);

        c.gridwidth = 1;
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        this.add(this.addButton, c);
        c.gridx++;
        this.add(this.removeButton, c);

        c.anchor = GridBagConstraints.EAST;
        c.gridx++;
        final JMenuBar b = new JMenuBar();
        b.setOpaque(false);
        b.setBorderPainted(false);
        b.add(this.comboUser);
        // Pour que le menu ne disparaisse pas quand on rapetisse trop la fenetre en bas
        b.setMinimumSize(b.getPreferredSize());
        this.add(b, c);

        c.gridx++;
        c.weightx = 1;
        this.detailCheckBox = new JCheckBox(TM.tr("showDetails"));
        this.detailCheckBox.setOpaque(false);
        this.detailCheckBox.setSelected(false);
        this.add(this.detailCheckBox, c);

        //
        c.gridx++;
        this.hideOldCheckBox = new JCheckBox(TM.tr("hideHistory"));
        this.hideOldCheckBox.setOpaque(false);
        this.hideOldCheckBox.setSelected(true);
        this.add(this.hideOldCheckBox, c);

        c.gridx++;

        c.weightx = 0;
        c.anchor = GridBagConstraints.EAST;
        this.reloadPanel.setOpaque(false);
        this.add(this.reloadPanel, c);

        // Table
        c.gridwidth = 6;
        c.gridx = 0;
        c.gridy++;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 1;
        initPopUp();
        initTable(TodoListModel.SIMPLE_MODE);
        this.add(new JScrollPane(this.t), c);

        initListeners();

        this.model.asynchronousFill();
    }

    public final UserManager getUserManager() {
        return this.uMngr;
    }

    private void initViewableUsers(final User currentUser) {
        final SwingWorker<List<User>, Object> worker = new SwingWorker<List<User>, Object>() {

            @Override
            protected List<User> doInBackground() throws Exception {
                final List<Integer> canViewUsers = new ArrayList<Integer>();
                for (final UserTaskRight right : UserTaskRight.getUserTaskRight(currentUser)) {
                    if (right.canRead())
                        canViewUsers.add(right.getIdToUser());
                }
                // final Vector users = new Vector();
                final SQLTable userT = getUserManager().getTable();
                final SQLSelect select1 = new SQLSelect(false);
                select1.addSelectStar(userT);
                final Where meWhere = new Where(userT.getKey(), "=", currentUser.getId());
                final Where canViewWhere = new Where(userT.getKey(), canViewUsers);
                select1.setWhere(meWhere.or(canViewWhere));

                final List<User> result = new ArrayList<User>();
                for (final SQLRow r : SQLRowListRSH.execute(select1)) {
                    result.add(new User(r));
                }
                return result;
            }

            @Override
            protected void done() {
                try {
                    final List<User> tuples = get();
                    for (final User user : tuples) {
                        String displayName = user.getNickName();
                        if (displayName.length() == 0) {
                            displayName = user.getFirstName() + " " + user.getName().toUpperCase();
                        }
                        final JCheckBoxMenuItem checkBoxMenuItem = new JCheckBoxMenuItem(displayName);
                        TodoListPanel.this.comboUser.add(checkBoxMenuItem);

                        final int uId = user.getId();

                        TodoListPanel.this.users.add(user);
                        checkBoxMenuItem.addActionListener(new ActionListener() {

                            public void actionPerformed(ActionEvent e) {
                                if (checkBoxMenuItem.isSelected())
                                    addUserListenerId(uId);
                                else
                                    removeUserListenerId(uId);
                            }

                        });
                    }

                } catch (Exception e) {
                    ExceptionHandler.handle("Unable to get tasks users", e);
                }

            }
        };

        worker.execute();

    }

    /**
     * @param addButton
     * @param removeButton
     */
    private void initListeners() {
        this.t.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                updateDeleteBtn();
            }
        });
        this.removeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeSelectedTask();
            }
        });
        this.addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addTask();
            }
        });
        this.detailCheckBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                // masque les colonnes "fait le" et "le"
                detailCheckBoxClicked();
            }
        });
        this.hideOldCheckBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                TodoListPanel.this.model.setHistoryVisible(e.getStateChange() == ItemEvent.DESELECTED);
                TodoListPanel.this.model.asynchronousFill();
            }
        });
        try {

        } catch (Exception e) {
            throw new RuntimeException();
        }
        this.model.addModelStateListener(TodoListPanel.this);
        this.addAncestorListener(new AncestorListener() {

            public void ancestorAdded(AncestorEvent event) {
            }

            public void ancestorMoved(AncestorEvent event) {
            }

            public void ancestorRemoved(AncestorEvent event) {
                TodoListPanel.this.model.removeModelStateListener(TodoListPanel.this);
                TodoListPanel.this.model.stopUpdate();
            }
        });
    }

    protected void removeSelectedTask() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                TodoListPanel.this.t.editingCanceled(null);
                int index = TodoListPanel.this.t.getSelectedRow();
                while (index >= 0) {

                    if (!TodoListPanel.this.model.deleteTaskAtIndex(TodoListPanel.this.sorter.modelIndex(index))) {
                        break;
                    }

                    index = TodoListPanel.this.t.getSelectedRow();
                }
                TodoListPanel.this.model.asynchronousFill();
            }
        });
    }

    protected void detailCheckBoxClicked() {
        if (this.detailCheckBox.isSelected()) {
            initTable(TodoListModel.EXTENDED_MODE);
        } else {
            initTable(TodoListModel.SIMPLE_MODE);
        }
    }

    private void initTable(int mode) {
        this.t.setBlockRepaint(true);

        this.t.setBlockEventOnColumn(true);
        this.model.setMode(mode);

        this.t.getColumnModel().getColumn(0).setCellRenderer(this.a);
        this.t.getColumnModel().getColumn(0).setCellEditor(this.a);
        this.t.setBlockEventOnColumn(true);
        setIconForColumn(0, this.iconTache);
        setIconForColumn(1, this.iconPriorite);
        this.t.setBlockEventOnColumn(true);

        this.t.getColumnModel().getColumn(1).setCellEditor(this.iconEditor);
        final JTextField textField = new JTextField() {
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                g.setColor(TodoListPanel.this.t.getGridColor());
                g.fillRect(getWidth() - 19, 0, 1, getHeight());
                g.setColor(new Color(250, 250, 250));
                g.fillRect(getWidth() - 18, 0, 18, getHeight());
                g.setColor(Color.BLACK);
                for (int i = 0; i < 3; i++) {
                    int x = getWidth() - 14 + i * 4;
                    int y = getHeight() - 5;
                    g.fillRect(x, y, 1, 2);
                }
            }
        };
        textField.setBorder(BorderFactory.createEmptyBorder());
        final DefaultCellEditor defaultCellEditor = new DefaultCellEditor(textField);
        textField.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent e) {

            }

            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mousePressed(MouseEvent e) {

            }

            public void mouseReleased(MouseEvent e) {
                if (e.getX() > textField.getWidth() - 19) {
                    TodoListElement l = getTaskAt(SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), TodoListPanel.this.t));
                    TodoListPanel.this.t.editingCanceled(new ChangeEvent(this));
                    JFrame f = new JFrame(TM.tr("details"));
                    f.setContentPane(new TodoListElementEditorPanel(l));
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.setSize(500, 200);
                    f.setLocation(50, e.getYOnScreen() + TodoListPanel.this.t.getRowHeight());
                    f.setVisible(true);
                }

            }
        });
        this.t.getColumnModel().getColumn(2).setCellEditor(defaultCellEditor);
        this.t.getColumnModel().getColumn(3).setMaxWidth(300);
        this.t.getColumnModel().getColumn(3).setMinWidth(100);

        this.timestampTableCellEditorCreated.stopCellEditing();
        this.timestampTableCellEditorDone.stopCellEditing();
        this.timestampTableCellEditorDeadLine.stopCellEditing();

        if (this.model.getMode() == TodoListModel.EXTENDED_MODE) {
            this.t.getColumnModel().getColumn(3).setCellRenderer(this.timestampTableCellRendererCreated);
            this.t.getColumnModel().getColumn(3).setCellEditor(this.timestampTableCellEditorCreated);

            this.t.getColumnModel().getColumn(4).setCellRenderer(this.timestampTableCellRendererDone);
            this.t.getColumnModel().getColumn(4).setCellEditor(this.timestampTableCellEditorDone);

            this.t.getColumnModel().getColumn(5).setCellRenderer(this.timestampTableCellRendererDeadLine);
            this.t.getColumnModel().getColumn(5).setCellEditor(this.timestampTableCellEditorDeadLine);
        } else {
            this.t.getColumnModel().getColumn(3).setCellRenderer(this.timestampTableCellRendererDeadLine);
            this.t.getColumnModel().getColumn(3).setCellEditor(this.timestampTableCellEditorDeadLine);
        }

        final TableColumn userColumn = this.t.getColumnModel().getColumn(this.t.getColumnModel().getColumnCount() - 1);
        userColumn.setCellRenderer(this.userTableCellRenderer);
        userColumn.setMaxWidth(150);
        userColumn.setMinWidth(100);
        t.setEnabled(false);
        initUserCellEditor(userColumn);

        this.t.setBlockEventOnColumn(false);
        this.t.setBlockRepaint(false);
        this.t.getColumnModel().getColumn(1).setCellRenderer(this.iconRenderer);
        // Better look
        this.t.setShowHorizontalLines(false);
        this.t.setGridColor(new Color(230, 230, 230));
        this.t.setRowHeight(new JTextField(" ").getPreferredSize().height + 4);
        AlternateTableCellRenderer.UTILS.setAllColumns(this.t);
        this.t.repaint();

    }

    private void initUserCellEditor(final TableColumn userColumn) {
        new SwingWorker<List<UserTaskRight>, Object>() {
            @Override
            protected List<UserTaskRight> doInBackground() throws Exception {
                return UserTaskRight.getUserTaskRight(getUserManager().getCurrentUser());
            }

            @Override
            protected void done() {
                // only display allowed recipients
                try {
                    final List<UserTaskRight> rights = get();
                    final List<User> canAddUsers = new ArrayList<User>();
                    for (final UserTaskRight right : rights) {
                        assert right.getIdUser() == getUserManager().getCurrentUser().getId();
                        if (right.canAdd()) {
                            canAddUsers.add(getUserManager().getUser(right.getIdToUser()));
                        }
                    }
                    userColumn.setCellEditor(new UserTableCellEditor(getUserManager(), new UserComboBox(canAddUsers)));
                    t.setEnabled(true);
                } catch (Exception e) {
                    ExceptionHandler.handle("Unable to get user task rights", e);
                }

                super.done();
            }
        }.execute();
    }

    void initPopUp() {
        TablePopupMouseListener.add(this.t, new ITransformer<MouseEvent, JPopupMenu>() {

            @Override
            public JPopupMenu transformChecked(MouseEvent evt) {
                final JTable table = (JTable) evt.getSource();
                final int modelIndex = TodoListPanel.this.sorter.modelIndex(table.getSelectedRow());
                final JPopupMenu res = new JPopupMenu();

                // Avancer d'un jour
                Action act = new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                        final TodoListElement element = TodoListPanel.this.model.getTaskAtRow(modelIndex);
                        if (element != null) {
                            final Date ts = element.getExpectedDate();
                            final Calendar cal = Calendar.getInstance();
                            cal.setTimeInMillis(ts.getTime());
                            cal.add(Calendar.DAY_OF_YEAR, 1);
                            SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                    ts.setTime(cal.getTimeInMillis());
                                    element.setExpectedDate(ts);
                                    element.commitChangesAndWait();
                                    table.repaint();
                                }
                            });
                        }
                    }
                };
                act.putValue(Action.NAME, TM.tr("moveOneDay"));
                res.add(act);

                // Marquer comme réalisé
                act = new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                        TodoListElement element = TodoListPanel.this.model.getTaskAtRow(modelIndex);
                        if (element != null) {
                            element.setDone(true);
                            element.commitChangesAndWait();
                            table.repaint();
                        }
                    }
                };
                act.putValue(Action.NAME, TM.tr("markDone"));
                res.add(act);

                // Suppression
                act = new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                        TodoListPanel.this.model.deleteTaskAtIndex(modelIndex);
                        table.repaint();
                    }
                };
                act.putValue(Action.NAME, TM.tr("delete"));
                res.add(act);

                final TodoListElement element = TodoListPanel.this.model.getTaskAtRow(modelIndex);
                SQLRowValues rowTache = element.getRowValues();

                List<AbstractAction> actions = TacheActionManager.getInstance().getActionsForTaskRow(rowTache);

                for (AbstractAction abstractAction : actions) {
                    res.add(abstractAction);
                }

                return res;
            }
        });
    }

    private void setIconForColumn(int i, ImageIcon icon) {

        TableCellRenderer renderer = new JComponentTableCellRenderer(icon);
        TableColumnModel columnModel = this.t.getColumnModel();
        TableColumn column = columnModel.getColumn(i);
        column.setHeaderRenderer(renderer);
        column.setMaxWidth(icon.getIconWidth() + 16);
        column.setMinWidth(icon.getIconWidth() + 8);
    }

    private void addTask() {
        this.model.addNewTask();

    }

    public void addUserListenerId(int id) {
        // Selection de l'utilisateur dans la combo
        for (int i = 0; i < this.users.size(); i++) {
            Integer idUser = Integer.valueOf((this.users.get(i)).getId());
            if (idUser.intValue() == id) {
                ((JCheckBoxMenuItem) this.comboUser.getMenuComponent(i)).setState(true);
            }
        }
        this.model.addIdListener(Integer.valueOf(id));
    }

    private void removeUserListenerId(int id) {
        this.t.editingCanceled(new ChangeEvent(this));
        this.model.removeIdListener(Integer.valueOf(id));
    }

    public void stopUpdate() {
        this.model.stopUpdate();
    }

    public void stateChanged(int state) {
        if (state == ModelStateListener.STATE_OK) {
            this.reloadPanel.setMode(ReloadPanel.MODE_EMPTY);
        }
        if (state == ModelStateListener.STATE_DEAD) {
            this.reloadPanel.setMode(ReloadPanel.MODE_BLINK);
        }
        if (state == ModelStateListener.STATE_RELOADING) {
            this.reloadPanel.setMode(ReloadPanel.MODE_ROTATE);
        }
    }

    public void addModelStateListener(ModelStateListener l) {
        this.model.addModelStateListener(l);
    }

    /**
     * @param event
     * @return
     */
    private TodoListElement getTaskAt(Point p) {
        int row = this.t.rowAtPoint(p);
        TodoListElement task = this.model.getTaskAtRow(TodoListPanel.this.sorter.modelIndex(row));
        return task;
    }

    protected void updateDeleteBtn() {
        final int nbRows = this.t.getSelectedRows().length;
        this.removeButton.setEnabled(nbRows > 0);
        this.removeButton.setText(getTM().trM("deleteSelectedTasks", "count", nbRows));
    }
}

class JComponentTableCellRenderer extends DefaultTableCellRenderer {
    Icon icon;
    TableCellRenderer renderer;

    public JComponentTableCellRenderer(Icon icon) {
        super();
        this.icon = icon;
        this.renderer = new JTableHeader().getDefaultRenderer();
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        JLabel label = (JLabel) this.renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        label.setIcon(this.icon);
        label.setBorder(BorderFactory.createEmptyBorder());
        label.setIconTextGap(0);
        label.setHorizontalTextPosition(0);
        label.setHorizontalAlignment(SwingConstants.CENTER);
        return label;
    }
}