Java tutorial
/** * 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); } }