org.openelis.modules.attachment.client.IssuesTabUI.java Source code

Java tutorial

Introduction

Here is the source code for org.openelis.modules.attachment.client.IssuesTabUI.java

Source

/**
 * Exhibit A - UIRF Open-source Based Public Software License.
 * 
 * The contents of this file are subject to the UIRF Open-source Based Public
 * Software License(the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * openelis.uhl.uiowa.edu
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is OpenELIS code.
 * 
 * The Initial Developer of the Original Code is The University of Iowa.
 * Portions created by The University of Iowa are Copyright 2006-2008. All
 * Rights Reserved.
 * 
 * Contributor(s): ______________________________________.
 * 
 * Alternatively, the contents of this file marked "Separately-Licensed" may be
 * used under the terms of a UIRF Software license ("UIRF Software License"), in
 * which case the provisions of a UIRF Software License are applicable instead
 * of those above.
 */
package org.openelis.modules.attachment.client;

import static org.openelis.ui.screen.Screen.ShortKeys.*;
import static org.openelis.ui.screen.State.*;

import java.util.ArrayList;
import java.util.HashMap;

import org.openelis.constants.Messages;
import org.openelis.domain.AttachmentIssueViewDO;
import org.openelis.modules.attachment.client.AttachmentIssueEvent.Action;
import org.openelis.ui.event.DataChangeEvent;
import org.openelis.ui.event.StateChangeEvent;
import org.openelis.ui.screen.AsyncCallbackUI;
import org.openelis.ui.screen.Screen;
import org.openelis.ui.screen.ScreenHandler;
import org.openelis.ui.screen.State;
import org.openelis.ui.widget.Button;
import org.openelis.ui.widget.table.Row;
import org.openelis.ui.widget.table.Table;
import org.openelis.ui.widget.table.event.BeforeCellEditedEvent;
import org.openelis.ui.widget.table.event.BeforeCellEditedHandler;
import org.openelis.ui.widget.table.event.CellEditedEvent;
import org.openelis.ui.widget.table.event.CellEditedHandler;
import org.openelis.ui.widget.table.event.UnselectionEvent;
import org.openelis.ui.widget.table.event.UnselectionHandler;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.VisibleEvent;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;

public class IssuesTabUI extends Screen {
    @UiTemplate("IssuesTab.ui.xml")
    interface IssuesTabUIBinder extends UiBinder<Widget, IssuesTabUI> {
    };

    private static IssuesTabUIBinder uiBinder = GWT.create(IssuesTabUIBinder.class);

    @UiField
    protected Button updateButton, deleteButton, commitButton, abortButton, displayButton, refreshButton;

    @UiField
    protected Table table;

    protected AsyncCallbackUI<ArrayList<AttachmentIssueViewDO>> fetchIssuesCall;

    protected AsyncCallbackUI<AttachmentIssueViewDO> fetchForUpdateCall, updateCall, unlockCall;

    protected AsyncCallback<Void> deleteCall;

    protected Screen parentScreen, screen1;

    protected EventBus parentBus;

    protected boolean autoLoadIssues, lockForUpdate, lockForDelete;

    protected AttachmentIssueViewDO removed;

    protected ArrayList<AttachmentIssueViewDO> issueList;

    protected HashMap<Integer, AttachmentIssueViewDO> issueMap;

    public IssuesTabUI(Screen parentScreen) {
        this.parentScreen = parentScreen;
        this.parentBus = parentScreen.getEventBus();
        initWidget(uiBinder.createAndBindUi(this));
        initialize();

        autoLoadIssues = true;
    }

