/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.gwt.wysiwyg.client.plugin.table.ui; import org.xwiki.gwt.user.client.FocusCommand; import org.xwiki.gwt.user.client.StringUtils; import org.xwiki.gwt.user.client.TextBoxNumberFilter; import org.xwiki.gwt.user.client.ui.wizard.AbstractInteractiveWizardStep; import org.xwiki.gwt.user.client.ui.wizard.NavigationListener; import org.xwiki.gwt.user.client.ui.wizard.NavigationListener.NavigationDirection; import org.xwiki.gwt.user.client.ui.wizard.NavigationListenerCollection; import org.xwiki.gwt.user.client.ui.wizard.SourcesNavigationEvents; import org.xwiki.gwt.wysiwyg.client.Strings; import org.xwiki.gwt.wysiwyg.client.plugin.table.TableDescriptor; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.TextBox; /** * Wizard step for configuring a table before inserting it. * * @version $Id: 235d2f60b2242b29df4425c56e60c907a0002e7f $ */ public class TableConfigWizardStep extends AbstractInteractiveWizardStep implements KeyUpHandler, SourcesNavigationEvents { /** * Default panel style. */ private static final String DEFAULT_PANEL_STYLE = "xTablePanel"; /** * Style of the information labels. */ private static final String INFO_LABEL_STYLE = "xInfoLabel"; /** * Style used to signal mandatory elements. */ private static final String MANDATORY_STYLE = "xMandatory"; /** * Style of the information labels. */ private static final String HELP_LABEL_STYLE = "xHelpLabel"; /** * The style applied to the validation messages. */ private static final String ERROR_STYLE = "xErrorMsg"; /** * The style for an field in error. */ private static final String FIELD_ERROR_STYLE = "xErrorField"; /** * Row number text input. */ private TextBox rows; /** * Displays a validation message if the {@link #rows} field has an invalid value. */ private Label rowsValidationMessage; /** * Column number text input. */ private TextBox columns; /** * Displays a validation message if the {@link #columns} field has an invalid value. */ private Label columnsValidationMessage; /** * Border size text input. */ private TextBox border; /** * Table has a heading row. */ private CheckBox header; /** * Describes the table to be inserted. */ private final TableDescriptor descriptor; /** * The list of navigation listeners. This wizard step generates navigation events when the user presses the Enter * key in one of the fields. */ private final NavigationListenerCollection navigationListeners = new NavigationListenerCollection(); /** * Creates a new wizard step for configuring a table before inserting it. */ public TableConfigWizardStep() { setStepTitle(Strings.INSTANCE.tableInsertDialogTitle()); descriptor = new TableDescriptor(); descriptor.setRowCount(2); descriptor.setColumnCount(2); descriptor.setWithHeader(true); display().addStyleName("xTableMainPanel"); display().add(getRowsPanel()); display().add(getColumnsPanel()); // getPanel().add(getBorderPanel()); display().add(getHeaderPanel()); } @Override public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { navigationListeners.fireNavigationEvent(NavigationDirection.NEXT); } } @Override public Object getResult() { return descriptor; } @Override public void init(Object data, AsyncCallback< ? > cb) { cb.onSuccess(null); // Focus the first input field. Scheduler.get().scheduleDeferred(new FocusCommand(rows)); } @Override public void onCancel() { hideValidationMessages(); } @Override public void onSubmit(AsyncCallback<Boolean> async) { if (validate()) { updateTableDescriptor(); async.onSuccess(true); } else { async.onSuccess(false); } } @Override public void addNavigationListener(NavigationListener listener) { navigationListeners.add(listener); } @Override public void removeNavigationListener(NavigationListener listener) { navigationListeners.remove(listener); } /** * @return the panel holding the rows settings for the table */ private Panel getRowsPanel() { FlowPanel panel = new FlowPanel(); panel.addStyleName(DEFAULT_PANEL_STYLE); Panel rowsLabel = new FlowPanel(); rowsLabel.setStyleName(INFO_LABEL_STYLE); rowsLabel.add(new InlineLabel(Strings.INSTANCE.tableRowsLabel())); InlineLabel mandatoryLabel = new InlineLabel(Strings.INSTANCE.mandatory()); mandatoryLabel.addStyleName(MANDATORY_STYLE); rowsLabel.add(mandatoryLabel); panel.add(rowsLabel); Label rowsHelpLabel = new Label(Strings.INSTANCE.tableRowsHelpLabel()); rowsHelpLabel.setStyleName(HELP_LABEL_STYLE); panel.add(rowsHelpLabel); rowsValidationMessage = new Label(Strings.INSTANCE.tableInsertStrictPositiveIntegerRequired()); rowsValidationMessage.setVisible(false); rowsValidationMessage.addStyleName(ERROR_STYLE); panel.add(rowsValidationMessage); rows = new TextBox(); rows.setText(String.valueOf(descriptor.getRowCount())); rows.setTitle(Strings.INSTANCE.tableRowsToolTip()); rows.addKeyPressHandler(new TextBoxNumberFilter()); rows.addKeyUpHandler(this); panel.add(rows); return panel; } /** * @return the panel holding the columns settings for the table */ private Panel getColumnsPanel() { FlowPanel panel = new FlowPanel(); panel.addStyleName(DEFAULT_PANEL_STYLE); Panel colsLabel = new FlowPanel(); colsLabel.setStyleName(INFO_LABEL_STYLE); colsLabel.add(new InlineLabel(Strings.INSTANCE.tableColsLabel())); InlineLabel mandatoryLabel = new InlineLabel(Strings.INSTANCE.mandatory()); mandatoryLabel.addStyleName(MANDATORY_STYLE); colsLabel.add(mandatoryLabel); panel.add(colsLabel); Label colsHelpLabel = new Label(Strings.INSTANCE.tableColsHelpLabel()); colsHelpLabel.setStyleName(HELP_LABEL_STYLE); panel.add(colsHelpLabel); columnsValidationMessage = new Label(Strings.INSTANCE.tableInsertStrictPositiveIntegerRequired()); columnsValidationMessage.setVisible(false); columnsValidationMessage.addStyleName(ERROR_STYLE); panel.add(columnsValidationMessage); columns = new TextBox(); columns.setText(String.valueOf(descriptor.getColumnCount())); columns.setTitle(Strings.INSTANCE.tableColsToolTip()); columns.addKeyPressHandler(new TextBoxNumberFilter()); columns.addKeyUpHandler(this); panel.add(columns); return panel; } /** * @return the panel holding the border settings for the table */ private Panel getBorderPanel() { FlowPanel panel = new FlowPanel(); panel.addStyleName(DEFAULT_PANEL_STYLE); Label borderSizeLabel = new Label(Strings.INSTANCE.tableBorderLabel()); borderSizeLabel.setStyleName(INFO_LABEL_STYLE); panel.add(borderSizeLabel); Label borderSizeHelpLabel = new Label(Strings.INSTANCE.tableBorderHelpLabel()); borderSizeHelpLabel.setStyleName(HELP_LABEL_STYLE); panel.add(borderSizeHelpLabel); border = new TextBox(); border.addStyleName("xBorderInput"); border.addKeyPressHandler(new TextBoxNumberFilter()); border.addKeyUpHandler(this); panel.add(border); Label borderPixelLabel = new Label(Strings.INSTANCE.tablePixel()); borderPixelLabel.setStyleName("xTablePixel"); panel.add(borderPixelLabel); return panel; } /** * @return the panel holding the border settings for the table */ private Panel getHeaderPanel() { FlowPanel panel = new FlowPanel(); panel.addStyleName(DEFAULT_PANEL_STYLE); header = new CheckBox(Strings.INSTANCE.tableHeaderLabel()); header.addStyleName(INFO_LABEL_STYLE); header.addKeyUpHandler(this); header.setValue(descriptor.isWithHeader()); panel.add(header); Label headerHelpLabel = new Label(Strings.INSTANCE.tableHeaderHelpLabel()); headerHelpLabel.setStyleName(HELP_LABEL_STYLE); panel.add(headerHelpLabel); return panel; } /** * @return {@code true} if this dialog can be submitted, {@code false} otherwise */ private boolean validate() { hideValidationMessages(); Focusable failed = null; if (!validateRequiredStrictPositiveIntger(columns.getText())) { columnsValidationMessage.setVisible(true); columns.addStyleName(FIELD_ERROR_STYLE); failed = columns; } if (!validateRequiredStrictPositiveIntger(rows.getText())) { rowsValidationMessage.setVisible(true); rows.addStyleName(FIELD_ERROR_STYLE); failed = rows; } if (failed != null) { Scheduler.get().scheduleDeferred(new FocusCommand(failed)); return false; } return true; } /** * Checks if the given string is a strict positive integer. * * @param str the string to be validated * @return {@code true} if the given string is valid, {@code false} otherwise */ private boolean validateRequiredStrictPositiveIntger(String str) { if (StringUtils.isEmpty(str)) { // Required return false; } else { try { int rowCount = Integer.parseInt(str); if (rowCount <= 0) { // Positive return false; } } catch (NumberFormatException e) { // Number return false; } } return true; } /** * Hides the validation messages generated by the last call to {@link #validate()}. */ private void hideValidationMessages() { rowsValidationMessage.setVisible(false); rows.removeStyleName(FIELD_ERROR_STYLE); columnsValidationMessage.setVisible(false); columns.removeStyleName(FIELD_ERROR_STYLE); } /** * Updates the table descriptor with the values from the input fields. */ private void updateTableDescriptor() { descriptor.setRowCount(Integer.parseInt(rows.getText())); descriptor.setColumnCount(Integer.parseInt(columns.getText())); descriptor.setWithHeader(header.getValue()); } }