com.google.livingstories.client.contentmanager.ThemeManager.java Source code

Java tutorial

Introduction

Here is the source code for com.google.livingstories.client.contentmanager.ThemeManager.java

Source

/**
 * Copyright 2010 Google Inc.
 *
 * 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 com.google.livingstories.client.contentmanager;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.livingstories.client.LivingStoryRpcService;
import com.google.livingstories.client.LivingStoryRpcServiceAsync;
import com.google.livingstories.client.Theme;
import com.google.livingstories.client.ui.CoordinatedLivingStorySelector;
import com.google.livingstories.client.ui.ItemList;
import com.google.livingstories.client.ui.RadioGroup;
import com.google.livingstories.client.ui.RadioGroup.Layout;
import com.google.livingstories.client.ui.RadioGroup.RadioClickHandler;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Page to enter themes.
 */
public class ThemeManager extends ManagerPane {
    private static enum EditMode {
        CREATE, EDIT;
    }

    /**
     * Create a remote service proxy to talk to the server-side living story persisting service.
     */
    private final LivingStoryRpcServiceAsync livingStoryService = GWT.create(LivingStoryRpcService.class);

    private RadioGroup<EditMode> modeSelector;
    private TextBox nameBox;
    private CoordinatedLivingStorySelector livingStorySelector;
    private ChangeHandler livingStorySelectionHandler;
    private ItemList<Theme> themeListBox;
    private Button saveButton;
    private Button deleteButton;
    private Label statusLabel;

    private Map<Long, Theme> idToContentMap = new HashMap<Long, Theme>();

    public ThemeManager() {
        final VerticalPanel contentPanel = new VerticalPanel();

        contentPanel.add(createLivingStorySelectorPanel());

        // Add the radio buttons to create or edit themes
        contentPanel.add(createModeSelector());

        // Add the editor and the content listbox in a horizontal panel at the center
        HorizontalPanel horizontalPanel = new HorizontalPanel();
        horizontalPanel.add(createEditorPanel());
        horizontalPanel.add(createThemeListBox());
        contentPanel.add(horizontalPanel);

        // Add buttons to save and delete at the bottom
        contentPanel.add(createSaveDeletePanel());

        // Event handlers
        createLivingStorySelectionHandler();
        createThemeSelectionHandler();
        createSaveButtonHandler();
        createDeleteButtonHandler();

        initWidget(contentPanel);
    }

    private Widget createLivingStorySelectorPanel() {
        livingStorySelector = new CoordinatedLivingStorySelector(livingStoryService);
        return livingStorySelector.makeContainingPanel();
    }

    /**
     * Create radio buttons at the top of the tab to choose between creating a new Theme
     * or editing an existing one.
     */
    private Widget createModeSelector() {
        modeSelector = new RadioGroup<EditMode>("modeSelector", Layout.HORIZONTAL);
        modeSelector.addButton(EditMode.CREATE, "Create a new theme");
        modeSelector.addButton(EditMode.EDIT, "Rename an existing theme");
        modeSelector.setValue(EditMode.CREATE);
        modeSelector.setClickHandler(new RadioClickHandler<EditMode>() {
            @Override
            public void onClick(EditMode mode) {
                clearEditArea();
                if (mode == EditMode.EDIT) {
                    populateThemeList();
                    themeListBox.setVisible(true);
                } else {
                    themeListBox.setVisible(false);
                }
            }
        });
        return modeSelector;
    }

    /**
     * Create a panel for showing the text box to name or rename an theme.
     */
    private Widget createEditorPanel() {
        nameBox = new TextBox();
        HorizontalPanel nameBoxPanel = new HorizontalPanel();
        nameBoxPanel.add(new Label("Enter theme name:"));
        nameBoxPanel.add(nameBox);

        return nameBoxPanel;
    }

    /**
     * Create a list box for displaying all the themes for the selected living story so that the user
     * can select one to edit.
     */
    private Widget createThemeListBox() {
        themeListBox = new ItemList<Theme>() {
            @Override
            public void loadItems() {
                // Don't load the list of themes for a living story by default. They are only
                // loaded when the user selects the 'edit' radio button.
            }
        };
        themeListBox.setVisibleItemCount(15);
        themeListBox.setVisible(false);
        return themeListBox;
    }

    /**
     * Create buttons to save and delete themes. And a label for error messages if the
     * updates don't work.
     */
    private Widget createSaveDeletePanel() {
        saveButton = new Button("Save");
        deleteButton = new Button("Delete");
        deleteButton.setEnabled(false);

        statusLabel = new Label();

        HorizontalPanel buttonPanel = new HorizontalPanel();
        buttonPanel.add(saveButton);
        buttonPanel.add(deleteButton);
        buttonPanel.add(statusLabel);
        return buttonPanel;
    }

