ca.qc.cegepoutaouais.tge.pige.client.ui.view.NewLoanView.java Source code

Java tutorial

Introduction

Here is the source code for ca.qc.cegepoutaouais.tge.pige.client.ui.view.NewLoanView.java

Source

/*
 * Copyright 2010, 2011 Renaud Brub
 *
 * This file is part of PIGE.
 *
 * PIGE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PIGE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PIGE.  If not, see <http://www.gnu.org/licenses/>.
 */
package ca.qc.cegepoutaouais.tge.pige.client.ui.view;

import ca.qc.cegepoutaouais.tge.pige.client.LoanStatus;
import ca.qc.cegepoutaouais.tge.pige.client.services.UserServiceAsync;
import ca.qc.cegepoutaouais.tge.pige.client.services.exceptions.FrozenAccountException;
import ca.qc.cegepoutaouais.tge.pige.client.ui.AppEvents;
import ca.qc.cegepoutaouais.tge.pige.client.ui.AppWidgets;
import ca.qc.cegepoutaouais.tge.pige.client.PIGE;
import ca.qc.cegepoutaouais.tge.pige.client.PigeUtil;
import ca.qc.cegepoutaouais.tge.pige.client.resources.Resources;
import ca.qc.cegepoutaouais.tge.pige.client.services.ManagementServiceAsync;
import ca.qc.cegepoutaouais.tge.pige.client.ui.dialog.AbstractCEVDialog.CEV;
import ca.qc.cegepoutaouais.tge.pige.client.ui.dialog.ItemCEVDialog;
import ca.qc.cegepoutaouais.tge.pige.client.ui.widget.ItemSelectorField;
import ca.qc.cegepoutaouais.tge.pige.client.ui.widget.StatusBar;
import ca.qc.cegepoutaouais.tge.pige.dao.pojos.Item;
import ca.qc.cegepoutaouais.tge.pige.dao.pojos.Loan;
import ca.qc.cegepoutaouais.tge.pige.dao.pojos.Tag;
import ca.qc.cegepoutaouais.tge.pige.dao.pojos.UserDetail;
import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.core.Template;
import com.extjs.gxt.ui.client.data.BaseFilterPagingLoadConfig;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.BaseStringFilterConfig;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.FilterConfig;
import com.extjs.gxt.ui.client.data.LoadConfig;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.KeyListener;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.RowEditorEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Params;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid.ClicksToEdit;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.RowEditor;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.menu.AdapterMenuItem;
import com.extjs.gxt.ui.client.widget.menu.DateMenu;
import com.extjs.gxt.ui.client.widget.menu.HeaderMenuItem;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Vue permettant  l'usager d'effectuer des demandes d'emprunt.
 *
 * @author Renaud Brub
 */
public class NewLoanView extends BaseView {

    protected final String NEW_TAG_FLAG = "is-new";
    protected final Integer MAX_LOAN_PER_REQUEST = 20;
    protected final Integer PAGE_SIZE = 50;

    protected RpcProxy<PagingLoadResult<UserDetail>> proxy = null;
    protected BasePagingLoader<PagingLoadResult<ModelData>> loader = null;
    protected BaseFilterPagingLoadConfig loadConfig = null;
    protected Grid<BeanModel> grid = null;
    protected ListStore<BeanModel> loanStore = new ListStore<BeanModel>();
    protected Button addLoanBtn = null;
    protected Button saveLoanRequestBtn = null;
    protected final SimpleComboBox<String> tagCbox = new SimpleComboBox<String>();
    SimpleComboBox<String> menuTagCbox = new SimpleComboBox<String>();
    protected PagingToolBar pagingTB = null;
    protected final StatusBar statusBar = Registry.get(AppWidgets.APP_STATUS_BAR);
    protected final ToolBar actionTB = new ToolBar();

    //protected BeanModel lastCreatedModel = null;
    protected List<BeanModel> selectedLoans = null;

    protected final ItemSelectorField itemSelectorField = new ItemSelectorField();

    protected String descTemplateStr = "<div class=\"pige-description-column  {icon} \">"
            + "<span class=\"pige-description-column-text \">{desc}</span>" + "</div>";

