se.streamsource.streamflow.client.ui.workspace.table.CasesTableView.java Source code

Java tutorial

Introduction

Here is the source code for se.streamsource.streamflow.client.ui.workspace.table.CasesTableView.java

Source

/**
 *
 * Copyright 2009-2014 Jayway Products AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package se.streamsource.streamflow.client.ui.workspace.table;

import ca.odell.glazedlists.SeparatorList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.EventJXTableModel;
import ca.odell.glazedlists.swing.EventTableModel;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.color.ColorUtil;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.jdesktop.swingx.renderer.DefaultTableRenderer;
import org.jdesktop.swingx.renderer.StringValue;
import org.jdesktop.swingx.table.TableColumnExt;
import org.jdesktop.swingx.table.TableColumnModelExt;
import org.qi4j.api.common.Optional;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.injection.scope.Uses;
import org.qi4j.api.structure.Module;
import org.qi4j.api.util.Iterables;
import se.streamsource.dci.value.link.LinkValue;
import se.streamsource.streamflow.api.administration.priority.PriorityValue;
import se.streamsource.streamflow.api.workspace.cases.CaseStates;
import se.streamsource.streamflow.client.Icons;
import se.streamsource.streamflow.client.MacOsUIWrapper;
import se.streamsource.streamflow.client.ui.DateFormats;
import se.streamsource.streamflow.client.ui.workspace.WorkspaceResources;
import se.streamsource.streamflow.client.ui.workspace.cases.CaseResources;
import se.streamsource.streamflow.client.ui.workspace.cases.CaseTableValue;
import se.streamsource.streamflow.client.util.CommandTask;
import se.streamsource.streamflow.client.util.RefreshWhenShowing;
import se.streamsource.streamflow.client.util.i18n;
import se.streamsource.streamflow.client.util.table.SeparatorTable;
import se.streamsource.streamflow.infrastructure.event.domain.DomainEvent;
import se.streamsource.streamflow.infrastructure.event.domain.TransactionDomainEvents;
import se.streamsource.streamflow.infrastructure.event.domain.source.TransactionListener;
import se.streamsource.streamflow.infrastructure.event.domain.source.helper.EventParameters;
import se.streamsource.streamflow.infrastructure.event.domain.source.helper.Events;
import se.streamsource.streamflow.util.Strings;

import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.font.TextAttribute;
import java.awt.geom.Ellipse2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.TimeZone;

import static java.awt.RenderingHints.*;
import static java.lang.Integer.*;
import static se.streamsource.streamflow.client.util.i18n.*;
import static se.streamsource.streamflow.infrastructure.event.domain.source.helper.Events.*;

/**
 * Base class for all views of case lists.
 */
public class CasesTableView extends JPanel implements TransactionListener {
    @Structure
    Module module;

    public static final int MILLIS_IN_DAY = (1000 * 60 * 60 * 24);
    public static final WorkspaceResources[] dueGroups = { WorkspaceResources.overdue, WorkspaceResources.duetoday,
            WorkspaceResources.duetomorrow, WorkspaceResources.duenextweek, WorkspaceResources.duenextmonth,
            WorkspaceResources.later, WorkspaceResources.noduedate };

    private Comparator<CaseTableValue> groupingComparator = new Comparator<CaseTableValue>() {
        public int compare(CaseTableValue o1, CaseTableValue o2) {
            GroupBy groupBy = model.getGroupBy();
            switch (groupBy) {
            case caseType:
                return o1.caseType().get().compareTo(o2.caseType().get());
            case dueOn:
                return dueOnGroup(o1.dueOn().get()).compareTo(dueOnGroup(o2.dueOn().get()));
            case assignee:
                return o1.assignedTo().get().compareTo(o2.assignedTo().get());
            case project:
                return o1.owner().get().compareTo(o2.owner().get());
            case priority:
                Integer prio1 = o1.priority().get() != null ? o1.priority().get().priority().get()
                        : new Integer(9999);
                Integer prio2 = o2.priority().get() != null ? o2.priority().get().priority().get()
                        : new Integer(9999);
                return prio1.compareTo(prio2);

            default:
                return 0;
            }
        }
    };

    protected JXTable caseTable;
    protected CasesTableModel model;
    private TableFormat tableFormat;
    private ApplicationContext context;

    private PerspectiveView filter;

