view flys-client/src/main/java/de/intevation/flys/client/client/ui/ThemePanel.java @ 1310:c4c957a9c092

Improved exception handling while fetching theme styles. flys-client/trunk@2944 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 12 Oct 2011 09:34:38 +0000
parents a95e82d6bcc1
children 8a93fb299e64
line wrap: on
line source
package de.intevation.flys.client.client.ui;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.EditCompleteEvent;
import com.smartgwt.client.widgets.grid.events.EditCompleteHandler;
import com.smartgwt.client.widgets.grid.events.RowContextClickEvent;
import com.smartgwt.client.widgets.grid.events.RowContextClickHandler;
import com.smartgwt.client.widgets.menu.Menu;
import com.smartgwt.client.widgets.menu.MenuItem;
import com.smartgwt.client.widgets.menu.events.ClickHandler;
import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;

import de.intevation.flys.client.shared.model.Collection;
import de.intevation.flys.client.shared.model.CollectionItemAttribute;
import de.intevation.flys.client.shared.model.FacetRecord;
import de.intevation.flys.client.shared.model.OutputMode;
import de.intevation.flys.client.shared.model.Theme;
import de.intevation.flys.client.shared.model.ThemeList;

import de.intevation.flys.client.client.Config;
import de.intevation.flys.client.client.FLYSConstants;
import de.intevation.flys.client.client.event.HasOutputParameterChangeHandlers;
import de.intevation.flys.client.client.event.HasRedrawRequestHandlers;
import de.intevation.flys.client.client.event.OnMoveEvent;
import de.intevation.flys.client.client.event.OnMoveHandler;
import de.intevation.flys.client.client.event.OutputParameterChangeEvent;
import de.intevation.flys.client.client.event.OutputParameterChangeHandler;
import de.intevation.flys.client.client.event.RedrawRequestHandler;
import de.intevation.flys.client.client.event.RedrawRequestEvent;
import de.intevation.flys.client.client.event.RedrawRequestEvent.Type;
import de.intevation.flys.client.client.services.CollectionAttributeService;
import de.intevation.flys.client.client.services.CollectionAttributeServiceAsync;
import de.intevation.flys.client.client.services.CollectionItemAttributeService;
import de.intevation.flys.client.client.services.CollectionItemAttributeServiceAsync;