    public NewLoanView(Controller controller) {
        super(controller, messages.createLoan());
    }

    @Override
    protected void handleEvent(AppEvent event) {
        super.handleEvent(event);
        EventType type = event.getType();
        if (type == AppEvents.NEW_LOAN_VIEW_EVENT) {
            onUpdateTagList(event);
            onActivateView();
        }
    }

    @Override
    protected void initialize() {
        super.initialize();

        proxy = new RpcProxy<PagingLoadResult<UserDetail>>() {

            @Override
            protected void load(Object loadConfig, final AsyncCallback<PagingLoadResult<UserDetail>> callback) {

                statusBar.setBusyText(messages.loading());

                UserServiceAsync rpcService = Registry.get(PIGE.USER_SERVICE);
                rpcService.getAllLoan((PagingLoadConfig) loadConfig, new AsyncCallback<PagingLoadResult<Loan>>() {

                    @Override
                    public void onSuccess(PagingLoadResult result) {
                        statusBar.getStatus().clearStatus(messages.loadDone());
                        callback.onSuccess(result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        callback.onFailure(caught);
                    }
                });

            }

        };

        loadConfig = new BaseFilterPagingLoadConfig();
        loader = new BasePagingLoader<PagingLoadResult<ModelData>>(proxy, new BeanModelReader()) {

            @Override
            protected LoadConfig newLoadConfig() {
                return loadConfig;
            }
        };
        loader.setRemoteSort(false);

        loanStore = new ListStore<BeanModel>(loader);

        pagingTB = new PagingToolBar(PAGE_SIZE);
        pagingTB.bind(loader);

        /*
         * TODO:
         *
         * VOIR LES MTHODES DES CELLEDITORS POUR AMLIORER LE COMPORTEMENT
         * DU ROWEDITOR. EX.: setCompleteEditOnEnter...
         */

        // Note: Les CellEditors ne gnrent pas d'vnement de type EditorEvent
        //  moins d'tre utiliss dans un EditorGrid.

        List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

        ColumnConfig quantityCC = new ColumnConfig(Loan.QUANTITY_REF, messages.quantity(), 50);
        NumberFormat nf = NumberFormat.getFormat(PIGE.QUANTITY_FORMAT);
        quantityCC.setNumberFormat(nf);
        NumberField numberField = new NumberField();
        numberField.setPropertyEditorType(Integer.class);
        numberField.setFormat(nf);
        numberField.setMinValue(new Integer(0));
        numberField.setAllowDecimals(Boolean.FALSE);
        numberField.setAllowNegative(Boolean.FALSE);
        numberField.setMaxLength(6);
        quantityCC.setEditor(new CellEditor(numberField));
        ;

        ColumnConfig descriptionCC = new ColumnConfig(Loan.DESCRIPTION_REF, messages.description(), 300);
        itemSelectorField.setAllowBlank(Boolean.FALSE);
        CellEditor descCCEditor = new CellEditor(itemSelectorField);
        descriptionCC.setEditor(descCCEditor);
        final Template descTemplate = new Template(descTemplateStr);
        descTemplate.compile();
        descriptionCC.setRenderer(new GridCellRenderer() {

            @Override
            public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex,
                    ListStore store, Grid grid) {
                Loan loan = (Loan) ((BeanModel) model).getBean();
                Params p = new Params();
                p.set("desc", model.get(property));
                if (loan.getItemId() != null) {
                    p.set("icon", "pige-icon-visible");
                } else {
                    p.set("icon", "pige-icon-hidden");
                }
                return descTemplate.applyTemplate(p);
            }
        });

        ColumnConfig termCC = new ColumnConfig(Loan.TERM_REF, messages.term(), 100);
        DateTimeFormat dtf = DateTimeFormat.getFormat(PIGE.TERM_DATE_FORMAT);
        termCC.setDateTimeFormat(dtf);
        DateField dateField = new DateField();
        dateField.setMinValue(new Date());
        dateField.setEditable(false);
        dateField.setFormatValue(true);
        dateField.getPropertyEditor().setFormat(dtf);
        termCC.setEditor(new CellEditor(dateField));

        ColumnConfig tagCC = new ColumnConfig(Loan.TAG_REF, messages.tag(), 100);
        tagCbox.setTriggerAction(TriggerAction.ALL);
        tagCbox.setAllowBlank(Boolean.FALSE);
        tagCbox.setForceSelection(Boolean.FALSE);
        tagCbox.setEditable(Boolean.TRUE);
        CellEditor tagCellEditor = new CellEditor(tagCbox) {

            @Override
            public Object preProcessValue(Object value) {
                if (value == null) {
                    return value;
                }
                ModelData model = tagCbox.findModel(value.toString());
                if (model != null) {
                    return model;
                }
                return new SimpleComboValueWrapper((String) value);
            }

            @Override
            public Object postProcessValue(Object value) {
                return tagCbox.getRawValue();
            }
        };
        tagCC.setEditor(tagCellEditor);

        configs.add(quantityCC);
        configs.add(descriptionCC);
        configs.add(termCC);
        configs.add(tagCC);

        ColumnModel cm = new ColumnModel(configs);

        final RowEditor<BeanModel> rowEditor = new RowEditor<BeanModel>() {

            @Override
            protected void createButtons() {
                super.createButtons();
                saveBtn.setText(BaseView.messages.ok());
            }

            // 1.5.0
            // Empcher que l'diteur soit fermer accidentellement lorsque
            // l'utilisateur appuie sur la touche "Entre" dans un des champs...
            // Continuer l'action que si tous les champs requis sont valides.
            @Override
            protected void onEnter(ComponentEvent ce) {
                if (isValid()) {
                    super.onEnter(ce);
                }
            }
        };

        rowEditor.setClicksToEdit(ClicksToEdit.TWO);

        rowEditor.addListener(Events.AfterEdit, new Listener<RowEditorEvent>() {

            @Override
            public void handleEvent(RowEditorEvent event) {
                BeanModel model = loanStore.getAt(event.getRowIndex());//1.4.0
                if (model != null) {
                    setLoanItem(model);
                    model.set(NEW_TAG_FLAG, Boolean.FALSE.toString());
                    loanStore.update(model);
                }
            }
        });
        rowEditor.addListener(Events.CancelEdit, new Listener<RowEditorEvent>() {

            @Override
            public void handleEvent(RowEditorEvent event) {
                BeanModel model = loanStore.getAt(event.getRowIndex()); //1.4.0
                if (model != null) {
                    Boolean isNew = Boolean
                            .parseBoolean((String) model.get(NEW_TAG_FLAG, Boolean.FALSE.toString()));
                    if (isNew) {
                        loanStore.remove(0);
                    }
                }
            }
        });

        // Permet de ractiver la barre de menu lorsque l'usager est en train
        // d'diter une range et qu'il appuie sur "Entr" ou "chap" pour
        // fermer l'diteur.
        Listener editorListener = new Listener<ComponentEvent>() {

            @Override
            public void handleEvent(ComponentEvent event) {
                actionTB.setEnabled(Boolean.TRUE);
            }
        };
        Listener editorListener2 = new Listener<ComponentEvent>() {

            @Override
            public void handleEvent(ComponentEvent event) {
                actionTB.setEnabled(Boolean.FALSE);
            }
        };
        rowEditor.addListener(Events.Hide, editorListener);
        rowEditor.addListener(Events.Show, editorListener2);

        grid = new Grid<BeanModel>(loanStore, cm);
        grid.setLoadMask(Boolean.FALSE);
        grid.setBorders(Boolean.FALSE);
        grid.setAutoExpandColumn(Loan.DESCRIPTION_REF);
        grid.getView().setAutoFill(Boolean.TRUE);
        grid.addPlugin(rowEditor);
        grid.setContextMenu(createContextMenu());
        grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener() {

            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                selectedLoans = event.getSelection();
            }
        });

        addLoanBtn = new Button(messages.addLoan());
        addLoanBtn.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.addLoanIcon()));
        addLoanBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent event) {
                Loan loan = new Loan();
                loan.setQuantity(1);
                loan.setDescription(messages.description());
                loan.setStartDate(new Date());
                loan.setTerm(new Date());// La mme journe!
                loan.setStatus(LoanStatus.STATUS_PENDING);
                BeanModelFactory factory = BeanModelLookup.get().getFactory(Loan.class);
                BeanModel bm = factory.createModel(loan);
                bm.set(NEW_TAG_FLAG, Boolean.TRUE.toString());
                //setLastCreatedLoan(bm);
                rowEditor.stopEditing(false);
                loanStore.insert(bm, 0);
                rowEditor.startEditing(loanStore.indexOf(bm), true);
                ColumnConfig cf = grid.getColumnModel().getColumnById(Loan.DESCRIPTION_REF);
                ItemSelectorField isf = (ItemSelectorField) cf.getEditor().getField();
                isf.clear();
                // Patch pour le bug #009
                actionTB.setEnabled(Boolean.FALSE);
            }
        });

        Button deleteLoanBtn = new Button(messages.deleteLoan());
        deleteLoanBtn.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.removeLoanIcon()));
        deleteLoanBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent event) {
                if (!validateLoanSelection()) {
                    return;
                }
                List<Loan> loans = new ArrayList();
                for (int i = 0; i < selectedLoans.size(); ++i) {
                    Loan l = (Loan) selectedLoans.get(i).getBean();
                    if (l.getStatus().equals(LoanStatus.STATUS_SAVED)) {
                        loans.add(l);
                    }
                }
                deleteSavedLoans(loans);
                for (BeanModel bm : selectedLoans) {
                    loanStore.remove(bm);
                }
            }
        });

        Button submitLoanRequest = new Button(messages.submitRequest());
        submitLoanRequest.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.loansApprovalIcon()));
        submitLoanRequest.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                Set lr = buildLoanRequest(Boolean.FALSE);
                if (lr != null) {
                    submitLoanRequest(lr, Boolean.FALSE);
                    resetLoanRequest();
                }
            }
        });

        Button resetLoanRequest = new Button(messages.clearAll());
        resetLoanRequest.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.emptyLoanIcon()));
        resetLoanRequest.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                List<Loan> loans = new ArrayList();
                for (int i = 0; i < loanStore.getCount(); ++i) {
                    Loan l = (Loan) loanStore.getAt(i).getBean();
                    if (l.getStatus().equals(LoanStatus.STATUS_SAVED)) {
                        loans.add(l);
                    }
                }
                deleteSavedLoans(loans);
                resetLoanRequest();
            }
        });

        saveLoanRequestBtn = new Button(messages.saveLoanRequest());
        saveLoanRequestBtn.setIcon(AbstractImagePrototype.create(Resources.INSTANCE.saveIcon()));
        saveLoanRequestBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                Set lr = buildLoanRequest(Boolean.TRUE);
                if (lr != null) {
                    submitLoanRequest(lr, Boolean.TRUE);
                }
            }
        });

        actionTB.add(addLoanBtn);
        actionTB.add(PigeUtil.createVerticalSeparator());
        actionTB.add(deleteLoanBtn);
        actionTB.add(PigeUtil.createVerticalSeparator());
        actionTB.add(submitLoanRequest);
        actionTB.add(PigeUtil.createVerticalSeparator());
        actionTB.add(saveLoanRequestBtn);
        actionTB.add(PigeUtil.createVerticalSeparator());
        actionTB.add(resetLoanRequest);
        actionTB.add(PigeUtil.createVerticalSeparator());

        contentPanel.setTopComponent(actionTB);
        contentPanel.setBottomComponent(pagingTB);// 1.2
        BorderLayoutData data = new BorderLayoutData(LayoutRegion.NORTH, 1);
        contentPanel.add(grid, data);
        ContentPanel panel = Registry.get(AppWidgets.APP_CONTENT_PANEL);
        panel.add(contentPanel);

        panel.layout();

        List<FilterConfig> filterConfigList = new ArrayList<FilterConfig>();
        loadConfig.set(PIGE.FILTER_CONFIGS, filterConfigList);
        FilterConfig fc = new BaseStringFilterConfig();
        fc.setField(Loan.STATUS_REF);
        fc.setValue(LoanStatus.STATUS_SAVED);
        filterConfigList.add(fc);
    }

    protected void onUpdateTagList(AppEvent event) {
        Set<Tag> tagSet = (Set) event.getData(PIGE.TAG_SET);
        PIGE.__assert(tagSet != null, "tagSet est null", getClass(), "onUpdateTagList()");
        tagCbox.removeAll();
        menuTagCbox.removeAll();

        // Populer la liste avec les libells par dfaut.
        tagCbox.add(messages.forHome());
        menuTagCbox.add(messages.forHome());

        // Populer la liste avec les libells dfinis par l'usager.
        for (Tag t : tagSet) {
            tagCbox.add(t.getName());
            menuTagCbox.add(t.getName());
        }
    }

    protected ListStore getLoanStore() {
        return loanStore;
    }

    protected Set<Loan> buildLoanRequest(Boolean save) {
        List<BeanModel> models = loanStore.getModels();
        if (models.size() <= 0) {
            MessageBox.info(messages.information(), messages.loanRequestIsEmpty(), null);
            return null;
        }
        Set<Loan> loanRequest = new HashSet();
        Loan loan;
        for (BeanModel bm : models) {
            loan = (Loan) bm.getBean();
            if (save) {
                loan.setStatus(LoanStatus.STATUS_SAVED);
            } else {
                loan.setStatus(LoanStatus.STATUS_PENDING);
            }
            loanRequest.add(loan);
        }
        return loanRequest;
    }

    protected void submitLoanRequest(Set<Loan> loanRequest, final Boolean save) {

        UserServiceAsync rpcService = Registry.get(PIGE.USER_SERVICE);
        rpcService.addLoans(loanRequest, new AsyncCallback() {

            @Override
            public void onSuccess(Object o) {
                StatusBar statusBar = Registry.get(AppWidgets.APP_STATUS_BAR);
                if (save) {
                    statusBar.setTimedText(messages.saveDone());
                } else {
                    statusBar.setTimedText(messages.loanRequestSent());
                }
                loader.load(0, PAGE_SIZE);
            }

            @Override
            public void onFailure(Throwable caught) {
                if (caught instanceof FrozenAccountException) {
                    MessageBox.alert(messages.warning(), messages.frozenAccountNotification(), null)
                            .setIcon(MessageBox.WARNING);
                } else {
                    PIGE.handleException(caught);
                }
            }
        });
    }

    protected void resetLoanRequest() {
        loanStore.removeAll();
    }

    protected void deleteSavedLoans(List<Loan> savedLoans) {
        UserServiceAsync rpcService = Registry.get(PIGE.USER_SERVICE);
        rpcService.deleteSavedLoans(savedLoans, new AsyncCallback() {

            @Override
            public void onSuccess(Object o) {
            }

            @Override
            public void onFailure(Throwable caught) {
                PIGE.handleException(caught);
            }
        });
    }

    private Boolean validateLoanSelection() {
        if (selectedLoans != null && selectedLoans.size() > 0) {
            return Boolean.TRUE;
        }
        MessageBox.info(messages.information(), messages.noLoanSelected(), null);
        return Boolean.FALSE;
    }

    @Override
    protected void onActivateView() {
        super.onActivateView();

        // 1.5.0
        // L'utilisateur sera averti que son compte est gel ds que la vue
        // sera charg.
        UserServiceAsync rpcService = Registry.get(PIGE.USER_SERVICE);
        rpcService.isUserFrozen(new AsyncCallback<Boolean>() {

            @Override
            public void onSuccess(Boolean frozen) {
                if (frozen) {
                    actionTB.setEnabled(Boolean.FALSE);
                    MessageBox.alert(messages.warning(), messages.frozenAccountNotification(), null)
                            .setIcon(MessageBox.WARNING);
                } else {
                    actionTB.setEnabled(Boolean.TRUE);
                    load();
                }
            }

            @Override
            public void onFailure(Throwable caught) {
                PIGE.handleException(caught);
            }
        });
    }

    protected void load() {
        loader.load(0, PAGE_SIZE);
    }

    protected void setLoanItem(BeanModel model) {
        if (model != null) {
            Loan loan = (Loan) model.getBean();
            Item item = itemSelectorField.getItem();
            if (item != null) {
                loan.setItemId(item.getId());
            }
        }
    }

    public BeanModel getSelectedLoan() {
        return selectedLoans.get(0);
    }

    protected Menu createContextMenu() {
        Menu contextMenu = new Menu();
        contextMenu.add(new HeaderMenuItem(messages.loanMenu()));
        MenuItem viewItemMenu = new MenuItem(messages.viewItem());
        viewItemMenu.addSelectionListener(new SelectionListener<MenuEvent>() {

            @Override
            public void componentSelected(MenuEvent e) {
                viewLoanItem();
            }
        });
        MenuItem unbindItemMenu = new MenuItem(messages.unbind());
        unbindItemMenu.addSelectionListener(new SelectionListener<MenuEvent>() {

            @Override
            public void componentSelected(MenuEvent e) {
                unbindItem();
            }
        });
        final DateMenu dateMenu = new DateMenu();
        dateMenu.getDatePicker().addListener(Events.Select, new Listener<ComponentEvent>() {

            @Override
            public void handleEvent(ComponentEvent ce) {
                //String d = DateTimeFormat.getFormat(PIGE.TERM_DATE_FORMAT)
                //.format(dateMenu.getDatePicker().getValue());
                changeLoanDate(dateMenu.getDate());
            }
        });
        MenuItem changeTermDateItemMenu = new MenuItem(messages.changeTermDate());
        changeTermDateItemMenu.setSubMenu(dateMenu);

        menuTagCbox.setTriggerAction(TriggerAction.ALL);
        menuTagCbox.setAllowBlank(Boolean.FALSE);
        menuTagCbox.setForceSelection(Boolean.FALSE);
        menuTagCbox.setEditable(Boolean.TRUE);

        AdapterMenuItem tagMenuAdapter = new AdapterMenuItem(menuTagCbox);
        tagMenuAdapter.setManageFocus(true);
        tagMenuAdapter.setCanActivate(true);
        menuTagCbox.addSelectionChangedListener(new SelectionChangedListener() {

            @Override
            public void selectionChanged(SelectionChangedEvent se) {
                String value = (String) se.getSelectedItem().get("value");
                changeLoanTag(value);
            }
        });
        menuTagCbox.addKeyListener(new KeyListener() {

            @Override
            public void componentKeyUp(ComponentEvent event) {
                super.componentKeyUp(event);
                if (event.getKeyCode() == KeyCodes.KEY_ENTER) {
                    changeLoanTag(menuTagCbox.getRawValue());
                }
            }
        });

        contextMenu.add(viewItemMenu);
        contextMenu.add(unbindItemMenu);
        contextMenu.add(new SeparatorMenuItem());
        contextMenu.add(changeTermDateItemMenu);
        contextMenu.add(tagMenuAdapter);

        contextMenu.addListener(Events.Show, new Listener() {

            @Override
            public void handleEvent(BaseEvent be) {
                menuTagCbox.clear();
            }
        });

        return contextMenu;
    }

    protected void unbindItem() {
        if (!validateLoanSelection()) {
            return;
        }
        Loan loan = (Loan) getSelectedLoan().getBean();
        Integer itemId = loan.getItemId();
        if (itemId == null) {
            MessageBox.info(messages.information(), messages.noAssociatedItem(), null);
            return;
        }
        doUnbindItem(loan);
    }

    protected void doUnbindItem(final Loan loan) {
        PIGE.__assert(loan != null, "loan == null", getClass(), "doUnbindItem");
        loan.setItemId(null);
        if (!loan.getStatus().equals(LoanStatus.STATUS_SAVED)) {
            loanStore.update(getSelectedLoan());
            return;
        }
        ManagementServiceAsync rpcService = (ManagementServiceAsync) Registry.get(PIGE.MANAGEMENT_SERVICE);
        rpcService.updateLoans(Arrays.asList(loan), new AsyncCallback() {

            @Override
            public void onSuccess(Object o) {
                loanStore.update(getSelectedLoan());
            }

            @Override
            public void onFailure(Throwable caught) {
                PIGE.handleException(caught);
            }
        });
    }

    protected void viewLoanItem() {
        if (!validateLoanSelection()) {
            return;
        }
        Loan loan = (Loan) getSelectedLoan().getBean();
        Integer itemId = loan.getItemId();
        if (itemId == null) {
            MessageBox.info(messages.information(), messages.noAssociatedItem(), null);
            return;
        }
        doViewLoanItem(itemId);
    }

    protected void doViewLoanItem(Integer itemId) {
        if (itemId == null) {
            return;
        }
        ManagementServiceAsync rpcService = (ManagementServiceAsync) Registry.get(PIGE.MANAGEMENT_SERVICE);
        rpcService.getItemById(itemId, new AsyncCallback<Item>() {

            @Override
            public void onSuccess(Item item) {
                if (item != null) {
                    ItemCEVDialog dialog = new ItemCEVDialog(CEV.VIEW);
                    dialog.setData("item", item);
                    dialog.showDialog();
                }
            }

            @Override
            public void onFailure(Throwable caught) {
                PIGE.handleException(caught);
            }
        });
    }

    protected void changeLoanDate(Date date) {
        if (!validateLoanSelection()) {
            return;
        }
        doChangeLoanData(selectedLoans, date);
    }

    /*protected void doChangeLoanDate(final List<BeanModel> models, Date date) {
        
    //PIGE.__assert(loan != null, "loan == null", getClass(), "doUnbindItem");
    Loan loan;
    BeanModel bm;
    List<Loan> loans = new ArrayList();
    Iterator<BeanModel> itr = new ArrayList(models).iterator();
    while (itr.hasNext()) {
        bm = itr.next();
        loan = (Loan) bm.getBean();
        //loan.setTerm(DateTimeFormat.getFormat(PIGE.TERM_DATE_FORMAT)
        //        .parse(date));
        loan.setTerm(date);
        if (!loan.getStatus().equals(LoanStatus.STATUS_SAVED)) {
            loanStore.update(bm);
            itr.remove();
        } else {
            loans.add(loan);
        }
    }
    ManagementServiceAsync rpcService =
            (ManagementServiceAsync) Registry.get(PIGE.MANAGEMENT_SERVICE);
    rpcService.updateLoans(loans, new AsyncCallback() {
        
        @Override
        public void onSuccess(Object o) {
            for (BeanModel bm : models) {
                loanStore.update(bm);
            }
        }
        
        @Override
        public void onFailure(Throwable caught) {
            PIGE.handleException(caught);
        }
    });
    }
    */
    protected void changeLoanTag(String tag) {
        if (!validateLoanSelection()) {
            return;
        }
        doChangeLoanData(selectedLoans, tag);
    }

    protected void doChangeLoanData(final List<BeanModel> models, Object value) {
        Loan loan;
        BeanModel bm;
        List<Loan> loans = new ArrayList();
        Iterator<BeanModel> itr = new ArrayList(models).iterator();
        while (itr.hasNext()) {
            bm = itr.next();
            loan = (Loan) bm.getBean();
            if (value instanceof String) {
                loan.setTag((String) value);
            } else if (value instanceof Date) {
                loan.setTerm((Date) value);
            } else {
                PIGE.__assert(false, "value n'est pas une date ou une string", getClass(), "doChangeLoanData");
            }
            if (!loan.getStatus().equals(LoanStatus.STATUS_SAVED)) {
                loanStore.update(bm);
                itr.remove();
            } else {
                loans.add(loan);
            }
        }
        if (loans.size() <= 0) {
            return;
        }
        ManagementServiceAsync rpcService = (ManagementServiceAsync) Registry.get(PIGE.MANAGEMENT_SERVICE);
        rpcService.updateLoans(loans, new AsyncCallback() {

            @Override
            public void onSuccess(Object o) {
                for (BeanModel bm : models) {
                    loanStore.update(bm);
                }
            }

            @Override
            public void onFailure(Throwable caught) {
                PIGE.handleException(caught);
            }
        });
    }

}