    public void init(final @Service ApplicationContext context, @Uses CasesTableModel casesTableModel,
            final @Uses TableFormat tableFormat, @Optional @Uses JTextField searchField) {
        setLayout(new BorderLayout());

        this.context = context;
        this.model = casesTableModel;
        this.tableFormat = tableFormat;

        ActionMap am = context.getActionMap(CasesTableView.class, this);
        setActionMap(am);
        MacOsUIWrapper.convertAccelerators(context.getActionMap(CasesTableView.class, this));

        // Filter
        filter = module.objectBuilderFactory().newObjectBuilder(PerspectiveView.class).use(model, searchField)
                .newInstance();
        add(filter, BorderLayout.NORTH);

        // Table
        // Trigger creation of filters and table model
        caseTable = new SeparatorTable(null) {
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);

                //  add custom rendering here
                EventTableModel model = (EventTableModel) getModel();
                if (model.getElementAt(row) instanceof CaseTableValue) {

                    Map attributes = c.getFont().getAttributes();
                    if (((CaseTableValue) model.getElementAt(row)).removed().get()) {
                        attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
                    } else if (((CaseTableValue) model.getElementAt(row)).unread().get()) {
                        attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
                    }
                    c.setFont(new Font(attributes));
                }

                return c;
            }
        };
        caseTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        caseTable.getActionMap().getParent().setParent(am);
        caseTable.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
                KeyboardFocusManager.getCurrentKeyboardFocusManager()
                        .getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
        caseTable.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
                KeyboardFocusManager.getCurrentKeyboardFocusManager()
                        .getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));

        caseTable.getActionMap().remove("column.horizontalScroll");
        caseTable.getActionMap().remove("column.packAll");
        caseTable.getActionMap().remove("column.packSelected");
        caseTable.setColumnControlVisible(true);

        caseTable.setModel(new EventJXTableModel<CaseTableValue>(model.getEventList(), tableFormat));

        model.addObserver(new Observer() {
            public void update(Observable o, Object arg) {
                if (model.getGroupBy() == GroupBy.none) {
                    caseTable.setModel(new EventJXTableModel<CaseTableValue>(model.getEventList(), tableFormat));
                } else {
                    SeparatorList<CaseTableValue> groupingList = new SeparatorList<CaseTableValue>(
                            model.getEventList(), groupingComparator, 1, 10000);
                    caseTable.setModel(new EventJXTableModel<CaseTableValue>(groupingList, tableFormat));
                }

                if (!model.containsCaseWithPriority()) {
                    model.addInvisibleColumn(8);
                }

                for (Integer invisibleCol : model.getInvisibleColumns()) {
                    TableColumnModelExt tm = (TableColumnModelExt) caseTable.getColumnModel();
                    if (tm.getColumnExt(invisibleCol).isVisible())
                        caseTable.getColumnExt(invisibleCol).setVisible(false);
                }

            }
        });

        caseTable.getColumn(0).setPreferredWidth(500);
        caseTable.getColumn(1).setPreferredWidth(70);
        caseTable.getColumn(1).setMaxWidth(70);
        caseTable.getColumn(1).setResizable(false);
        caseTable.getColumn(2).setPreferredWidth(300);
        caseTable.getColumn(2).setMaxWidth(300);
        caseTable.getColumn(3).setPreferredWidth(150);
        caseTable.getColumn(3).setMaxWidth(150);
        caseTable.getColumn(4).setPreferredWidth(90);
        caseTable.getColumn(4).setMaxWidth(90);
        caseTable.getColumn(5).setPreferredWidth(150);
        caseTable.getColumn(5).setMaxWidth(150);
        caseTable.getColumn(6).setPreferredWidth(90);
        caseTable.getColumn(6).setMaxWidth(90);
        caseTable.getColumn(7).setPreferredWidth(150);
        caseTable.getColumn(7).setMaxWidth(150);
        caseTable.getColumn(7).setResizable(false);
        caseTable.getColumn(8).setPreferredWidth(100);
        caseTable.getColumn(8).setMaxWidth(100);
        caseTable.getColumn(9).setMaxWidth(50);
        caseTable.getColumn(9).setResizable(false);

        caseTable.setAutoCreateColumnsFromModel(false);

        int count = 0;
        for (TableColumn c : caseTable.getColumns()) {
            c.setIdentifier((Integer) count);
            count++;

            c.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("visible".equals(evt.getPropertyName())) {
                        TableColumnExt columnExt = (TableColumnExt) evt.getSource();

                        if (columnExt.isVisible()) {
                            model.removeInvisibleColumn(columnExt.getModelIndex());
                        } else {
                            model.addInvisibleColumn(columnExt.getModelIndex());
                        }
                    }
                }
            });
        }

        JScrollPane caseScrollPane = new JScrollPane(caseTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        add(caseScrollPane, BorderLayout.CENTER);

        caseTable.setDefaultRenderer(Date.class, new DefaultTableRenderer(new StringValue() {
            private static final long serialVersionUID = 4782416330896582518L;

            public String getString(Object value) {
                return value != null ? DateFormats.getProgressiveDateTimeValue((Date) value, Locale.getDefault())
                        : "";
            }
        }));
        caseTable.setDefaultRenderer(ArrayList.class, new DefaultTableCellRenderer() {

            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                if (value == null)
                    return this;
                if (value instanceof SeparatorList.Separator)
                    return caseTable.getDefaultRenderer(SeparatorList.Separator.class)
                            .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

                JPanel renderer = new JPanel(new FlowLayout(FlowLayout.LEFT));

                ArrayList<String> icons = (ArrayList<String>) value;
                for (String icon : icons) {
                    ImageIcon image = i18n.icon(Icons.valueOf(icon), 11);
                    JLabel iconLabel = image != null ? new JLabel(image, SwingConstants.LEADING)
                            : new JLabel("   ");
                    renderer.add(iconLabel);
                }
                if (isSelected)
                    renderer.setBackground(table.getSelectionBackground());
                return renderer;
            }
        });
        caseTable.setDefaultRenderer(CaseStates.class, new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                if (value == null)
                    return this;

                EventTableModel model = (EventTableModel) table.getModel();
                boolean hasResolution = !Strings
                        .empty(((CaseTableValue) model.getElementAt(row)).resolution().get());
                boolean removed = ((CaseTableValue) model.getElementAt(row)).removed().get();

                String iconName = hasResolution
                        ? "case_status_withresolution_" + value.toString().toLowerCase() + "_icon"
                        : "case_status_" + value.toString().toLowerCase() + "_icon";

                iconName = removed ? "case_status_draft_icon" : iconName;

                JLabel renderedComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected,
                        hasFocus, row, column);
                renderedComponent.setHorizontalAlignment(SwingConstants.CENTER);
                setText(null);

                setIcon(i18n.icon(CaseResources.valueOf(iconName), i18n.ICON_16));
                setName(i18n
                        .text(CaseResources.valueOf("case_status_" + value.toString().toLowerCase() + "_text")));
                setToolTipText(i18n
                        .text(CaseResources.valueOf("case_status_" + value.toString().toLowerCase() + "_text")));

                return this;
            }
        });

        caseTable.setDefaultRenderer(PriorityValue.class, new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                final PriorityValue priority = (PriorityValue) value;
                String val = priority == null ? "" : priority.text().get();

                JPanel panel = new JPanel();
                FormLayout layout = new FormLayout("10dlu, 50dlu:grow", "pref");
                DefaultFormBuilder formBuilder = new DefaultFormBuilder(layout, panel);

                panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
                JLabel label = new JLabel() {
                    @Override
                    protected void paintComponent(Graphics g) {
                        Color color = getBackground();
                        if (priority != null) {
                            if (!Strings.empty(priority.color().get()))
                                color = new Color(parseInt(priority.color().get()));
                            else
                                color = Color.BLACK;
                        }
                        final Color FILL_COLOR = ColorUtil.removeAlpha(color);

                        Graphics2D g2 = (Graphics2D) g.create();

                        try {
                            g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
                            g2.setColor(Color.LIGHT_GRAY);
                            final int DIAM = Math.min(getWidth(), getHeight());
                            final int inset = 3;
                            g2.fill(new Ellipse2D.Float(inset, inset, DIAM - 2 * inset, DIAM - 2 * inset));
                            g2.setColor(FILL_COLOR);
                            final int border = 1;
                            g2.fill(new Ellipse2D.Float(inset + border, inset + border,
                                    DIAM - 2 * inset - 2 * border, DIAM - 2 * inset - 2 * border));
                        } finally {
                            g2.dispose();
                        }
                    }
                };
                label.setPreferredSize(new Dimension(10, 10));
                //label.setBorder( BorderFactory.createLineBorder( Color.RED ) );
                formBuilder.add((Strings.empty(val) || "-".equals(val)) ? new JLabel() : label, new CellConstraints(
                        1, 1, 1, 1, CellConstraints.FILL, CellConstraints.FILL, new Insets(0, 0, 0, 0)));
                JLabel text = new JLabel(val);
                //text.setBorder( BorderFactory.createLineBorder( Color.RED ) );
                formBuilder.add(text, new CellConstraints(2, 1, 1, 1, CellConstraints.LEFT, CellConstraints.FILL,
                        new Insets(0, 0, 0, 0)));

                if (isSelected) {
                    panel.setBackground(table.getSelectionBackground());
                    text.setForeground(table.getSelectionForeground());
                }
                return panel;
            }
        });
        caseTable.setDefaultRenderer(SeparatorList.Separator.class, new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object separator, boolean isSelected,
                    boolean hasFocus, int row, int column) {
                String value = "";
                boolean emptyDescription = false;
                switch (model.getGroupBy()) {
                case caseType:
                    emptyDescription = Strings.empty(
                            ((CaseTableValue) ((SeparatorList.Separator) separator).first()).caseType().get());
                    value = !emptyDescription
                            ? ((CaseTableValue) ((SeparatorList.Separator) separator).first()).caseType().get()
                            : text(WorkspaceResources.no_casetype);
                    break;
                case assignee:
                    emptyDescription = Strings.empty(
                            ((CaseTableValue) ((SeparatorList.Separator) separator).first()).assignedTo().get());
                    value = !emptyDescription
                            ? ((CaseTableValue) ((SeparatorList.Separator) separator).first()).assignedTo().get()
                            : text(WorkspaceResources.no_assignee);
                    break;
                case project:
                    emptyDescription = Strings
                            .empty(((CaseTableValue) ((SeparatorList.Separator) separator).first()).owner().get());
                    value = !emptyDescription
                            ? ((CaseTableValue) ((SeparatorList.Separator) separator).first()).owner().get()
                            : text(WorkspaceResources.no_project);
                    break;
                case dueOn:
                    value = text(dueGroups[dueOnGroup(
                            ((CaseTableValue) ((SeparatorList.Separator) separator).first()).dueOn().get())]);
                    break;
                case priority:
                    emptyDescription = ((CaseTableValue) ((SeparatorList.Separator) separator).first()).priority()
                            .get() == null
                            || Strings.empty(((CaseTableValue) ((SeparatorList.Separator) separator).first())
                                    .priority().get().color().get());
                    value = !emptyDescription ? ((CaseTableValue) ((SeparatorList.Separator) separator).first())
                            .priority().get().text().get() : text(WorkspaceResources.no_priority);
                    break;
                }

                Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
                        column);
                component.setFont(component.getFont().deriveFont(Font.BOLD + Font.ITALIC));
                component.setBackground(Color.lightGray);
                return component;
            }
        });

        AbstractHighlighter separatorHighlighter = (AbstractHighlighter) HighlighterFactory
                .createSimpleStriping(HighlighterFactory.QUICKSILVER);
        separatorHighlighter.setHighlightPredicate(
                new HighlightPredicate.TypeHighlightPredicate(SeparatorList.Separator.class));
        caseTable.addHighlighter(HighlighterFactory.createAlternateStriping());
        caseTable.addHighlighter(separatorHighlighter);

        addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent e) {
                caseTable.requestFocusInWindow();
            }
        });

        model.getEventList().addListEventListener(new ListEventListener<CaseTableValue>() {
            public void listChanged(ListEvent<CaseTableValue> listChanges) {
                // Synchronize lists
                Set<String> labels = new HashSet<String>();
                Set<String> assignees = new HashSet<String>();
                Set<String> projects = new HashSet<String>();
                for (CaseTableValue caseTableValue : listChanges.getSourceList()) {
                    for (LinkValue linkValue : caseTableValue.labels().get().links().get()) {
                        labels.add(linkValue.text().get());
                    }

                    assignees.add(caseTableValue.assignedTo().get());
                    projects.add(caseTableValue.owner().get());
                }
                List<String> sortedLabels = new ArrayList<String>(labels);
                List<String> sortedAssignees = new ArrayList<String>(assignees);
                List<String> sortedProjects = new ArrayList<String>(projects);
                Collections.sort(sortedLabels);
                Collections.sort(sortedAssignees);
                Collections.sort(sortedProjects);
                sortedLabels.add(0, text(WorkspaceResources.all));
                sortedAssignees.add(0, text(WorkspaceResources.all));
                sortedProjects.add(0, text(WorkspaceResources.all));
            }
        });

        addHierarchyListener(new HierarchyListener() {
            public void hierarchyChanged(HierarchyEvent e) {
                if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) > 0) {
                    if (CasesTableView.this.isShowing()) {
                        context.getActionMap().get("savePerspective").setEnabled(true);
                    }
                }
            }
        });
        new RefreshWhenShowing(this, model);
    }

    public JXTable getCaseTable() {
        return caseTable;
    }

    public CasesTableModel getModel() {
        return model;
    }

    private Integer dueOnGroup(Date date) {
        /**
         * 0 = Overdue
         * 1 = Today
         * 2 = Tomorrow
         * 3 = Within next week
         * 4 = Within next month
         * 5 = Later
         * 6 = No due date
         */

        long currentTime = System.currentTimeMillis();
        currentTime = currentTime / MILLIS_IN_DAY;
        currentTime *= MILLIS_IN_DAY;
        Date today = new Date(currentTime);
        Date lateToday = new Date(currentTime + MILLIS_IN_DAY - 1);

        Calendar month = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        month.setTime(today);
        month.add(Calendar.MONTH, 1);

        Calendar week = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        week.setTime(today);
        week.add(Calendar.WEEK_OF_YEAR, 1);

        Calendar tomorrow = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        tomorrow.setTime(lateToday);
        tomorrow.add(Calendar.DATE, 1);

        int group;
        if (date == null)
            group = 6;
        else if (date.after(month.getTime()))
            group = 5; // Later
        else if (date.after(week.getTime()))
            group = 4; // Within next month
        else if (date.after(tomorrow.getTime()))
            group = 3; // Within next week
        else if (date.after(lateToday))
            group = 2; // Tomorrow
        else if (date.after(today))
            group = 1;
        else
            group = 0;

        return group;
    }

    public void notifyTransactions(final Iterable<TransactionDomainEvents> transactions) {

        if (Events.matches(withNames("createdCase"), transactions)) {
            final DomainEvent event = Iterables
                    .first(Iterables.filter(withNames("createdCase"), Events.events(transactions)));
            ;

            context.getTaskService().execute(new CommandTask() {
                @Override
                protected void command() throws Exception {
                    model.refresh();
                }

                @Override
                protected void succeeded(Iterable<TransactionDomainEvents> transactionEventsIterable) {
                    super.succeeded(transactionEventsIterable);

                    TableModel model = caseTable.getModel();
                    boolean rowFound = false;

                    for (int i = 0, n = model.getRowCount(); i < n; i++) {
                        if (model.getValueAt(i, model.getColumnCount()).toString()
                                .endsWith(EventParameters.getParameter(event, "param1") + "/")) {
                            caseTable.getSelectionModel().setSelectionInterval(caseTable.convertRowIndexToView(i),
                                    caseTable.convertRowIndexToView(i));
                            caseTable.scrollRectToVisible(caseTable.getCellRect(i, 0, true));
                            rowFound = true;
                            break;
                        }
                    }
                }
            });
        } else if (Events.matches(withNames("addedLabel", "removedLabel", "changedDescription", "changedCaseType",
                "changedStatus", "changedOwner", "assignedTo", "unassigned", "changedRemoved", "deletedEntity",
                "updatedContact", "addedContact", "deletedContact", "createdConversation", "changedDueOn",
                "submittedForm", "createdAttachment", "removedAttachment", "changedPriority", "setUnread",
                "createdMessageFromDraft"), transactions)) {
            context.getTaskService().execute(new CommandTask() {
                @Override
                protected void command() throws Exception {

                    model.refresh();

                    if (Events.matches(
                            withNames("changedStatus", "changedOwner", "assignedTo", "unassigned", "deletedEntity"),
                            transactions)) {
                        caseTable.getSelectionModel().clearSelection();
                    }
                }
            });
        }
    }
}