123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986 |
- /*
- @ITMillApache2LicenseForJavaFiles@
- */
-
- package com.itmill.toolkit.terminal.gwt.client;
-
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Vector;
-
- import com.google.gwt.core.client.JavaScriptObject;
- import com.google.gwt.http.client.Request;
- import com.google.gwt.http.client.RequestBuilder;
- import com.google.gwt.http.client.RequestCallback;
- import com.google.gwt.http.client.RequestException;
- import com.google.gwt.http.client.Response;
- import com.google.gwt.json.client.JSONArray;
- import com.google.gwt.json.client.JSONObject;
- import com.google.gwt.json.client.JSONParser;
- import com.google.gwt.json.client.JSONString;
- import com.google.gwt.json.client.JSONValue;
- import com.google.gwt.user.client.Command;
- import com.google.gwt.user.client.DOM;
- import com.google.gwt.user.client.DeferredCommand;
- import com.google.gwt.user.client.Element;
- import com.google.gwt.user.client.Event;
- import com.google.gwt.user.client.Timer;
- import com.google.gwt.user.client.Window;
- import com.google.gwt.user.client.WindowCloseListener;
- import com.google.gwt.user.client.ui.FocusWidget;
- import com.google.gwt.user.client.ui.HasFocus;
- import com.google.gwt.user.client.ui.HasWidgets;
- import com.google.gwt.user.client.ui.Widget;
- import com.itmill.toolkit.terminal.gwt.client.ui.ContextMenu;
- import com.itmill.toolkit.terminal.gwt.client.ui.Field;
- import com.itmill.toolkit.terminal.gwt.client.ui.IView;
- import com.itmill.toolkit.terminal.gwt.client.ui.Notification;
- import com.itmill.toolkit.terminal.gwt.client.ui.Notification.HideEvent;
-
- /**
- * Entry point classes define <code>onModuleLoad()</code>.
- */
- public class ApplicationConnection {
- private static final String MODIFIED_CLASSNAME = "i-modified";
-
- private static final String REQUIRED_CLASSNAME_EXT = "-required";
-
- private static final String ERROR_CLASSNAME_EXT = "-error";
-
- public static final String VAR_RECORD_SEPARATOR = "\u001e";
-
- public static final String VAR_FIELD_SEPARATOR = "\u001f";
-
- private final HashMap resourcesMap = new HashMap();
-
- private static Console console;
-
- private static boolean testingMode;
-
- private final Vector pendingVariables = new Vector();
-
- private final HashMap idToPaintable = new HashMap();
-
- private final HashMap paintableToId = new HashMap();
-
- /** Contains ExtendedTitleInfo by paintable id */
- private final HashMap paintableToTitle = new HashMap();
-
- private final WidgetSet widgetSet;
-
- private ContextMenu contextMenu = null;
-
- private Timer loadTimer;
- private Timer loadTimer2;
- private Timer loadTimer3;
- private Element loadElement;
-
- private final IView view;
-
- private boolean applicationRunning = false;
-
- /**
- * True if each Paintable objects id is injected to DOM. Used for Testing
- * Tools.
- */
- private boolean usePaintableIdsInDOM = false;
-
- /**
- * Contains reference for client wrapper given to Testing Tools.
- *
- * Used in JSNI functions
- *
- * @SuppressWarnings
- */
- private final JavaScriptObject ttClientWrapper = null;
-
- private int activeRequests = 0;
-
- private final ApplicationConfiguration configuration;
-
- private final Vector pendingVariableBursts = new Vector();
-
- public ApplicationConnection(WidgetSet widgetSet,
- ApplicationConfiguration cnf) {
- this.widgetSet = widgetSet;
- configuration = cnf;
-
- if (isDebugMode()) {
- console = new DebugConsole(this, cnf);
- } else {
- console = new NullConsole();
- }
-
- if (checkTestingMode()) {
- usePaintableIdsInDOM = true;
- initializeTestingTools();
- Window.addWindowCloseListener(new WindowCloseListener() {
- public void onWindowClosed() {
- uninitializeTestingTools();
- }
-
- public String onWindowClosing() {
- return null;
- }
- });
- }
-
- initializeClientHooks();
-
- // TODO remove hard coded id name
- view = new IView(cnf.getRootPanelId());
-
- makeUidlRequest("", true);
- applicationRunning = true;
- }
-
- /**
- * Method to check if application is in testing mode. Can be used after
- * application init.
- *
- * @return true if in testing mode
- */
- public static boolean isTestingMode() {
- return testingMode;
- }
-
- /**
- * Check is application is run in testing mode.
- *
- * @return true if in testing mode
- */
- private native static boolean checkTestingMode()
- /*-{
- @com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::testingMode = $wnd.top.itmill && $wnd.top.itmill.registerToTT ? true : false;
- return @com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::testingMode;
- }-*/;
-
- private native void initializeTestingTools()
- /*-{
- var ap = this;
- var client = {};
- client.isActive = function() {
- return ap.@com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::hasActiveRequest()();
- }
- var vi = ap.@com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::getVersionInfo()();
- if (vi) {
- client.getVersionInfo = function() {
- return vi;
- }
- }
- $wnd.top.itmill.registerToTT(client);
- this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::ttClientWrapper = client;
- }-*/;
-
- /**
- * Helper for tt initialization
- */
- private JavaScriptObject getVersionInfo() {
- return configuration.getVersionInfoJSObject();
- }
-
- private native void uninitializeTestingTools()
- /*-{
- $wnd.top.itmill.unregisterFromTT(this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::ttClientWrapper);
- }-*/;
-
- /**
- * Publishes a JavaScript API for mash-up applications.
- * <ul>
- * <li><code>itmill.forceSync()</code> sends pending variable changes, in
- * effect synchronizing the server and client state. This is done for all
- * applications on host page.</li>
- * </ul>
- *
- * TODO make this multi-app aware
- */
- private native void initializeClientHooks()
- /*-{
- var app = this;
- var oldSync;
- if($wnd.itmill.forceSync) {
- oldSync = $wnd.itmill.forceSync;
- }
- $wnd.itmill.forceSync = function() {
- if(oldSync) {
- oldSync();
- }
- app.@com.itmill.toolkit.terminal.gwt.client.ApplicationConnection::sendPendingVariableChanges()();
- }
- }-*/;
-
- public static Console getConsole() {
- return console;
- }
-
- private native static boolean isDebugMode()
- /*-{
- var uri = $wnd.location;
- var re = /debug[^\/]*$/;
- return re.test(uri);
- }-*/;
-
- public String getAppUri() {
- return configuration.getApplicationUri();
- };
-
- public boolean hasActiveRequest() {
- return (activeRequests > 0);
- }
-
- private void makeUidlRequest(String requestData, boolean repaintAll) {
- startRequest();
-
- console.log("Making UIDL Request with params: " + requestData);
- String uri = getAppUri() + "UIDL" + configuration.getPathInfo();
- if (repaintAll) {
- uri += "?repaintAll=1";
- }
- final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri);
- // rb.setHeader("Content-Type",
- // "application/x-www-form-urlencoded; charset=utf-8");
- rb.setHeader("Content-Type", "text/plain;charset=utf-8");
- try {
- rb.sendRequest(requestData, new RequestCallback() {
- public void onError(Request request, Throwable exception) {
- // TODO Better reporting to user
- console.error("Got error");
- endRequest();
- }
-
- public void onResponseReceived(Request request,
- Response response) {
- handleReceivedJSONMessage(response);
- }
-
- });
-
- } catch (final RequestException e) {
- // TODO Better reporting to user
- console.error(e.getMessage());
- endRequest();
- }
- }
-
- private void startRequest() {
- activeRequests++;
- showLoadingIndicator();
- }
-
- private void endRequest() {
-
- checkForPendingVariableBursts();
-
- activeRequests--;
- // deferring to avoid flickering
- DeferredCommand.addCommand(new Command() {
- public void execute() {
- if (activeRequests == 0) {
- hideLoadingIndicator();
- }
- }
- });
- }
-
- /**
- * This method is called after applying uidl change set to application.
- *
- * It will clean current and queued variable change sets. And send next
- * change set if it exists.
- */
- private void checkForPendingVariableBursts() {
- cleanVariableBurst(pendingVariables);
- if (pendingVariableBursts.size() > 0) {
- for (Iterator iterator = pendingVariableBursts.iterator(); iterator
- .hasNext();) {
- cleanVariableBurst((Vector) iterator.next());
- }
- Vector nextBurst = (Vector) pendingVariableBursts.firstElement();
- pendingVariableBursts.remove(0);
- buildAndSendVariableBurst(nextBurst);
- }
- }
-
- /**
- * Cleans given queue of variable changes of such changes that came from
- * components that do not exist anymore.
- *
- * @param variableBurst
- */
- private void cleanVariableBurst(Vector variableBurst) {
- for (int i = 1; i < variableBurst.size(); i += 2) {
- String id = (String) variableBurst.get(i);
- id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR));
- if (!idToPaintable.containsKey(id)) {
- // variable owner does not exist anymore
- variableBurst.remove(i - 1);
- variableBurst.remove(i - 1);
- i -= 2;
- ApplicationConnection.getConsole().log(
- "Removed variable from removed component: " + id);
- }
- }
- }
-
- private void showLoadingIndicator() {
- // show initial throbber
- if (loadTimer == null) {
- loadTimer = new Timer() {
- public void run() {
- // show initial throbber
- if (loadElement == null) {
- loadElement = DOM.createDiv();
- DOM.setStyleAttribute(loadElement, "position",
- "absolute");
- DOM.appendChild(view.getElement(), loadElement);
- ApplicationConnection.getConsole().log(
- "inserting load indicator");
- // Position
- DOM.setStyleAttribute(loadElement, "top", (view
- .getAbsoluteTop() + 6)
- + "px");
- }
- DOM.setElementProperty(loadElement, "className",
- "i-loading-indicator");
- DOM.setStyleAttribute(loadElement, "display", "block");
- final int updatedX = Window.getScrollLeft()
- + view.getAbsoluteLeft()
- + view.getOffsetWidth()
- - DOM.getElementPropertyInt(loadElement,
- "offsetWidth") - 5;
- DOM.setStyleAttribute(loadElement, "left", updatedX + "px");
- final int updatedY = Window.getScrollTop() + 6
- + view.getAbsoluteTop();
- DOM.setStyleAttribute(loadElement, "top", updatedY + "px");
- // Initialize other timers
- loadTimer2 = new Timer() {
- public void run() {
- DOM.setElementProperty(loadElement, "className",
- "i-loading-indicator-delay");
- }
- };
- // Second one kicks in at 1500ms
- loadTimer2.schedule(1200);
-
- loadTimer3 = new Timer() {
- public void run() {
- DOM.setElementProperty(loadElement, "className",
- "i-loading-indicator-wait");
- }
- };
- // Third one kicks in at 5000ms
- loadTimer3.schedule(4700);
- }
- };
- // First one kicks in at 300ms
- loadTimer.schedule(300);
- }
- }
-
- private void hideLoadingIndicator() {
- if (loadTimer != null) {
- loadTimer.cancel();
- if (loadTimer2 != null) {
- loadTimer2.cancel();
- loadTimer3.cancel();
- }
- loadTimer = null;
- }
- if (loadElement != null) {
- DOM.removeChild(view.getElement(), loadElement);
- loadElement = null;
- }
- }
-
- private void handleReceivedJSONMessage(Response response) {
- final Date start = new Date();
- String jsonText = response.getText();
- // for(;;);[realjson]
- jsonText = jsonText.substring(9, jsonText.length() - 1);
- JSONValue json;
- try {
- json = JSONParser.parse(jsonText);
- } catch (final com.google.gwt.json.client.JSONException e) {
- endRequest();
- console.log(e.getMessage() + " - Original JSON-text:");
- console.log(jsonText);
- return;
- }
- // Handle redirect
- final JSONObject redirect = (JSONObject) ((JSONObject) json)
- .get("redirect");
- if (redirect != null) {
- final JSONString url = (JSONString) redirect.get("url");
- if (url != null) {
- console.log("redirecting to " + url.stringValue());
- redirect(url.stringValue());
- return;
- }
- }
-
- // Store resources
- final JSONObject resources = (JSONObject) ((JSONObject) json)
- .get("resources");
- for (final Iterator i = resources.keySet().iterator(); i.hasNext();) {
- final String key = (String) i.next();
- resourcesMap.put(key, ((JSONString) resources.get(key))
- .stringValue());
- }
-
- // Store locale data
- if (((JSONObject) json).containsKey("locales")) {
- final JSONArray l = (JSONArray) ((JSONObject) json).get("locales");
- for (int i = 0; i < l.size(); i++) {
- LocaleService.addLocale((JSONObject) l.get(i));
- }
- }
-
- JSONObject meta = null;
- if (((JSONObject) json).containsKey("meta")) {
- meta = ((JSONObject) json).get("meta").isObject();
- if (meta.containsKey("repaintAll")) {
- view.clear();
- idToPaintable.clear();
- paintableToId.clear();
- }
- }
-
- // Process changes
- final JSONArray changes = (JSONArray) ((JSONObject) json)
- .get("changes");
- for (int i = 0; i < changes.size(); i++) {
- try {
- final UIDL change = new UIDL((JSONArray) changes.get(i));
- try {
- console.dirUIDL(change);
- } catch (final Exception e) {
- console.log(e.getMessage());
- // TODO: dir doesn't work in any browser although it should
- // work (works in hosted mode)
- // it partially did at some part but now broken.
- }
- final UIDL uidl = change.getChildUIDL(0);
- final Paintable paintable = getPaintable(uidl.getId());
- if (paintable != null) {
- paintable.updateFromUIDL(uidl, this);
- } else {
- if (!uidl.getTag().equals("window")) {
- System.out.println("Received update for "
- + uidl.getTag()
- + ", but there is no such paintable ("
- + uidl.getId() + ") rendered.");
- } else {
- view.updateFromUIDL(uidl, this);
- }
- }
- } catch (final Throwable e) {
- e.printStackTrace();
- }
- }
-
- if (meta != null) {
- if (meta.containsKey("focus")) {
- final String focusPid = meta.get("focus").isString()
- .stringValue();
- final Paintable toBeFocused = getPaintable(focusPid);
- if (toBeFocused instanceof HasFocus) {
- final HasFocus toBeFocusedWidget = (HasFocus) toBeFocused;
- toBeFocusedWidget.setFocus(true);
- } else if (toBeFocused instanceof Focusable) {
- ((Focusable) toBeFocused).focus();
- } else {
- getConsole().log("Could not focus component");
- }
-
- }
- if (meta.containsKey("appError")) {
- JSONObject error = meta.get("appError").isObject();
- JSONValue val = error.get("caption");
- String html = "";
- if (val.isString() != null) {
- html += "<h1>" + val.isString().stringValue() + "</h1>";
- }
- val = error.get("message");
- if (val.isString() != null) {
- html += "<p>" + val.isString().stringValue() + "</p>";
- }
- val = error.get("url");
- String url = null;
- if (val.isString() != null) {
- url = val.isString().stringValue();
- }
-
- if (html.length() != 0) {
- Notification n = new Notification(1000 * 60 * 45); // 45min
- n.addEventListener(new NotificationRedirect(url));
- n.show(html, Notification.CENTERED_TOP, "system");
- } else {
- redirect(url);
- }
- applicationRunning = false;
- }
- }
-
- final long prosessingTime = (new Date().getTime()) - start.getTime();
- console.log(" Processing time was " + String.valueOf(prosessingTime)
- + "ms for " + jsonText.length() + " characters of JSON");
- console.log("Referenced paintables: " + idToPaintable.size());
-
- endRequest();
- }
-
- // Redirect browser, null reloads current page
- private static native void redirect(String url)
- /*-{
- if (url) {
- $wnd.location = url;
- } else {
- $wnd.location = $wnd.location;
- }
- }-*/;
-
- public void registerPaintable(String id, Paintable paintable) {
- idToPaintable.put(id, paintable);
- paintableToId.put(paintable, id);
- }
-
- public void unregisterPaintable(Paintable p) {
- Object id = paintableToId.get(p);
- idToPaintable.remove(id);
- paintableToTitle.remove(id);
- paintableToId.remove(p);
-
- if (p instanceof HasWidgets) {
- unregisterChildPaintables((HasWidgets) p);
- }
- }
-
- public void unregisterChildPaintables(HasWidgets container) {
- final Iterator it = container.iterator();
- while (it.hasNext()) {
- final Widget w = (Widget) it.next();
- if (w instanceof Paintable) {
- unregisterPaintable((Paintable) w);
- } else if (w instanceof HasWidgets) {
- unregisterChildPaintables((HasWidgets) w);
- }
- }
- }
-
- /**
- * Returns Paintable element by its id
- *
- * @param id
- * Paintable ID
- */
- public Paintable getPaintable(String id) {
- return (Paintable) idToPaintable.get(id);
- }
-
- private void addVariableToQueue(String paintableId, String variableName,
- String encodedValue, boolean immediate, char type) {
- final String id = paintableId + VAR_FIELD_SEPARATOR + variableName
- + VAR_FIELD_SEPARATOR + type;
- for (int i = 1; i < pendingVariables.size(); i += 2) {
- if ((pendingVariables.get(i)).equals(id)) {
- pendingVariables.remove(i - 1);
- pendingVariables.remove(i - 1);
- break;
- }
- }
- pendingVariables.add(encodedValue);
- pendingVariables.add(id);
- if (immediate) {
- sendPendingVariableChanges();
- }
- }
-
- /**
- * This method sends currently queued variable changes to server. It is
- * called when immediate variable update must happen.
- *
- * To ensure correct order for variable changes (due servers multithreading
- * or network), we always wait for active request to be handler before
- * sending a new one. If there is an active request, we will put varible
- * "burst" to queue that will be purged after current request is handled.
- *
- */
- public void sendPendingVariableChanges() {
- if (applicationRunning) {
- if (hasActiveRequest()) {
- // skip empty queues if there are pending bursts to be sent
- if (pendingVariables.size() > 0
- || pendingVariableBursts.size() == 0) {
- Vector burst = (Vector) pendingVariables.clone();
- pendingVariableBursts.add(burst);
- }
- } else {
- buildAndSendVariableBurst(pendingVariables);
- }
- }
- }
-
- private void buildAndSendVariableBurst(Vector pendingVariables) {
- final StringBuffer req = new StringBuffer();
-
- for (int i = 0; i < pendingVariables.size(); i++) {
- if (i > 0) {
- if (i % 2 == 0) {
- req.append(VAR_RECORD_SEPARATOR);
- } else {
- req.append(VAR_FIELD_SEPARATOR);
- }
- }
- req.append(pendingVariables.get(i));
- }
-
- pendingVariables.clear();
- makeUidlRequest(req.toString(), false);
- }
-
- public void updateVariable(String paintableId, String variableName,
- String newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, newValue, immediate, 's');
- }
-
- public void updateVariable(String paintableId, String variableName,
- int newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, "" + newValue, immediate,
- 'i');
- }
-
- public void updateVariable(String paintableId, String variableName,
- long newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, "" + newValue, immediate,
- 'l');
- }
-
- public void updateVariable(String paintableId, String variableName,
- float newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, "" + newValue, immediate,
- 'f');
- }
-
- public void updateVariable(String paintableId, String variableName,
- double newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, "" + newValue, immediate,
- 'd');
- }
-
- public void updateVariable(String paintableId, String variableName,
- boolean newValue, boolean immediate) {
- addVariableToQueue(paintableId, variableName, newValue ? "true"
- : "false", immediate, 'b');
- }
-
- public void updateVariable(String paintableId, String variableName,
- Object[] values, boolean immediate) {
- final StringBuffer buf = new StringBuffer();
- for (int i = 0; i < values.length; i++) {
- if (i > 0) {
- buf.append(",");
- }
- buf.append(values[i].toString());
- }
- addVariableToQueue(paintableId, variableName, buf.toString(),
- immediate, 'a');
- }
-
- /**
- * Update generic component features.
- *
- * <h2>Selecting correct implementation</h2>
- *
- * <p>
- * The implementation of a component depends on many properties, including
- * styles, component features, etc. Sometimes the user changes those
- * properties after the component has been created. Calling this method in
- * the beginning of your updateFromUIDL -method automatically replaces your
- * component with more appropriate if the requested implementation changes.
- * </p>
- *
- * <h2>Caption, icon, error messages and description</h2>
- *
- * <p>
- * Component can delegate management of caption, icon, error messages and
- * description to parent layout. This is optional an should be decided by
- * component author
- * </p>
- *
- * <h2>Component visibility and disabling</h2>
- *
- * This method will manage component visibility automatically and if
- * component is an instanceof FocusWidget, also handle component disabling
- * when needed.
- *
- * @param component
- * Widget to be updated, expected to implement an instance of
- * Paintable
- * @param uidl
- * UIDL to be painted
- * @param manageCaption
- * True if you want to delegate caption, icon, description
- * and error message management to parent.
- *
- * @return Returns true iff no further painting is needed by caller
- */
- public boolean updateComponent(Widget component, UIDL uidl,
- boolean manageCaption) {
-
- // If the server request that a cached instance should be used, do
- // nothing
- if (uidl.getBooleanAttribute("cached")) {
- return true;
- }
-
- // Visibility
- boolean visible = !uidl.getBooleanAttribute("invisible");
- component.setVisible(visible);
- if (!visible) {
- return true;
- }
-
- // Switch to correct implementation if needed
- if (!widgetSet.isCorrectImplementation(component, uidl)) {
- final Container parent = Util.getParentLayout(component);
- if (parent != null) {
- final Widget w = widgetSet.createWidget(uidl);
- parent.replaceChildComponent(component, w);
- registerPaintable(uidl.getId(), (Paintable) w);
- ((Paintable) w).updateFromUIDL(uidl, this);
- return true;
- }
- }
-
- updateComponentSize(component, uidl);
-
- boolean enabled = !uidl.getBooleanAttribute("disabled");
- if (component instanceof FocusWidget) {
- ((FocusWidget) component).setEnabled(enabled);
- }
-
- StringBuffer styleBuf = new StringBuffer();
- final String primaryName = component.getStylePrimaryName();
- styleBuf.append(primaryName);
-
- // first disabling and read-only status
- if (!enabled) {
- styleBuf.append(" ");
- styleBuf.append("i-disabled");
- }
- if (uidl.getBooleanAttribute("readonly")) {
- styleBuf.append(" ");
- styleBuf.append("i-readonly");
- }
-
- // add additional styles as css classes, prefixed with component default
- // stylename
- if (uidl.hasAttribute("style")) {
- final String[] styles = uidl.getStringAttribute("style").split(" ");
- for (int i = 0; i < styles.length; i++) {
- styleBuf.append(" ");
- styleBuf.append(primaryName);
- styleBuf.append("-");
- styleBuf.append(styles[i]);
- }
- }
-
- // add modified classname to Fields
- if (uidl.hasAttribute("modified") && component instanceof Field) {
- styleBuf.append(" ");
- styleBuf.append(MODIFIED_CLASSNAME);
- }
-
- TooltipInfo tooltipInfo = getTitleInfo((Paintable) component);
- if (uidl.hasAttribute("description")) {
- tooltipInfo.setTitle(uidl.getStringAttribute("description"));
- } else {
- tooltipInfo.setTitle(null);
- }
-
- // add error classname to components w/ error
- if (uidl.hasAttribute("error")) {
- styleBuf.append(" ");
- styleBuf.append(primaryName);
- styleBuf.append(ERROR_CLASSNAME_EXT);
-
- tooltipInfo.setErrorUidl(uidl.getErrors());
- } else {
- tooltipInfo.setErrorUidl(null);
- }
-
- // add required style to required components
- if (uidl.hasAttribute("required")) {
- styleBuf.append(" ");
- styleBuf.append(primaryName);
- styleBuf.append(REQUIRED_CLASSNAME_EXT);
- }
-
- // Styles + disabled & readonly
- component.setStyleName(styleBuf.toString());
-
- // Set captions
- if (manageCaption) {
- final Container parent = Util.getParentLayout(component);
- if (parent != null) {
- parent.updateCaption((Paintable) component, uidl);
- }
- }
-
- if (usePaintableIdsInDOM) {
- DOM.setElementProperty(component.getElement(), "id", uidl.getId());
- }
-
- return false;
- }
-
- private void updateComponentSize(Widget component, UIDL uidl) {
- String w = uidl.hasAttribute("width") ? uidl
- .getStringAttribute("width") : "";
- component.setWidth(w);
- String h = uidl.hasAttribute("height") ? uidl
- .getStringAttribute("height") : "";
- component.setHeight(h);
- }
-
- /**
- * Get either existing or new Paintable for given UIDL.
- *
- * If corresponding Paintable has been previously painted, return it.
- * Otherwise create and register a new Paintable from UIDL. Caller must
- * update the returned Paintable from UIDL after it has been connected to
- * parent.
- *
- * @param uidl
- * UIDL to create Paintable from.
- * @return Either existing or new Paintable corresponding to UIDL.
- */
- public Paintable getPaintable(UIDL uidl) {
- final String id = uidl.getId();
- Paintable w = getPaintable(id);
- if (w != null) {
- return w;
- }
- w = (Paintable) widgetSet.createWidget(uidl);
- registerPaintable(id, w);
- return w;
- }
-
- public String getResource(String name) {
- return (String) resourcesMap.get(name);
- }
-
- /**
- * Singleton method to get instance of app's context menu.
- *
- * @return IContextMenu object
- */
- public ContextMenu getContextMenu() {
- if (contextMenu == null) {
- contextMenu = new ContextMenu();
- if (usePaintableIdsInDOM) {
- DOM.setElementProperty(contextMenu.getElement(), "id",
- "PID_TOOLKIT_CM");
- }
- }
- return contextMenu;
- }
-
- /**
- * Translates custom protocols in UIRL URI's to be recognizable by browser.
- * All uri's from UIDL should be routed via this method before giving them
- * to browser due URI's in UIDL may contain custom protocols like theme://.
- *
- * @param toolkitUri
- * toolkit URI from uidl
- * @return translated URI ready for browser
- */
- public String translateToolkitUri(String toolkitUri) {
- if (toolkitUri == null) {
- return null;
- }
- if (toolkitUri.startsWith("theme://")) {
- final String themeUri = configuration.getThemeUri();
- if (themeUri == null) {
- console
- .error("Theme not set: ThemeResource will not be found. ("
- + toolkitUri + ")");
- }
- toolkitUri = themeUri + toolkitUri.substring(7);
- }
- return toolkitUri;
- }
-
- public String getThemeUri() {
- return configuration.getThemeUri();
- }
-
- /**
- * Listens for Notification hide event, and redirects. Used for system
- * messages, such as session expired.
- *
- */
- private class NotificationRedirect implements Notification.EventListener {
- String url;
-
- NotificationRedirect(String url) {
- this.url = url;
- }
-
- public void notificationHidden(HideEvent event) {
- redirect(url);
- }
-
- }
-
- /* Extended title handling */
-
- /**
- * Data showed in tooltips are stored centrilized as it may be needed in
- * varios place: caption, layouts, and in owner components themselves.
- *
- * Updating TooltipInfo is done in updateComponent method.
- *
- */
- public TooltipInfo getTitleInfo(Paintable titleOwner) {
- TooltipInfo info = (TooltipInfo) paintableToTitle.get(titleOwner);
- if (info == null) {
- info = new TooltipInfo();
- paintableToTitle.put(titleOwner, info);
- }
- return info;
- }
-
- private final Tooltip tooltip = new Tooltip(this);
-
- /**
- * Component may want to delegate Tooltip handling to client. Layouts add
- * Tooltip (description, errors) to caption, but some components may want
- * them to appear one other elements too.
- *
- * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
- * @param event
- * @param owner
- */
- public void handleTooltipEvent(Event event, Paintable owner) {
- tooltip.handleTooltipEvent(event, owner);
-
- }
-
- /**
- * Adds PNG-fix conditionally (only for IE6) to the specified IMG -element.
- *
- * @param el
- * the IMG element to fix
- */
- public void addPngFix(Element el) {
- BrowserInfo b = BrowserInfo.get();
- if (b.isIE6()) {
- Util.addPngFix(el, getThemeUri()
- + "/../default/common/img/blank.gif");
- }
- }
-
- }
|