    /**
     * Create a handler to handle selection in the living story list box.
     */
    private void createLivingStorySelectionHandler() {
        livingStorySelectionHandler = new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent event) {
                modeSelector.setValue(EditMode.CREATE);
                clearEditArea();
                themeListBox.setVisible(false);
            }
        };
        livingStorySelector.addChangeHandler(livingStorySelectionHandler);
    }

    /**
     * Create a handler to handle selection of a theme from the theme list box.
     */
    private void createThemeSelectionHandler() {
        ChangeHandler themeSelectionHandler = new ChangeHandler() {
            @Override
            public void onChange(ChangeEvent event) {
                clearEditArea();
                Long selectedContentId = Long.valueOf(themeListBox.getSelectedItemValue());
                Theme selectedContent = idToContentMap.get(selectedContentId);
                nameBox.setText(selectedContent.getName());

                deleteButton.setEnabled(true);
            }
        };
        themeListBox.addChangeHandler(themeSelectionHandler);
    }

    /**
     * Create a handler for the 'Save' Button. Saves a new content entity if the 'create' radio button
     * has been selected. Saves changes to an existing content entity if the 'edit' radio button has
     * been selected.
     */
    private void createSaveButtonHandler() {
        ClickHandler saveHandler = new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                boolean createNewContent = (modeSelector.getValue() == EditMode.CREATE);
                Long livingStoryId = Long.valueOf(livingStorySelector.getSelectedItemValue());
                String name = nameBox.getText();

                Long id = null;
                if (!createNewContent) {
                    id = Long.valueOf(themeListBox.getSelectedItemValue());
                }
                createOrChangeTheme(createNewContent, id, name, livingStoryId);
            }
        };
        saveButton.addClickHandler(saveHandler);
    }

    /**
     * Create a handler for the 'Delete' Button.
     */
    private void createDeleteButtonHandler() {
        ClickHandler deleteHandler = new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                deleteContent(Long.valueOf(themeListBox.getSelectedItemValue()));
            }
        };
        deleteButton.addClickHandler(deleteHandler);
    }

    /**
     * Make an RPC call to the server to persist a new theme entity or change an
     * existing theme entity in the datastore.
     */
    private void createOrChangeTheme(final boolean createNewTheme, Long id, String name, Long livingStoryId) {
        AsyncCallback<Theme> callback = new AsyncCallback<Theme>() {
            public void onFailure(Throwable caught) {
                statusLabel.setText("Save not successful. Try again.");
                statusLabel.setStyleName("serverResponseLabelError");
            }

            public void onSuccess(Theme content) {
                statusLabel.setText("Saved!");
                statusLabel.setStyleName("serverResponseLabelSuccess");
                idToContentMap.put(content.getId(), content);
                String idAsString = String.valueOf(content.getId());
                if (createNewTheme) {
                    themeListBox.addItem(content.getName(), idAsString);
                } else {
                    themeListBox.renameItemWithValue(idAsString, content.getName());
                }
            }
        };

        livingStoryService.saveTheme(new Theme(createNewTheme ? null : id, name, livingStoryId), callback);
    }

    /**
     * Make an RPC call to the server to delete an existing theme entity. After it's done, remove
     * it from the theme Listbox and clear the edit area.
     */
    private void deleteContent(final Long contentId) {
        AsyncCallback<Void> callback = new AsyncCallback<Void>() {
            public void onFailure(Throwable caught) {
                statusLabel.setText("Delete not successful. Try again.");
                statusLabel.setStyleName("serverResponseLabelError");
            }

            public void onSuccess(Void result) {
                statusLabel.setText("Saved!");
                statusLabel.setStyleName("serverResponseLabelSuccess");
                clearEditArea();
                themeListBox.removeItemWithValue(String.valueOf(contentId));
                idToContentMap.remove(contentId);
            }
        };

        livingStoryService.deleteTheme(contentId, callback);
    }

    private void clearEditArea() {
        nameBox.setText("");
        statusLabel.setText("");
        deleteButton.setEnabled(false);
    }

    /**
     * Retrieve the list of themes associated with a given living story from the server and populate
     * the given list box with the initial snippet from each of them. 
     */
    private void populateThemeList() {
        AsyncCallback<List<Theme>> callback = new AsyncCallback<List<Theme>>() {
            public void onFailure(Throwable caught) {
                themeListBox.clear();
                themeListBox.addItem("Failed to retrieve data.");
                themeListBox.setEnabled(false);
            }

            public void onSuccess(List<Theme> themes) {
                themeListBox.clear();
                for (Theme theme : themes) {
                    themeListBox.addItem(theme.getName(), String.valueOf(theme.getId()));
                    idToContentMap.put(theme.getId(), theme);
                }
                themeListBox.setEnabled(true);
            }
        };

        livingStoryService.getThemesForLivingStory(Long.valueOf(livingStorySelector.getSelectedItemValue()),
                callback);
    }

    @Override
    public void onLivingStoriesChanged() {
        livingStorySelector.refresh();
    }

    @Override
    public void onShow() {
        livingStorySelector.selectCoordinatedLivingStory();
        livingStorySelectionHandler.onChange(null);
    }
}