*/
public Command handleDirties() {
// need to sync to window, since the dispatching must be finished so that the render tree is stable before we collect the dirties.
// more accurately, the synchronized is needed when other classes than window call this method.
synchronized(this) {
Command com = null;
boolean isDebugLog = Tracing.isDebugEnabled(Window.class);
StringBuilder debugMsg = null;
final List<Component> dirties = new ArrayList<Component>();
ComponentVisitor dirtyV = new ComponentVisitor() {
public boolean visit(Component comp, UserRequest ureq) {
boolean visitChildren = false;
if (!comp.isVisible()) {
// a component just made -visible- still needs to be collected (detected by checking dirty flag)
if (comp.isDirty()) {
dirties.add(comp);
comp.setDirty(false); // clear manually here since this component will not be rendered
}
} else if (comp.isDirty()) {
dirties.add(comp);
} else {
// visible and not dirty -> visit children
visitChildren = true;
}
return visitChildren;
}};
ComponentTraverser ct = new ComponentTraverser(dirtyV, getContentPane(), false);
ct.visitAll(null);
int dCnt = dirties.size();
if (dCnt > 0) { // collect the redraw dirties command
try {
JSONObject root = new JSONObject();
root.put("cc", dirties.size());
root.put("wts", timestamp);
JSONArray ja = new JSONArray();
root.put("cps", ja);
GlobalSettings gsettings = wbackofficeImpl.getGlobalSettings();
synchronized(render_mutex) { //o_clusterOK by:fj
// we let all dirty components render themselves.
// not offered (since not usability-useful) is the include of new js-libraries and css-libraries here, since this may invoke a screen reload
// which disturbes the user and lets him/her loose the focus and the cursor.
AsyncMediaResponsible amr = null;
long rstart = 0;
if (isDebugLog) {
rstart = System.currentTimeMillis();
debugMsg = new StringBuilder("update:").append(String.valueOf(dCnt)).append(";");
}
for (int i = 0; i < dCnt; i++) {
Component toRender = dirties.get(i);
boolean wasDomR = toRender.isDomReplaceable();
if (!wasDomR) {
throw new AssertException("cannot replace as dom fragment:"+toRender.getComponentName()+" ("+toRender.getClass().getName()+"),"+toRender.getExtendedDebugInfo());
}
Panel wrapper = new Panel("renderpanel");
wrapper.setDomReplaceable(false); // to omit <div> around the render helper panel
RenderResult renderResult = null;
StringOutput jsol = new StringOutput();
StringOutput hdr = new StringOutput();
String result = null;
try {
toRender.setDomReplaceable(false);
wrapper.setContent(toRender);
String newTimestamp = String.valueOf(timestamp);
URLBuilder ubu = new URLBuilder(uriPrefix,getInstanceId(), newTimestamp,wbackofficeImpl);
renderResult = new RenderResult();
// if we have an around-component-interception
// set the handler for this render cycle
InterceptHandler interceptHandler = wbackofficeImpl.getInterceptHandler();
if (interceptHandler != null) {
InterceptHandlerInstance dhri = interceptHandler.createInterceptHandlerInstance();
renderResult.setInterceptHandlerRenderInstance(dhri);
}
Renderer fr = Renderer.getInstance(wrapper,null, ubu, renderResult, gsettings);
jsol = new StringOutput();
fr.renderBodyOnLoadJSFunctionCall(jsol,toRender);
hdr = new StringOutput();
fr.renderHeaderIncludes(hdr, toRender);
long pstart = 0;
if (isDebugLog) {
pstart = System.currentTimeMillis();
}
result = fr.render(toRender).toString();
if (isDebugLog) {
long pstop = System.currentTimeMillis();
debugMsg.append(toRender.getComponentName()).append(":").append((pstop - pstart));
if (i < dCnt - 1)
debugMsg.append(",");
}
} catch (Exception e) {
throw new OLATRuntimeException(Window.class,renderResult.getLogMsg(), renderResult.getRenderException());
} finally {
toRender.setDomReplaceable(true);
}
if (renderResult.getRenderException() != null) throw new OLATRuntimeException(Window.class, renderResult.getLogMsg(),
renderResult.getRenderException());
AsyncMediaResponsible curAmr = renderResult.getAsyncMediaResponsible();
if (curAmr != null) {
if (amr != null) {
throw new AssertException("can set amr only once in a screen!");
} else {
amr = curAmr;
}
}
JSONObject jo = new JSONObject();
long cid = toRender.getDispatchID();
if (Settings.isDebuging()) {
// for debugging only
jo.put("cname", toRender.getComponentName());
jo.put("clisteners",toRender.getListenerInfo());
jo.put("hfragsize", result.length());
}
jo.put("cid", cid);
jo.put("cidvis", toRender.isVisible());
jo.put("hfrag", result);
jo.put("jsol", jsol);
jo.put("hdr", hdr);
ja.put(jo);
}
//polling case should never set the asyncMediaResp.
//to null otherwise it possible that e.g. pdf served as following click within a CP component
if (amr != null) setAsyncMediaResponsible(amr);
if (isDebugLog) {
long rstop = System.currentTimeMillis();
debugMsg.append(";inl_part_render:").append((rstop-rstart));
Tracing.logDebug(debugMsg.toString(), Window.class);
}
}
com = CommandFactory.createDirtyComponentsCommand();
com.setSubJSON(root);
return com;
} catch (JSONException e) {
throw new AssertException("wrong data put into json object", e);
}