    protected void initialize() {
        screen1 = this;
        //
        // button panel buttons
        //
        addStateChangeHandler(new StateChangeEvent.Handler() {
            public void onStateChange(StateChangeEvent event) {
                updateButton.setEnabled(isState(UPDATE, DISPLAY));
                if (isState(UPDATE)) {
                    updateButton.lock();
                    updateButton.setPressed(true);
                }
            }
        });
        addShortcut(updateButton, 'u', CTRL);

        addStateChangeHandler(new StateChangeEvent.Handler() {
            public void onStateChange(StateChangeEvent event) {
                deleteButton.setEnabled(isState(DELETE, DISPLAY));
                if (isState(DELETE)) {
                    deleteButton.lock();
                    deleteButton.setPressed(true);
                }
            }
        });

        addShortcut(deleteButton, 'd', CTRL);

        addStateChangeHandler(new StateChangeEvent.Handler() {
            public void onStateChange(StateChangeEvent event) {
                commitButton.setEnabled(isState(UPDATE, DELETE));
            }
        });
        addShortcut(commitButton, 'm', CTRL);

        addStateChangeHandler(new StateChangeEvent.Handler() {
            public void onStateChange(StateChangeEvent event) {
                abortButton.setEnabled(isState(UPDATE, DELETE));
            }
        });
        addShortcut(abortButton, 'o', CTRL);

        addScreenHandler(table, "table", new ScreenHandler<ArrayList<Row>>() {
            public void onDataChange(DataChangeEvent event) {
                loadTable();
            }

            public void onStateChange(StateChangeEvent event) {
                table.setEnabled(true);
            }

            public Widget onTab(boolean forward) {
                return forward ? displayButton : refreshButton;
            }
        });

        table.addUnselectionHandler(new UnselectionHandler<Integer>() {
            public void onUnselection(UnselectionEvent<Integer> event) {
                /*
                 * the selected row is not allowed to be unselected in Update or
                 * Delete states because its manager is locked
                 */
                if (isState(UPDATE, DELETE))
                    event.cancel();
            }
        });

        table.addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
            public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
                /*
                 * no other row is allowed to be selected in Update or Delete
                 * states because the selected row's manager is locked
                 */
                if (isState(UPDATE, DELETE))
                    event.cancel();
            }
        });

        table.addBeforeCellEditedHandler(new BeforeCellEditedHandler() {
            @Override
            public void onBeforeCellEdited(BeforeCellEditedEvent event) {
                if (event.getCol() != 2 || !isState(UPDATE))
                    event.cancel();
            }
        });

        table.addCellEditedHandler(new CellEditedHandler() {
            @Override
            public void onCellUpdated(CellEditedEvent event) {
                int r, c;
                Object val;
                AttachmentIssueViewDO data;

                r = event.getRow();
                c = event.getCol();

                val = table.getValueAt(r, c);
                data = table.getRowAt(r).getData();

                switch (c) {
                case 2:
                    data.setText((String) val);
                    break;
                }
            }
        });

        addScreenHandler(displayButton, "displayButton", new ScreenHandler<ArrayList<Row>>() {
            public void onStateChange(StateChangeEvent event) {
                displayButton.setEnabled(isState(UPDATE, DISPLAY));
            }

            public Widget onTab(boolean forward) {
                return forward ? refreshButton : refreshButton;
            }
        });

        addScreenHandler(refreshButton, "refreshButton", new ScreenHandler<ArrayList<Row>>() {
            public void onStateChange(StateChangeEvent event) {
                refreshButton.setEnabled(isState(DEFAULT, DISPLAY));
            }

            public Widget onTab(boolean forward) {
                return forward ? table : displayButton;
            }
        });

        addVisibleHandler(new VisibleEvent.Handler() {
            public void onVisibleOrInvisible(VisibleEvent event) {
                if (event.isVisible() && autoLoadIssues) {
                    issueList = null;
                    issueMap = null;
                    autoLoadIssues = false;
                    fireAttachmentIssue(AttachmentIssueEvent.Action.FETCH, null);
                }
            }
        });

        parentBus.addHandler(AttachmentIssueEvent.getType(), new AttachmentIssueEvent.Handler() {
            @Override
            public void onAttachmentIssue(AttachmentIssueEvent event) {
                int r;
                Row row;
                AttachmentIssueViewDO data;

                if (parentScreen != event.getSource())
                    return;

                /*
                 * the tab fires events to the main screen to request it to do
                 * various operations e.g. fetch, lock, unlock etc; that's
                 * because the main screen maintains the data structures used by
                 * all tabs; if the operation was successful, the main screen
                 * fires an event to let the tab know; that event is handled
                 * here; the tab can find out if this event was fired to respond
                 * to a previous event fired by it or some other tab by checking
                 * if it's the event's "originalSource"; it can then perform
                 * some operation or ignore the event
                 */
                r = table.getSelectedRow();
                row = null;
                if (r >= 0)
                    row = table.getRowAt(r);

                issueList = event.getIssueList();
                issueMap = event.getIssueMap();
                data = null;
                switch (event.getAction()) {
                case FETCH:
                case ADD:
                case UPDATE:
                case DELETE:
                    /*
                     * attachment issues were fetched, added etc; refresh
                     * the tab; find which attachment issue is selected in
                     * the table before reloading the table
                     */
                    if (row != null)
                        data = row.getData();
                    loadTable();
                    refresh(data);
                    break;
                case LOCK:
                    if (screen1 == event.getOriginalSource()) {
                        /*
                         * an issue is locked to be updated or deleted;
                         * refresh the tab to show the latest data; set the
                         * state based on which operation is to be performed
                         */
                        if (lockForUpdate) {
                            setState(UPDATE);
                            data = issueMap.get(event.getAttachmentId());
                            row.setData(data);
                            table.setValueAt(r, 2, data.getText());
                            table.startEditing(r, 2);
                        } else if (lockForDelete) {
                            setState(DELETE);
                            table.removeRowAt(r);
                        }
                    }
                    break;
                case UNLOCK:
                    if (screen1 == event.getOriginalSource()) {
                        /*
                         * an issue was unlocked;refresh the tab to show the
                         * previously deleted or changed issues again
                         */
                        if (removed != null)
                            removed = null;
                        data = issueMap.get(event.getAttachmentId());
                        loadTable();
                        refresh(data);
                        lockForUpdate = false;
                        lockForDelete = false;
                    }
                    break;
                }
            }
        });
    }

    /**
     * Puts the screen in update state and locks the selected attachment
     */
    @UiHandler("updateButton")
    protected void update(ClickEvent event) {
        AttachmentIssueViewDO data;

        lockForUpdate = true;
        data = table.getRowAt(table.getSelectedRow()).getData();

        fireAttachmentIssue(AttachmentIssueEvent.Action.LOCK, data.getAttachmentId());
    }

    /**
     * Puts the screen in delete state and locks the selected attachment
     */
    @UiHandler("deleteButton")
    protected void delete(ClickEvent event) {
        lockForDelete = true;
        removed = table.getRowAt(table.getSelectedRow()).getData();

        fireAttachmentIssue(AttachmentIssueEvent.Action.LOCK, removed.getAttachmentId());
    }

    /**
     * Validates the data on the screen and based on the current state, and
     * calls the service method to commit the data on the screen, to the
     * database. Shows any errors/warnings encountered during the commit,
     * otherwise refreshes the tree with the committed data.
     */
    @UiHandler("commitButton")
    protected void commit(ClickEvent event) {
        finishEditing();

        if (validate().getStatus() == Validation.Status.ERRORS) {
            parentScreen.setError(Messages.get().gen_correctErrors());
            return;
        }

        switch (state) {
        case UPDATE:
            commitUpdate();
            break;
        case DELETE:
            commitDelete();
            break;
        }
    }

    /**
     * Commits the data on the screen to the database; shows any errors/warnings
     * encountered during the commit, otherwise loads the screen with the
     * committed data; if the checkbox for the attachment was checked i.e. it
     * was locked by this user before Update was clicked, tries to lock it
     * again, because update removes the lock in the back-end
     */
    protected void commitUpdate() {
        Row row;
        AttachmentIssueViewDO data;

        row = table.getRowAt(table.getSelectedRow());
        data = row.getData();
        fireAttachmentIssue(AttachmentIssueEvent.Action.UPDATE, data.getAttachmentId());
    }

    /**
     * Commits the data on the screen to the database; shows any errors/warnings
     * encountered during the commit, otherwise loads the screen with the
     * committed data; if the checkbox for the attachment was checked i.e. it
     * was locked by this user before Update was clicked, tries to lock it
     * again, because update removes the lock in the back-end
     */
    protected void commitDelete() {
        fireAttachmentIssue(AttachmentIssueEvent.Action.DELETE, removed.getAttachmentId());
    }

    /**
     * Returns the tab's current state
     */
    public State getState() {
        return state;
    }

    /**
     * Reverts any changes made to the data on the screen and disables editing
     * of the widgets; if the checkbox for the attachment was checked i.e. it
     * was locked by this user before Update was clicked, tries to lock it
     * again, because the unlock removes the lock in the back-end
     */
    @UiHandler("abortButton")
    protected void abort(ClickEvent event) {
        Row row;
        AttachmentIssueViewDO data;

        finishEditing();
        clearErrors();

        if (isState(DELETE)) {
            data = removed;
        } else {
            row = table.getRowAt(table.getSelectedRow());
            data = row.getData();
        }

        fireAttachmentIssue(AttachmentIssueEvent.Action.UNLOCK, data.getAttachmentId());
    }

    /**
     * Opens the file linked to the attachment showing in the selected row
     */
    @UiHandler("displayButton")
    protected void displayAttachment(ClickEvent event) {
        Row row;
        AttachmentIssueViewDO data;

        row = table.getRowAt(table.getSelectedRow());
        data = row.getData();
        parentBus.fireEventFromSource(new DisplayAttachmentEvent(data.getAttachmentId(), true), screen1);
    }

    @UiHandler("refreshButton")
    protected void refresh(ClickEvent event) {
        issueList = null;
        issueMap = null;
        fireAttachmentIssue(AttachmentIssueEvent.Action.FETCH, null);
    }

    private void loadTable() {
        Row row;
        ArrayList<Row> model;

        if (issueList == null) {
            table.setModel(null);
            return;
        }

        model = new ArrayList<Row>();
        for (AttachmentIssueViewDO data : issueList) {
            row = new Row(4);
            row.setCell(0, data.getSystemUserLoginName());
            row.setCell(1, data.getTimestamp());
            row.setCell(2, data.getText());
            row.setCell(3, data.getAttachmentDescription());
            row.setData(data);

            model.add(row);
        }

        table.setModel(model);
    }

    /**
     * Fires an AttachmentIssueEvent to the main screen to request it to do
     * various operations e.g. fetch, lock, unlock etc. for an attachment issue;
     * the operation is specified by "action" and "attachmentId" is used by the
     * main screen to find the attachment issue
     */
    private void fireAttachmentIssue(Action action, Integer attachmentId) {
        parentBus.fireEventFromSource(new AttachmentIssueEvent(action, attachmentId, null, null, screen1), this);
    }

    /**
     * If the passed issue is still in the table, selects the row that's showing
     * it; otherwise, selects the first row; sets the state to Display if there
     * are any rows in the table, so that they can be updated or deleted; sets
     * the state to Default otherwise
     */
    private void refresh(AttachmentIssueViewDO data) {
        int i, j;
        AttachmentIssueViewDO tdata;

        if (table.getRowCount() > 0) {
            i = 0;
            if (data != null) {
                for (j = 0; j < table.getRowCount(); j++) {
                    tdata = table.getRowAt(j).getData();
                    if (data.getAttachmentId().equals(tdata.getAttachmentId())) {
                        i = j;
                        break;
                    }
                }
            }
            table.selectRowAt(i);
            setState(DISPLAY);
        } else {
            setState(DEFAULT);
        }
    }
}