001 package org.hackystat.projectbrowser.page.loadingprocesspanel; 002 003 import org.apache.wicket.ResourceReference; 004 import org.apache.wicket.ajax.AjaxRequestTarget; 005 import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior; 006 import org.apache.wicket.markup.html.basic.MultiLineLabel; 007 import org.apache.wicket.markup.html.image.Image; 008 import org.apache.wicket.markup.html.panel.Panel; 009 import org.apache.wicket.model.PropertyModel; 010 import org.apache.wicket.util.time.Duration; 011 012 /** 013 * Panel to show progress of a lengthy operation. 014 * This panel will show when process is in progress or process end not successfully. 015 * This panel will display the processingMessage. 016 * This panel will update every second via Ajax when process is in progress. 017 * For more detail, please see Processable interface. 018 * 019 * @author Shaoxuan Zhang 020 */ 021 public class LoadingProcessPanel extends Panel { 022 /** Support serialization. */ 023 private static final long serialVersionUID = 1L; 024 /** the data model. */ 025 private Processable dataModel; 026 027 /** 028 * @param id the wicket component id. 029 * @param model the data model associating with this panel. 030 */ 031 // Has to suppress this warning because this constructor calls start() which calls onFinish which 032 // is an overridable method. Calling start() is necessary to start the Ajax auto update function 033 // if process is undergoing when every time this panel is created. The onFinish() method is not 034 // actually called when constructing. It is called within the timers interface method and will be 035 // called later. 036 @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") 037 public LoadingProcessPanel(String id, Processable model) { 038 super(id); 039 this.dataModel = model; 040 MultiLineLabel label = 041 new MultiLineLabel("processingMessage", new PropertyModel(dataModel, "processingMessage")); 042 label.setOutputMarkupId(true); 043 add(label); 044 045 //add loading image 046 Image loadingImage = new Image("loadingImage", 047 new ResourceReference(LoadingProcessPanel.class, "loading21-1.gif")) { 048 /** Support serialization. */ 049 private static final long serialVersionUID = 1L; 050 @Override 051 public boolean isVisible() { 052 return dataModel.isInProcess(); 053 } 054 }; 055 add(loadingImage); 056 057 if (dataModel.isInProcess()) { 058 start(); 059 } 060 } 061 062 /** 063 * start panel self update. 064 */ 065 public final void start() { 066 final AjaxSelfUpdatingTimerBehavior selfUpdate = 067 new AjaxSelfUpdatingTimerBehavior(Duration.milliseconds(500)) { 068 /** Support serialization. */ 069 private static final long serialVersionUID = 1L; 070 @Override 071 protected void onPostProcessTarget(AjaxRequestTarget target) { 072 if (!dataModel.isInProcess()) { 073 // do custom action 074 onFinished(target); 075 // stop the self update 076 stop(); 077 } 078 } 079 }; 080 add(selfUpdate); 081 } 082 /** 083 * visible when data loading is in process or data loading end with error. 084 * @return true if this panel is visible. 085 */ 086 @Override 087 public boolean isVisible() { 088 return dataModel.isInProcess() || !dataModel.isComplete(); 089 } 090 091 /** 092 * The method called when loading process is completed. 093 * @param target an AjaxRequestTarget. 094 */ 095 protected void onFinished(AjaxRequestTarget target) { 096 //do nothing here. add implementation in subclasses. 097 } 098 }