/** * Abstract base implementation for {@link IWebPage}. * * @author Philip Helger */ public abstract class AbstractWebPage<WPECTYPE extends IWebPageExecutionContext> extends AbstractPage implements IWebPage<WPECTYPE> { /** The CSS class to be applied to the help div */ public static final ICSSClassProvider CSS_PAGE_HELP_ICON = DefaultCSSClassProvider.create("page_help_icon"); private IWebPageIcon m_aIcon; /** * Constructor * * @param sID The unique page ID. May not be <code>null</code>. */ public AbstractWebPage(@Nonnull @Nonempty final String sID) { super(sID); } /** * Constructor * * @param sID The unique page ID. May not be <code>null</code>. * @param sName The constant (non-translatable) name of the page. May not be <code>null</code>. */ public AbstractWebPage(@Nonnull @Nonempty final String sID, @Nonnull final String sName) { super(sID, sName); } /** * Constructor * * @param sID The unique page ID. May not be <code>null</code>. * @param sName The constant (non-translatable) name of the page. May not be <code>null</code>. * @param sDescription The constant (non-translatable) description of the page. May be <code>null * </code>. */ public AbstractWebPage( @Nonnull @Nonempty final String sID, @Nonnull final String sName, @Nullable final String sDescription) { super(sID, sName, sDescription); } /** * Constructor * * @param sID The unique page ID. May not be <code>null</code>. * @param aName The name of the page. May not be <code>null</code>. */ public AbstractWebPage( @Nonnull @Nonempty final String sID, @Nonnull final IReadonlyMultiLingualText aName) { super(sID, aName); } /** * Constructor * * @param sID The unique page ID. May not be <code>null</code>. * @param aName The name of the page. May not be <code>null</code>. * @param aDescription Optional description of the page. May be <code>null</code>. */ public AbstractWebPage( @Nonnull @Nonempty final String sID, @Nonnull final IReadonlyMultiLingualText aName, @Nullable final IReadonlyMultiLingualText aDescription) { super(sID, aName, aDescription); } @Nullable public IWebPageIcon getIcon() { return m_aIcon; } @Nonnull public AbstractWebPage<WPECTYPE> setIcon(@Nullable final IWebPageIcon aIcon) { m_aIcon = aIcon; return this; } @Nullable @OverrideOnDemand public String getHeaderText(@Nonnull final WPECTYPE aWPEC) { return getDisplayText(aWPEC.getDisplayLocale()); } @Nullable @OverrideOnDemand public IHCNode getHeaderNode(@Nonnull final WPECTYPE aWPEC) { final String sText = getHeaderText(aWPEC); if (StringHelper.hasNoText(sText)) return null; return HCH1.create(sText); } @Nonnull public static final IRequestWebScopeWithoutResponse getScope() { return WebScopeManager.getRequestScope(); } /** @return A form that links to the current page. */ @Nonnull @Deprecated public HCForm createFormSelf() { return new HCForm(LinkUtils.getSelfHref()); } /** @return A form that links to the current page. */ @Nonnull public HCForm createFormSelf(@Nonnull final ILayoutExecutionContext aLEC) { return new HCForm(aLEC.getSelfHref()); } /** @return A file upload form that links to the current page. */ @Nonnull @Deprecated public HCForm createFormFileUploadSelf() { final HCForm aForm = createFormSelf(); aForm.setFileUploadEncType(); return aForm; } /** @return A file upload form that links to the current page. */ @Nonnull public HCForm createFormFileUploadSelf(@Nonnull final ILayoutExecutionContext aLEC) { final HCForm aForm = createFormSelf(aLEC); aForm.setFileUploadEncType(); return aForm; } /** * Check some pre-requisites. This is called as the very first action on each page view. * * @param aWPEC The web page execution context * @return Never <code>null</code>. */ @OverrideOnDemand @Nonnull protected EValidity isValidToDisplayPage(@Nonnull final WPECTYPE aWPEC) { return EValidity.VALID; } /** * This method is called before the main {@link #fillContent(IWebPageExecutionContext)} method is * called. */ @OverrideOnDemand protected void beforeFillContent() {} /** * Abstract method to be implemented by subclasses, that creates the main page content, without * the help icon. * * @param aWPEC The web page execution context. Never <code>null</code>. */ protected abstract void fillContent(@Nonnull WPECTYPE aWPEC); /** * This method is called after the main {@link #fillContent(IWebPageExecutionContext)} method is * called. */ @OverrideOnDemand protected void afterFillContent() {} /** * Get the help URL of the current page * * @param aRequestScope The request web scope to be used. Required for cookie-less handling. May * not be <code>null</code>. * @param aDisplayLocale The current display locale. Never <code>null</code>. * @return The help URL for this page. May not be <code>null</code>. */ @Nonnull @OverrideOnDemand protected ISimpleURL getHelpURL( @Nonnull final IRequestWebScopeWithoutResponse aRequestScope, @Nonnull final Locale aDisplayLocale) { return LinkUtils.getURLWithContext( aRequestScope, "help/" + getID(), new SMap().add("locale", aDisplayLocale.toString())); } /** * Create the HC node to represent the help icon. This method is only called, if help is available * for this page. The created code looks like this by default:<br> * <code> * <a href="<i>helpURL</i>" title="Show help for page <i>pageName</i>" target="simplehelpwindow"><br> * <span class="page_help_icon"></span><br> * </a></code> * * @param aWPEC The web page execution context * @return The created help icon node. May be <code>null</code>. */ @Nullable @OverrideOnDemand protected IHCNode getHelpIconNode(@Nonnull final WPECTYPE aWPEC) { final IRequestWebScopeWithoutResponse aRequestScope = aWPEC.getRequestScope(); final Locale aDisplayLocale = aWPEC.getDisplayLocale(); final HCA aHelpNode = new HCA(getHelpURL(aRequestScope, aDisplayLocale)); final String sPageName = getDisplayText(aDisplayLocale); aHelpNode.setTitle( EWebBasicsText.PAGE_HELP_TITLE.getDisplayTextWithArgs(aDisplayLocale, sPageName)); aHelpNode.addChild(new HCSpan().addClass(CSS_PAGE_HELP_ICON)); aHelpNode.setTarget(new HCA_Target(HELP_WINDOW_NAME)); return aHelpNode; } /** * Check if is help is available for the current execution context * * @param aWPEC The web page execution context * @return <code>true</code> if help is available, <code>false</code> if not */ @OverrideOnDemand public boolean isHelpAvailable(@Nonnull final WPECTYPE aWPEC) { return false; } /** * Overridable method to attach the help node to the page. This is called as the last action. * * @param aWPEC The web page execution context. Never <code>null</code>. * @param aHelpNode The help node to be inserted. Never <code>null</code>. */ @OverrideOnDemand protected void insertHelpNode(@Nonnull final WPECTYPE aWPEC, @Nonnull final IHCNode aHelpNode) { // Add the help icon as the first child of the resulting node list aWPEC.getNodeList().addChild(0, aHelpNode); } /** * Default implementation calling the abstract {@link #fillContent(IWebPageExecutionContext)} * method and creating the help node if desired. */ public final void getContent(@Nonnull final WPECTYPE aWPEC) { if (isValidToDisplayPage(aWPEC).isValid()) { // "before"-callback beforeFillContent(); // Create the main page content fillContent(aWPEC); // "after"-callback afterFillContent(); } // Is help available for this page? if (isHelpAvailable(aWPEC)) { final IHCNode aHelpNode = getHelpIconNode(aWPEC); if (aHelpNode != null) insertHelpNode(aWPEC, aHelpNode); } } }
public abstract class AbstractWebPageExt<WPECTYPE extends IWebPageExecutionContext> extends AbstractWebPage<WPECTYPE> { /** The width of a single action column in pixels */ public static final int DEFAULT_ACTION_COL_WIDTH = 20; @Deprecated public static final int ACTION_COL_WIDTH = DEFAULT_ACTION_COL_WIDTH; public static final String ACTION_CANCEL = "cancel"; public static final String ACTION_COLLAPSE = CHCParam.ACTION_COLLAPSE; public static final String ACTION_COPY = "copy"; public static final String ACTION_CREATE = CHCParam.ACTION_CREATE; public static final String ACTION_DELETE = CHCParam.ACTION_DELETE; public static final String ACTION_DELETE_ALL = "delete-all"; public static final String ACTION_EDIT = CHCParam.ACTION_EDIT; public static final String ACTION_EXPAND = CHCParam.ACTION_EXPAND; public static final String ACTION_PERFORM = CHCParam.ACTION_PERFORM; public static final String ACTION_SAVE = CHCParam.ACTION_SAVE; public static final String ACTION_UNDELETE = "undelete"; public static final String ACTION_UNDELETE_ALL = "undelete-all"; public static final String ACTION_VIEW = CHCParam.ACTION_VIEW; protected static final ICSSClassProvider CSS_CLASS_LEFT = WebBasicsCSS.CSS_CLASS_LEFT; protected static final ICSSClassProvider CSS_CLASS_CENTER = WebBasicsCSS.CSS_CLASS_CENTER; protected static final ICSSClassProvider CSS_CLASS_RIGHT = WebBasicsCSS.CSS_CLASS_RIGHT; protected static final ICSSClassProvider CSS_CLASS_ACTION_COL = WebBasicsCSS.CSS_CLASS_ACTION_COL; protected static final ICSSClassProvider CSS_CLASS_EMPTY_ACTION = DefaultCSSClassProvider.create("empty-action"); private static int s_nActionColWidth = DEFAULT_ACTION_COL_WIDTH; public AbstractWebPageExt(@Nonnull @Nonempty final String sID, @Nonnull final String sName) { super(sID, sName); } public AbstractWebPageExt( @Nonnull @Nonempty final String sID, @Nonnull final IReadonlyMultiLingualText aName) { super(sID, aName); } public AbstractWebPageExt( @Nonnull @Nonempty final String sID, @Nonnull final String sName, @Nullable final String sDescription) { super(sID, sName, sDescription); } public AbstractWebPageExt( @Nonnull @Nonempty final String sID, @Nonnull final IReadonlyMultiLingualText aName, @Nullable final IReadonlyMultiLingualText aDescription) { super(sID, aName, aDescription); } @Nonnull public static final IWebPageStyler getStyler() { return WebPageStylerManager.getStyler(); } @Nonnegative public static int getActionColWidth() { return s_nActionColWidth; } public static void setActionColWidth(@Nonnegative final int nActionColWidth) { s_nActionColWidth = nActionColWidth; } /** * Create a HCCol (table column) for the specified number of actions. Each action represents a * width of {@link #getActionColWidth()} pixels. At least the width of 3 actions is displayed, so * that the header text fits :) * * @param nActions Number of actions. Must be ≥ 0. * @return The column with the according column width. */ @Nonnull public static HCCol createActionCol(@Nonnegative final int nActions) { // Assume each action icon is 20 pixels (incl. margin) - at least 3 column // widths are required for the header final int nWidth = getActionColWidth() * Math.max(3, nActions); return new HCCol(nWidth); } @Nonnull public static HCSpan createEmptyAction() { return new HCSpan() .addClass(CSS_CLASS_EMPTY_ACTION) .addStyle(CCSSProperties.DISPLAY_INLINE_BLOCK) .addStyle(CCSSProperties.WIDTH.newValue(ECSSUnit.px(16))); } @Nonnull public static SimpleURL createCreateURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final String sMenuItemID) { return aLEC.getLinkToMenuItem(sMenuItemID).add(CHCParam.PARAM_ACTION, ACTION_CREATE); } @Nonnull public static SimpleURL createCreateURL(@Nonnull final ILayoutExecutionContext aLEC) { return aLEC.getSelfHref().add(CHCParam.PARAM_ACTION, ACTION_CREATE); } @Nonnull public static SimpleURL createViewURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject) { return aLEC.getSelfHref() .add(CHCParam.PARAM_ACTION, ACTION_VIEW) .add(CHCParam.PARAM_OBJECT, aCurObject.getID()); } @Nonnull public static <T extends IHasID<String> & IHasDisplayName> HCA createEditLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final T aCurObject) { return createEditLink(aLEC, aCurObject, (Map<String, String>) null); } @Nonnull public static <T extends IHasID<String> & IHasDisplayName> HCA createEditLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final T aCurObject, @Nullable final Map<String, String> aParams) { return createEditLink( aLEC, aCurObject, EWebPageText.OBJECT_EDIT.getDisplayTextWithArgs( aLEC.getDisplayLocale(), aCurObject.getDisplayName()), aParams); } @Nonnull public static IHCNode getEditImg() { return EDefaultIcon.EDIT.getIcon().getAsNode(); } @Nonnull public static SimpleURL createEditURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject) { return aLEC.getSelfHref() .add(CHCParam.PARAM_ACTION, ACTION_EDIT) .add(CHCParam.PARAM_OBJECT, aCurObject.getID()); } @Nonnull public static HCA createEditLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject, @Nullable final String sTitle) { return createEditLink(aLEC, aCurObject, sTitle, (Map<String, String>) null); } @Nonnull public static HCA createEditLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject, @Nullable final String sTitle, @Nullable final Map<String, String> aParams) { final ISimpleURL aEditURL = createEditURL(aLEC, aCurObject).addAll(aParams); return new HCA(aEditURL).setTitle(sTitle).addChild(getEditImg()); } @Nonnull public static <T extends IHasID<String> & IHasDisplayName> HCA createCopyLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final T aCurObject) { return createCopyLink( aLEC, aCurObject, EWebPageText.OBJECT_COPY.getDisplayTextWithArgs( aLEC.getDisplayLocale(), aCurObject.getDisplayName())); } @Nonnull public static IHCNode getCopyImg() { return EDefaultIcon.COPY.getIcon().getAsNode(); } @Nonnull public static SimpleURL createCopyURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject) { return aLEC.getSelfHref() .add(CHCParam.PARAM_ACTION, ACTION_COPY) .add(CHCParam.PARAM_OBJECT, aCurObject.getID()); } @Nonnull public static HCA createCopyLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject, @Nullable final String sTitle) { final ISimpleURL aCopyURL = createCopyURL(aLEC, aCurObject); return new HCA(aCopyURL).setTitle(sTitle).addChild(getCopyImg()); } @Nonnull public static <T extends IHasID<String> & IHasDisplayName> HCA createDeleteLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final T aCurObject) { return createDeleteLink( aLEC, aCurObject, EWebPageText.OBJECT_DELETE.getDisplayTextWithArgs( aLEC.getDisplayLocale(), aCurObject.getDisplayName())); } @Nonnull public static IHCNode getDeleteImg() { return EDefaultIcon.DELETE.getIcon().getAsNode(); } @Nonnull public static SimpleURL createDeleteURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject) { return aLEC.getSelfHref() .add(CHCParam.PARAM_ACTION, ACTION_DELETE) .add(CHCParam.PARAM_OBJECT, aCurObject.getID()); } @Nonnull public static HCA createDeleteLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject, @Nullable final String sTitle) { final ISimpleURL aURL = createDeleteURL(aLEC, aCurObject); return new HCA(aURL).setTitle(sTitle).addChild(getDeleteImg()); } @Nonnull public static SimpleURL createUndeleteURL( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject) { return aLEC.getSelfHref() .add(CHCParam.PARAM_ACTION, ACTION_UNDELETE) .add(CHCParam.PARAM_OBJECT, aCurObject.getID()); } @Nonnull public static IHCNode getCreateImg() { return EDefaultIcon.NEW.getIcon().getAsNode(); } @Nonnull public static HCA createNestedCreateLink( @Nonnull final ILayoutExecutionContext aLEC, @Nonnull final IHasID<String> aCurObject, @Nullable final String sTitle) { final ISimpleURL aURL = createCreateURL(aLEC).add(CHCParam.PARAM_OBJECT, aCurObject.getID()); return new HCA(aURL).setTitle(sTitle).addChild(getCreateImg()); } }