public abstract class ThemePanel
extends               Canvas
implements            OnMoveHandler,
                      EditCompleteHandler,
                      HasOutputParameterChangeHandlers,
                      HasRedrawRequestHandlers
{
    protected CollectionAttributeServiceAsync updater =
        GWT.create(CollectionAttributeService.class);

    /** The service used to get collection item attributes. */
    protected CollectionItemAttributeServiceAsync itemAttributeService =
        GWT.create(CollectionItemAttributeService.class);

    private FLYSConstants MSG = GWT.create(FLYSConstants.class);

    /** List of OutParameterChangedHandler. */
    protected List<OutputParameterChangeHandler> outHandlers;
    /** List of ChartShallRedrawHandler. */
    protected List<RedrawRequestHandler> redrawRequestHandlers;

    protected Collection collection;
    protected OutputMode mode;

    protected ThemeNavigationPanel navigation;
    protected ListGrid list;

    /** The collection view*/
    protected CollectionView view;


    /**
     * Setup Grid, navigation bar.
     * @param collection Collection for which to show themes.
     */
    public ThemePanel(Collection collection, OutputMode mode) {
        this.collection  = collection;
        this.mode        = mode;
        this.list        = createGrid();

        this.redrawRequestHandlers = new ArrayList<RedrawRequestHandler>();
        this.outHandlers = new ArrayList<OutputParameterChangeHandler>();
        this.navigation  = new ThemeNavigationPanel();
        this.navigation.addOnMoveHandler(this);
    }


    public abstract void activateTheme(Theme theme, boolean active);


    /**
     * Replace the current collection with a new one. <b>NOTE: this operation
     * triggers updateGrid() which modifies the themes in the grid.</b>
     *
     * @param collection The new collection object.
     */
    protected void setCollection(Collection collection) {
        this.collection = collection;

        updateGrid();
    }


    /**
     * Returns the ThemeList of the current collection and output mode.
     *
     * @return the current ThemeList.
     */
    public ThemeList getThemeList() {
        return collection.getThemeList(mode.getName());
    }


    /**
     * Registers a new OutputParameterChangeHandler.
     *
     * @param h The new handler.
     */
    public void addOutputParameterChangeHandler(OutputParameterChangeHandler h){
        if (h != null) {
            outHandlers.add(h);
        }
    }


    /**
     * Registers a RedrawRequestHandler.
     *
     * @param h The new handler.
     */
    public void addRedrawRequestHandler(RedrawRequestHandler h){
        if (h != null) {
            redrawRequestHandlers.add(h);
        }
    }


    /**
     * Request a redraw of e.g. a Chart.
     */
    protected void requestRedraw() {
        for (RedrawRequestHandler handler: redrawRequestHandlers) {
            handler.onRedrawRequest(new RedrawRequestEvent(Type.RESET));
        }
    }


    /**
     * Called when the attribution of an output changed. It informs the
     * registered handlers about the changes.
     */
    protected void fireOutputParameterChanged() {
        OutputParameterChangeEvent evt = new OutputParameterChangeEvent();

        for (OutputParameterChangeHandler handler: outHandlers) {
            handler.onOutputParameterChanged(evt);
        }
    }


    public void setCollectionView(CollectionView view) {
        this.view = view;
    }


    /**
     * This method is used to clear the current theme grid and add new updated
     * data.
     */
    protected void updateGrid() {
        GWT.log("ThemePanel.updateGrid");

        clearGrid();

        ThemeList themeList = getThemeList();

        if (themeList == null) {
            GWT.log("ERROR: No theme list.");
            return;
        }

        int count = themeList.getThemeCount();

        for (int i = 1; i <= count; i++) {
            Theme theme = themeList.getThemeAt(i);

            if (theme == null) {
                continue;
            }

            list.addData(new FacetRecord(theme));
        }

        fireOutputParameterChanged();
    }


    /**
     * This method triggers the CollectionAttributeService. Based on the current
     * collectin settings, the attribute of the collection is modified or not.
     * But in every case, we will get a new collection object - which might be
     * the same as the current one.
     */
    public void updateCollection() {
        final Config config = Config.getInstance();
        final String url    = config.getServerUrl();
        final String loc    = config.getLocale();

        GWT.log("ThemePanel.updateCollection via RPC now");

        // don't forget to enable the panel after the request has finished!
        disable();

        updater.update(collection, url, loc, new AsyncCallback<Collection>() {
            public void onFailure(Throwable caught) {
                GWT.log("Could not update collection attributes.");
                SC.warn(MSG.getString(caught.getMessage()));

                enable();
            }


            public void onSuccess(Collection collection) {
                setCollection(collection);

                enable();
            }
        });
    }


    /**
     * Create and configure the Grid to display.
     */
    protected ListGrid createGrid() {
        ListGrid grid =  new ListGrid();
        grid.addRowContextClickHandler(new RowContextClickHandler() {
            public void onRowContextClick(RowContextClickEvent event) {
                ListGridRecord[] records = list.getSelection();

                Menu menu = null;

                if (records == null || records.length == 0) {
                    return;
                }
                else if (records.length == 1) {
                    menu = getSingleContextMenu(records);
                }
                else if (records.length > 1) {
                    menu = getMultiContextMenu(records);
                }

                if (menu != null) {
                    list.setContextMenu(menu);
                    menu.showContextMenu();

                    event.cancel();
                }
            }
        });

        return grid;
    }


    /**
     * A method that removes all records from theme grid.
     */
    protected void clearGrid() {
        ListGridRecord[] records = list.getRecords();

        if (records == null || records.length == 0) {
            return;
        }

        for (ListGridRecord record: records) {
            list.removeData(record);
        }
    }


    protected Menu getSingleContextMenu(final ListGridRecord[] records) {
        Menu menu = new Menu();

        menu.addItem(createActivateItem(records));
        menu.addItem(createDeactivateItem(records));
        menu.addItem(createRemoveItem(records));
        menu.addItem(createPropertiesItem(records));

        return menu;
    }


    protected Menu getMultiContextMenu(final ListGridRecord[] records) {
        Menu menu = new Menu();

        menu.addItem(createActivateItem(records));
        menu.addItem(createDeactivateItem(records));
        menu.addItem(createRemoveItem(records));

        return menu;
    }


    protected MenuItem createPropertiesItem(final ListGridRecord[] records) {
        MenuItem properties = new MenuItem(MSG.properties());

        properties.addClickHandler(new ClickHandler() {
            public void onClick(MenuItemClickEvent evt) {
                GWT.log("clicked properties");
                for (ListGridRecord record: records) {
                    openStyleEditor((FacetRecord) record);
                }
            }
        });

        return properties;
    }


    protected MenuItem createActivateItem(final ListGridRecord[] records) {
        MenuItem activate = new MenuItem(MSG.activateTheme());

        activate.addClickHandler(new ClickHandler() {
            public void onClick(MenuItemClickEvent evt) {
                for (ListGridRecord record: records) {
                    FacetRecord facet = (FacetRecord) record;
                    activateTheme(facet.getTheme(), true);
                }

                updateCollection();
            }
        });

        return activate;
    }


    protected MenuItem createDeactivateItem(final ListGridRecord[] records) {
        MenuItem deactivate = new MenuItem(MSG.deactivateTheme());

        deactivate.addClickHandler(new ClickHandler() {
            public void onClick(MenuItemClickEvent evt) {
                for (ListGridRecord record: records) {
                    FacetRecord facet = (FacetRecord) record;
                    activateTheme(facet.getTheme(), false);
                }

                updateCollection();
            }
        });

        return deactivate;
    }


    protected MenuItem createRemoveItem(final ListGridRecord[] records) {
        MenuItem remove = new MenuItem(MSG.removeTheme());

        remove.addClickHandler(new ClickHandler() {
            public void onClick(MenuItemClickEvent evt) {
                SC.warn("Currently not implemented");

                for (ListGridRecord record: records) {
                    FacetRecord facet = (FacetRecord) record;
                }
            }
        });

        return remove;
    }


    /**
     * This method is called after a cell in the theme grid has been modified.
     *
     * @param event The event that stores information about the modified record.
     */
    @Override
    public void onEditComplete(EditCompleteEvent event) {
        GWT.log("Edited record.");

        int         row = event.getRowNum();
        FacetRecord rec = (FacetRecord) list.getRecord(row);

        activateTheme(rec.getTheme(), rec.getActive());

        updateCollection();
    }


    /**
     * This method should be defined in subclasses that wants to listen to this
     * event.
     *
     * @param theme The theme that is moved.
     * @param oldIdx The index of the theme before it was moved.
     * @param newIdx The index of the theme after it was moved.
     */
    protected void fireThemeMoved(Theme theme, int oldIdx, int newIdx) {
        // TODO Implement in subclasses
    }


    @Override
    public void onMove(OnMoveEvent event) {
        int type = event.getType();

        GWT.log("ThemePanel.onMove: " + type);

        ListGridRecord[] records = list.getSelection();

        if (records == null || records.length == 0) {
            GWT.log("ThemePanel.onMove: No records selected.");
            return;
        }

        switch (type) {
            case 0: moveRecordsTop(records); break;
            case 1: moveRecordsUp(records); break;
            case 2: moveRecordsDown(records); break;
            case 3: moveRecordsBottom(records); break;
        }

        updateCollection();
    }


    /**
     * Moves the selected grid records (themes) to the top of the grid.
     *
     * @param records The selected themes in the list. Null not permitted.
     */
    protected void moveRecordsTop(ListGridRecord[] records) {
        ThemeList themeList = getThemeList();

        int idx = 1;

        for (ListGridRecord record: records) {
            Theme theme = ((FacetRecord) record).getTheme();
            fireThemeMoved(theme, theme.getPosition(), idx);
            themeList.setThemePosition(theme, idx++);
        }

        updateGrid();
    }


    /**
     * Moves the selected grid records (themes) one step up.
     *
     * @param records The selected themes in the list. Null not permitted.
     */
    protected void moveRecordsUp(ListGridRecord[] records) {
        ThemeList themeList = getThemeList();

        int[] newPos = new int[records.length];

        for (int i = 0; i < records.length ; i++) {
            Theme theme = ((FacetRecord) records[i]).getTheme();
            newPos[i]   = theme.getPosition() - 1;
        }

        for (int i = 0; i < records.length ; i++) {
            Theme theme = ((FacetRecord) records[i]).getTheme();
            fireThemeMoved(theme, theme.getPosition(), newPos[i]);
            themeList.setThemePosition(theme, newPos[i]);
        }

        updateGrid();
    }


    /**
     * Moves the selected grid records (themes) one step down.
     *
     * @param records The selected themes in the list. Null not permitted.
     */
    protected void moveRecordsDown(ListGridRecord[] records) {
        ThemeList themeList = getThemeList();

        int[] newPos = new int[records.length];

        for (int i = records.length-1; i >= 0; i--) {
            Theme theme = ((FacetRecord) records[i]).getTheme();
            newPos[i] = theme.getPosition()+1;
        }

        for (int i = records.length-1; i >= 0; i--) {
            Theme theme = ((FacetRecord) records[i]).getTheme();
            fireThemeMoved(theme, theme.getPosition(), newPos[i]);
            themeList.setThemePosition(theme, newPos[i]);
        }

        updateGrid();
    }


    /**
     * Moves the selected grid records (themes) to the bottom of the grid.
     *
     * @param records The selected themes in the list. Null not permitted.
     */
    protected void moveRecordsBottom(ListGridRecord[] records) {
        ThemeList themeList = getThemeList();

        int idx = themeList.getThemeCount();

        for (int i = records.length-1; i >= 0; i--) {
            Theme theme = ((FacetRecord) records[i]).getTheme();
            fireThemeMoved(theme, theme.getPosition(), idx);
            themeList.setThemePosition(theme, idx--);
        }

        updateGrid();
    }


    protected void openStyleEditor(final FacetRecord record) {
        Config config = Config.getInstance();
        String url    = config.getServerUrl();
        String locale = config.getLocale();

        String artifact = record.getTheme().getArtifact();

        itemAttributeService.getCollectionItemAttribute(
            this.collection,
            artifact,
            url,
            locale,
            new AsyncCallback<CollectionItemAttribute>() {
                public void onFailure (Throwable caught) {
                    SC.warn(MSG.getString(caught.getMessage()));
                }
                public void onSuccess(CollectionItemAttribute cia) {
                    GWT.log("Successfully loaded collectionitem attributes.");
                    StyleEditorWindow win = new StyleEditorWindow(
                        collection,
                        cia,
                        record);
                    win.setCollectionView(view);
                    win.show();
                }
            });
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org