at.spardat.xma.page.WizardPageClient Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2003, 2009 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
package at.spardat.xma.page;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import at.spardat.xma.boot.component.IXMAControl;
import at.spardat.xma.component.ComponentClient;
/**
* Client half base class for the wizard frame.
* To use this class/functionality create a new WizardPage with the XMA GUI designer,
* create the subpages you need as embedded pages and either call setPageInfos() or
* override getNextPageInfo().
* @author laslovd
* @since 2.1.0
*/
public abstract class WizardPageClient extends DialogPage {
private static final Color COLOR_WHITE = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
protected Composite compositeExplanationW;
protected Label labelExplanationTitle;
protected Label labelExplanationText;
protected Label labelExplanationImage;
protected Label sep1W;
protected Composite compositeButtonsW;
protected Button buttonBackW;
protected Button buttonNextW;
protected Button buttonFinishW;
protected Button buttonCancelW;
protected Label sep2W;
protected Composite compositeContentW;
private WizardSubPageInfo actPageInfo = null;
private String stepOfText;
private ResourceBundle messages;
private List pageInfoList = null;
/**
* Initializes a WizardPageClient inside the same Component as the parent PageClient.
*
* @param parent the PageClient calling this DialogPage.
* @param stateless indicating if this page is stateless on the server.
* @param style The SWT-Style for the Shell of the DialogPage.
*/
public WizardPageClient(PageClient parent, boolean stateless, int style) {
super(parent,stateless,style);
}
/**
* Initializes a WizardPageClient inside inside a given Component.
*
* @param component the Component containing the DialogPage.
* @param style The SWT-Style for the Shell of the DialogPage.
* @param stateless indicating if this page is stateless on the server.
* @throws IllegalArgumentException if component is null.
*/
public WizardPageClient(ComponentClient component, boolean stateless, int style) {
super(component,stateless,style);
}
/**
* Initializes a WizardPageClient inside the same Component as the parent PageClient.
*
* @param parent the PageClient calling this DialogPage.
* @param stateless indicating if this page is stateless on the server.
* @param style The SWT-Style for the Shell of the DialogPage.
*/
public WizardPageClient(ComponentClient component, Shell parentShell, boolean stateless, int style) {
super(component,parentShell,stateless,style);
}
/**
* Creates Widgets and layout
* @see at.spardat.xma.page.DialogPage#initGUI()
*/
public void initGUI() {
super.initGUI();
FormData data;
Control[] tabOrder;
EventAdapter adapter = new EventAdapter(this);
Locale locale = getComponent().getContext().getLocale();
messages = ResourceBundle.getBundle("at.spardat.xma.page.PageTexts",locale);
stepOfText = messages.getString("WizardPage.stepOf");
final Scaler scaler = Scaler.getInstance(getComposite());
Composite wizardPageCompW = getComposite();
compositeExplanationW = new Composite(wizardPageCompW,SWT.NONE);
FormLayout layout = new FormLayout();
layout.marginHeight = scaler.convertYToCurrent(0);
layout.marginWidth = scaler.convertXToCurrent(0);
compositeExplanationW.setLayout(layout);
compositeExplanationW.setBackground(COLOR_WHITE);
labelExplanationTitle = new Label(compositeExplanationW,SWT.LEFT);
labelExplanationTitle.setText("");
labelExplanationTitle.setBackground(COLOR_WHITE);
labelExplanationTitle.setFont(getComponent().getFontByStyle(labelExplanationTitle.getFont(),SWT.BOLD));
labelExplanationText = new Label(compositeExplanationW,SWT.LEFT);
labelExplanationText.setText("");
labelExplanationText.setBackground(COLOR_WHITE);
labelExplanationImage = new Label(compositeExplanationW,SWT.LEFT);
labelExplanationImage.setBackground(COLOR_WHITE);
sep1W = new Label (compositeExplanationW,SWT.SEPARATOR|SWT.HORIZONTAL);
compositeButtonsW = new Composite(wizardPageCompW,SWT.NONE);
layout = new FormLayout();
layout.marginHeight = scaler.convertYToCurrent(0);
layout.marginWidth = scaler.convertXToCurrent(0);
compositeButtonsW.setLayout(layout);
buttonBackW = new Button (compositeButtonsW, SWT.PUSH|SWT.CENTER);
buttonBackW.setText(messages.getString("WizardPage.buttonBackW"));
buttonBackW.setEnabled(false);
buttonBackW.addSelectionListener(adapter);
buttonNextW = new Button (compositeButtonsW, SWT.PUSH|SWT.CENTER);
buttonNextW.setText(messages.getString("WizardPage.buttonNextW"));
buttonNextW.addSelectionListener(adapter);
buttonFinishW = new Button (compositeButtonsW, SWT.PUSH|SWT.CENTER);
buttonFinishW.setText(messages.getString("WizardPage.buttonFinishW"));
buttonFinishW.setEnabled(false);
buttonFinishW.addSelectionListener(adapter);
buttonCancelW = new Button (compositeButtonsW, SWT.PUSH|SWT.CENTER);
buttonCancelW.setText(messages.getString("WizardPage.buttonCancelW"));
buttonCancelW.addSelectionListener(adapter);
sep2W = new Label (compositeButtonsW,SWT.SEPARATOR|SWT.HORIZONTAL);
compositeContentW = new Composite(wizardPageCompW,SWT.NONE);
layout = new FormLayout();
layout.marginHeight = scaler.convertYToCurrent(0);
layout.marginWidth = scaler.convertXToCurrent(0);
compositeContentW.setLayout(layout);
mkLayout4ExplanationAndContentComposite(true);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(10));
data.top = new FormAttachment(0,100,scaler.convertYToCurrent(10));
labelExplanationTitle.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(20));
data.right = new FormAttachment(labelExplanationImage,scaler.convertXToCurrent(-3),SWT.LEFT);
data.top = new FormAttachment(labelExplanationTitle,scaler.convertYToCurrent(3),SWT.BOTTOM);
data.bottom = new FormAttachment(sep1W,scaler.convertYToCurrent(-3),SWT.TOP);
labelExplanationText.setLayoutData(data);
data = new FormData();
data.width = scaler.convertXToCurrent(60);
data.height = scaler.convertYToCurrent(60);
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(-6));
data.top = new FormAttachment(0,100,scaler.convertYToCurrent(3));
labelExplanationImage.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(0));
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(0));
data.top = new FormAttachment(labelExplanationImage,scaler.convertYToCurrent(6),SWT.BOTTOM);
sep1W.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(0));
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(0));
data.bottom = new FormAttachment(100,100,scaler.convertYToCurrent(0));
compositeButtonsW.setLayoutData(data);
data = new FormData();
data.width = scaler.convertXToCurrent(100);
data.right = new FormAttachment(buttonNextW,scaler.convertXToCurrent(-6),SWT.LEFT);
data.bottom = new FormAttachment(buttonCancelW,scaler.convertYToCurrent(0),SWT.BOTTOM);
buttonBackW.setLayoutData(data);
data = new FormData();
data.width = scaler.convertXToCurrent(100);
data.right = new FormAttachment(buttonFinishW,scaler.convertXToCurrent(-6),SWT.LEFT);
data.bottom = new FormAttachment(buttonCancelW,scaler.convertYToCurrent(0),SWT.BOTTOM);
buttonNextW.setLayoutData(data);
data = new FormData();
data.width = scaler.convertXToCurrent(100);
data.right = new FormAttachment(buttonCancelW,scaler.convertXToCurrent(-6),SWT.LEFT);
data.bottom = new FormAttachment(buttonCancelW,scaler.convertYToCurrent(0),SWT.BOTTOM);
buttonFinishW.setLayoutData(data);
data = new FormData();
data.width = scaler.convertXToCurrent(100);
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(-3));
data.bottom = new FormAttachment(100,100,scaler.convertYToCurrent(-3));
buttonCancelW.setLayoutData(data);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(0));
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(0));
data.bottom = new FormAttachment(buttonBackW,scaler.convertYToCurrent(-6),SWT.TOP);
sep2W.setLayoutData(data);
tabOrder = new Control[3];
tabOrder[0] = compositeExplanationW;
tabOrder[1] = compositeButtonsW;
tabOrder[2] = compositeContentW;
wizardPageCompW.setTabList(tabOrder);
tabOrder = new Control[0];
compositeExplanationW.setTabList(tabOrder);
tabOrder = new Control[4];
tabOrder[0] = buttonBackW;
tabOrder[1] = buttonNextW;
tabOrder[2] = buttonFinishW;
tabOrder[3] = buttonCancelW;
compositeButtonsW.setTabList(tabOrder);
tabOrder = new Control[0];
compositeContentW.setTabList(tabOrder);
wizardPageCompW.layout();
}
/**
* Remove all Widgets of the page after they have been disposed.
*/
public void removeWidgets() {
super.removeWidgetsBase();
compositeExplanationW = null;
labelExplanationTitle = null;
labelExplanationText = null;
labelExplanationImage = null;
sep1W = null;
compositeButtonsW = null;
buttonBackW = null;
buttonNextW = null;
buttonFinishW = null;
buttonCancelW = null;
sep2W = null;
compositeContentW = null;
}
/**
* Calls the client event configured for the widget of the event.
*
* @param event the SWT-Event that happened.
* @param type the type of the Event, as defined by the event type constants in class SWT.
*/
protected void clientEventBase(SelectionEvent event,int type) {
if (event.widget == buttonBackW) {
buttonBackWEvent();
} else if (event.widget == buttonNextW) {
buttonNextWEvent();
} else if (event.widget == buttonFinishW) {
buttonFinishWEvent();
} else if (event.widget == buttonCancelW) {
buttonCancelWEvent();
} else {
super.clientEventBase(event,type);
}
}
/**
* Startup action. In this case especially changePage()
* (and implicitly getNextPageInfo()) will be called the first time.
* @see at.spardat.xma.page.PageClient#enterBase()
*/
public void enterBase () {
buttonFinishW.setEnabled(false);
changePage(true);
super.enterBase();
}
/**
* Enables or disables Widgets according to the current state of the page.
* This method is called every time the content of any WizardModel of the
* Page may have been changed.
* This method is called immediately after {@link #determineState()}.
*/
final public void stateChangedBaseImpl() {
// if we have errors, the [next] button has to be disabled
buttonNextW.setEnabled ( getDialog().getErrorCount() < 1
&& actPageInfo != null
&& ! actPageInfo.isLastPage );
buttonFinishW.setEnabled( getDialog().getErrorCount() < 1
&& actPageInfo != null
&& (actPageInfo.isLastPage || actPageInfo.mayCompletePremature));
buttonBackW.setEnabled (actPageInfo != null && ! actPageInfo.isFirstPage);
if ( actPageInfo.isLastPage )
getShell().setDefaultButton(buttonFinishW);
else
getShell().setDefaultButton(buttonNextW);
super.stateChangedBaseImpl();
}
/**
* This method will be called every time the user clicks on buttonBackW.
*/
protected void buttonBackWEvent() {
changePage(false);
}
/**
* This method will be called every time the user clicks on buttonNextW.
*/
protected void buttonNextWEvent() {
changePage(true);
}
/**
* This method will be called every time the user clicks on buttonFinishW.
*/
protected void buttonFinishWEvent() {
newRemoteCall("finish").execute();
closeOK();
}
/**
* This method will be called every time the user clicks on buttonCancelW.
*/
protected void buttonCancelWEvent() {
closeCancel();
}
/**
* Does all what is necessary to move to the next or previous page
* (or the first one on startup).
* @param nextPressed direction in the wizard flow
*/
private void changePage ( boolean nextPressed ) {
WizardSubPageInfo newPageInfo;
try {
newPageInfo = getNextPageInfo(actPageInfo,nextPressed);
if ( newPageInfo == null )
return;
}
catch ( Exception ex ) {
showException(ex);
return;
}
if ( actPageInfo != null )
removeChild(actPageInfo.page);
actPageInfo = newPageInfo;
Composite compW = ((IXMAControl) actPageInfo.page).createComposite(compositeContentW);
FormData data = new FormData();
data.left = new FormAttachment(0,0);
data.right = new FormAttachment(100,0);
data.top = new FormAttachment(0,0);
data.bottom = new FormAttachment(100,0);
compW.setLayoutData(data);
// adjust the tab order
compositeContentW.setTabList(new Control[]{compW});
// attach the embedded component as subpage
addChild((IXMAControl) actPageInfo.page);
setFocusToFirstControl(actPageInfo.page.getComposite().getTabList());
if ( actPageInfo.explanationText == null ) {
showOrHideExplanationComposite(false);
}
else {
showOrHideExplanationComposite(true);
if ( actPageInfo.explanationTitle == null )
labelExplanationTitle.setText("");
else
labelExplanationTitle.setText(actPageInfo.explanationTitle);
labelExplanationText.setText(actPageInfo.explanationText);
if ( actPageInfo.explanationImageUri != null )
labelExplanationImage.setImage(getComponent().getImage(actPageInfo.explanationImageUri));
else
labelExplanationImage.setImage(null);
compositeExplanationW.layout();
}
}
/**
* Toggle function to show or hide the explanation composite
* @param showIt yes or no?
*/
private void showOrHideExplanationComposite ( boolean showIt ) {
if ( showIt == (compositeExplanationW.getSize().y > 0) )
return;
mkLayout4ExplanationAndContentComposite(showIt);
getComposite().layout();
}
/**
* Creates the layout for the explanation and the main composite according
* to the given parameter
* @param showExplanation should the explanation composite be visible?
*/
private void mkLayout4ExplanationAndContentComposite ( boolean showExplanation ) {
final Scaler scaler = Scaler.getInstance(getComposite());
FormData data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(0));
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(0));
data.top = new FormAttachment(0,100,scaler.convertYToCurrent(0));
data.bottom = new FormAttachment(0,100,scaler.convertYToCurrent(showExplanation ? 71 : 0));
compositeExplanationW.setLayoutData(data);
compositeExplanationW.setVisible(showExplanation);
data = new FormData();
data.left = new FormAttachment(0,100,scaler.convertXToCurrent(0));
data.right = new FormAttachment(100,100,scaler.convertXToCurrent(0));
data.top = new FormAttachment(compositeExplanationW,scaler.convertYToCurrent(3),SWT.BOTTOM);
data.bottom = new FormAttachment(compositeButtonsW,scaler.convertYToCurrent(-3),SWT.TOP);
compositeContentW.setLayoutData(data);
}
/**
* Searches (recursively) for the first control in the given array
* @param ctrls control array
* @return true if focus was set by this method call (directly or indirectly)
*/
private boolean setFocusToFirstControl ( Control[] ctrls ) {
if ( ctrls == null || ctrls.length < 1 )
return false;
Control ctrl = ctrls[0];
if ( ctrl instanceof Composite && ! (ctrl instanceof Group) ) {
if ( setFocusToFirstControl(((Composite) ctrl).getChildren()) )
return true;
}
return ctrl.setFocus();
}
/**
* Call this method to define a linear wizard flow (index 0 = first step, 1 = 2nd step...)
* Each WizardSubPageInfo can be different not only in obvious thins (page to embed,
* first-/last page flag...) also in layout.
* @param pageInfos Array with information for every wizard step. May not be null.
* @throws IllegalArgumentException parameter was null or length == 0
* @throws IllegalStateException method was called second time
* @see WizardSubPageInfo
*/
public void setPageInfos ( WizardSubPageInfo[] pageInfos ) {
if ( pageInfos == null )
throw new IllegalArgumentException("pageInfos may not be null!");
if ( pageInfos.length < 1 )
throw new IllegalArgumentException("pageInfos must contain at least one page!");
if ( pageInfoList != null )
throw new IllegalStateException("Cannot initialize wizard twice!");
pageInfos[0].isFirstPage = true;
pageInfos[pageInfos.length - 1].isLastPage = true;
pageInfoList = Arrays.asList(pageInfos);
}
/**
* Retrieve the next page info according to the direction.
* @param actPageInfo info to the current page, on which the next or
* prev button was pressed or null on wizard startup
* @param nextPressed true, if [next] was pressed (or first time initialization), false on [prev]
* @return info of next page to display
* @see WizardSubPageInfo
*/
protected WizardSubPageInfo getNextPageInfo ( WizardSubPageInfo actPageInfo, boolean nextPressed ) {
if ( pageInfoList == null )
throw new IllegalStateException("Initialize with setPageInfos() or override getNextPageInfo()!");
WizardSubPageInfo nextInfo;
int ndx;
if ( actPageInfo == null ) {
ndx = 0;
}
else {
ndx = pageInfoList.indexOf(actPageInfo);
if ( nextPressed ) {
ndx++;
}
else {
ndx--;
}
}
nextInfo = (WizardSubPageInfo) pageInfoList.get(ndx);
setStepOf(++ndx,pageInfoList.size());
return nextInfo;
}
/**
* Enriches the window title with a "Step x of y" information
* @param step current step (1-based!)
* @param of count of all step
*/
protected void setStepOf ( int step, int of ) {
MessageFormat mf = new MessageFormat(stepOfText,getComponent().getContext().getLocale());
String s = getDialogTitle() + " " + mf.format(new Object[] { new Integer(step), new Integer(of) });
getShell().setText(s);
}
}