Java tutorial
/******************************************************************************* *Copyright (c) 2009 Eucalyptus Systems, Inc. * * This program 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, only version 3 of the License. * * * This file 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 this program. If not, see <http://www.gnu.org/licenses/>. * * Please contact Eucalyptus Systems, Inc., 130 Castilian * Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> * if you need additional information or have any questions. * * This file may incorporate work covered under the following copyright and * permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF * THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE * LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS * SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA * BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN * THE REGENTS DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT * OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR * WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH * ANY SUCH LICENSES OR RIGHTS. *******************************************************************************/ package edu.ucsb.eucalyptus.admin.client; 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.*; import edu.ucsb.eucalyptus.admin.client.ClusterInfoTable.DeleteCallback; import edu.ucsb.eucalyptus.admin.client.SystemConfigTable.ChangeCallback; import edu.ucsb.eucalyptus.admin.client.SystemConfigTable.FocusHandler; import java.util.ArrayList; import java.util.List; // dmitrii TODO: remove commented out lines once the CSS-based design is confirmed public class WalrusInfoTable extends VerticalPanel implements ClickHandler { private static int maxWalruses = 1; // TODO: bump this up once we can do more than 1 private static Label noWalrusesLabel = new Label(); private static Label statusLabel = new Label(); private Grid grid = new Grid(); private EucaButton add_button = new EucaButton("Register Walrus", this); private static HTML hint = new HTML(); private List<WalrusInfoWeb> walrusList = new ArrayList<WalrusInfoWeb>(); private static String sessionId; private static String warningMessage = "Note: registering Walrus requires synchronization of keys among all nodes, which cannot be done through this interface. See documentation for details."; public WalrusInfoTable(String sessionId) { this.sessionId = sessionId; this.setStyleName("euca-config-component"); this.setSpacing(2); this.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); // this.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); Label walrusesHeader = new Label("Walrus Configuration:"); walrusesHeader.setStyleName("euca-section-header"); this.add(walrusesHeader); this.noWalrusesLabel.setText("No Walrus hosts registered"); this.noWalrusesLabel.setStyleName("euca-greeting-disabled"); HorizontalPanel grid_and_hint = new HorizontalPanel(); grid_and_hint.add(this.grid); grid_and_hint.add(this.hint); this.hint.setWidth("100"); this.add(grid_and_hint); HorizontalPanel hpanel = new HorizontalPanel(); hpanel.setSpacing(2); hpanel.add(add_button); hpanel.add(new EucaButton("Save Walrus configuration", new SaveCallback(this))); hpanel.add(this.statusLabel); // this.statusLabel.setWidth ("250"); this.statusLabel.setText(""); this.statusLabel.setStyleName("euca-greeting-pending"); this.add(hpanel); rebuildTable(); EucalyptusWebBackend.App.getInstance().getWalrusList(this.sessionId, new GetWalrusListCallback(this)); } public void onClick(ClickEvent event) // Register walrus button { this.walrusList.add(new WalrusInfoWeb("Walrus", "host", 8773 /** FIXME: DRAMATICALLY: URGENTLY **/ , new ArrayList<String>())); //these values are just defaults this.rebuildTable(); this.statusLabel.setText("Unsaved changes"); this.statusLabel.setStyleName("euca-greeting-warning"); } private void rebuildTable() { if (this.walrusList.isEmpty()) { this.grid.setVisible(false); this.noWalrusesLabel.setVisible(true); this.add_button.setEnabled(true); } else { this.noWalrusesLabel.setVisible(false); this.grid.clear(); this.grid.resize(this.walrusList.size(), 1); this.grid.setVisible(true); this.grid.setStyleName("euca-table"); this.grid.setCellPadding(2); int row = 0; for (WalrusInfoWeb w : this.walrusList) { /*// big yellow block looks kinda weird if ( ( row % 2 ) == 1 ) { this.grid.getRowFormatter().setStyleName( row, "euca-table-even-row" ); } else { this.grid.getRowFormatter().setStyleName( row, "euca-table-odd-row" ); }*/ this.grid.setWidget(row, 0, addWalrusEntry(row++, w)); } if (row >= maxWalruses) { this.add_button.setEnabled(false); } else { this.add_button.setEnabled(true); } } } private Grid addWalrusEntry(int row, WalrusInfoWeb walrusInfo) { final ArrayList<String> properties = walrusInfo.getProperties(); int numProperties = properties.size() / 4; Grid g = new Grid(1 + numProperties, 2); g.setStyleName("euca-table"); g.setCellPadding(4); int i = 0; // row 1 g.setWidget(i, 0, new Label("Walrus host:")); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); HorizontalPanel p = new HorizontalPanel(); p.setSpacing(0); g.setWidget(i, 1, p); final TextBox walrusHost_box = new TextBox(); walrusHost_box.addChangeListener(new ChangeCallback(this, row)); walrusHost_box.setVisibleLength(35); walrusHost_box.setText(walrusInfo.getHost()); p.add(walrusHost_box); p.add(new EucaButton("Deregister", new DeleteCallback(this, row))); for (int propIdx = 0; propIdx < numProperties; ++propIdx) { i++; // next row if ("KEYVALUE".equals(properties.get(4 * propIdx))) { g.setWidget(i, 0, new Label(properties.get(4 * propIdx + 1) + ": ")); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox propTextBox = new TextBox(); propTextBox.addChangeListener(new ChangeCallback(this, row)); propTextBox.setVisibleLength(30); propTextBox.setText(properties.get(4 * propIdx + 2)); propTextBox.addFocusListener(new FocusHandler(this.hint, this.warningMessage)); g.setWidget(i, 1, propTextBox); } else if ("KEYVALUEHIDDEN".equals(properties.get(4 * propIdx))) { g.setWidget(i, 0, new Label(properties.get(4 * propIdx + 1) + ": ")); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox propTextBox = new PasswordTextBox(); propTextBox.addChangeListener(new ChangeCallback(this, row)); propTextBox.setVisibleLength(30); propTextBox.setText(properties.get(4 * propIdx + 2)); propTextBox.addFocusListener(new FocusHandler(this.hint, this.warningMessage)); g.setWidget(i, 1, propTextBox); } else if ("BOOLEAN".equals(properties.get(4 * propIdx))) { final int index = propIdx; final CheckBox propCheckbox = new CheckBox(); g.getCellFormatter().setHorizontalAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT); g.setWidget(i, 0, propCheckbox); if (Boolean.parseBoolean(properties.get(4 * index + 2))) { propCheckbox.setChecked(true); } else { propCheckbox.setChecked(false); } propCheckbox.addClickListener(new ClickListener() { public void onClick(Widget sender) { if (((CheckBox) sender).isChecked()) { properties.set(4 * index + 2, String.valueOf(true)); } else { properties.set(4 * index + 2, String.valueOf(false)); } } }); g.setWidget(i, 1, new Label(properties.get(propIdx * 4 + 1))); } } return g; } public List<WalrusInfoWeb> getWalrusList() { return walrusList; } public void setWalrusList(final List<WalrusInfoWeb> walrusList) { this.walrusList = walrusList; } public void updateRow(int row) { WalrusInfoWeb walrus = this.walrusList.get(row); Grid g = (Grid) this.grid.getWidget(row, 0); HorizontalPanel p = (HorizontalPanel) g.getWidget(0, 1); walrus.setHost(((TextBox) p.getWidget(0)).getText()); int widgetStartIndex = 1; ArrayList<String> properties = walrus.getProperties(); for (int i = 0; i < (properties.size() / 4); ++i) { if (properties.get(4 * i).startsWith("KEYVALUE")) properties.set(4 * i + 2, ((TextBox) g.getWidget(widgetStartIndex + i, 1)).getText()); } } public void MarkCommitted() { for (WalrusInfoWeb walrus : this.walrusList) { walrus.setCommitted(); } } class ChangeCallback implements ChangeListener, ClickListener { private WalrusInfoTable parent; private int row; ChangeCallback(final WalrusInfoTable parent, final int row) { this.parent = parent; this.row = row; } public void onChange(Widget sender) { this.parent.updateRow(this.row); this.parent.statusLabel.setText("Unsaved changes"); this.parent.statusLabel.setStyleName("euca-greeting-warning"); } public void onClick(Widget sender) { this.parent.updateRow(this.row); this.parent.statusLabel.setText("Unsaved changes"); this.parent.statusLabel.setStyleName("euca-greeting-warning"); } } class DeleteCallback implements ClickHandler { private WalrusInfoTable parent; private int row; DeleteCallback(final WalrusInfoTable parent, final int row) { this.parent = parent; this.row = row; } public void onClick(ClickEvent event) { this.parent.walrusList.remove(this.row); this.parent.rebuildTable(); this.parent.statusLabel.setText("Unsaved changes"); this.parent.statusLabel.setStyleName("euca-greeting-warning"); } } class GetWalrusListCallback implements AsyncCallback { private WalrusInfoTable parent; GetWalrusListCallback(final WalrusInfoTable parent) { this.parent = parent; } public void onFailure(final Throwable throwable) { this.parent.statusLabel.setText("Failed to contact server!"); this.parent.statusLabel.setStyleName("euca-greeting-error"); } public void onSuccess(final Object o) { List<WalrusInfoWeb> newWalrusList = (List<WalrusInfoWeb>) o; this.parent.statusLabel.setText("Walrus configuration up to date"); this.parent.statusLabel.setStyleName("euca-greeting-disabled"); this.parent.walrusList = newWalrusList; this.parent.MarkCommitted(); this.parent.rebuildTable(); } } class SaveCallback implements AsyncCallback, ClickHandler { private WalrusInfoTable parent; SaveCallback(final WalrusInfoTable parent) { this.parent = parent; } public void onClick(ClickEvent event) { this.parent.statusLabel.setText("Saving..."); this.parent.statusLabel.setStyleName("euca-greeting-pending"); EucalyptusWebBackend.App.getInstance().setWalrusList(this.parent.sessionId, this.parent.walrusList, this); } public void onFailure(final Throwable throwable) { this.parent.statusLabel.setText("Failed to save! (Check hostname and path.)"); this.parent.statusLabel.setStyleName("euca-greeting-error"); } public void onSuccess(final Object o) { this.parent.statusLabel.setText("Saved Walrus configuration to server"); this.parent.statusLabel.setStyleName("euca-greeting-disabled"); this.parent.MarkCommitted(); this.parent.rebuildTable(); // so the committed ones show up } } class FocusHandler implements FocusListener { private HTML parent; private String message; FocusHandler(final HTML parent, String message) { this.parent = parent; this.message = message; } public void onLostFocus(Widget sender) { this.parent.setHTML(""); this.parent.setStyleName("euca-text"); } public void onFocus(Widget sender) { this.parent.setHTML(message); this.parent.setStyleName("euca-error-hint"); } } }