/** * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.waveprotocol.wave.client.wavepanel.render; import com.google.gwt.dom.client.Document; import org.waveprotocol.wave.client.common.util.LogicalPanel; import org.waveprotocol.wave.client.common.util.StringSequence; import org.waveprotocol.wave.client.editor.content.Registries; import org.waveprotocol.wave.client.wave.DocumentRegistry; import org.waveprotocol.wave.client.wave.InteractiveDocument; import org.waveprotocol.wave.client.wavepanel.view.AnchorView; import org.waveprotocol.wave.client.wavepanel.view.InlineThreadView; import org.waveprotocol.wave.client.wavepanel.view.ViewIdMapper; import org.waveprotocol.wave.client.wavepanel.view.dom.BlipMetaDomImpl; import org.waveprotocol.wave.client.wavepanel.view.dom.BlipViewDomImpl; import org.waveprotocol.wave.client.wavepanel.view.dom.DomAsViewProvider; import org.waveprotocol.wave.client.wavepanel.view.dom.ModelAsViewProvider; import org.waveprotocol.wave.client.wavepanel.view.dom.full.BlipQueueRenderer.PagingHandler; import org.waveprotocol.wave.client.wavepanel.view.impl.BlipMetaViewImpl; import org.waveprotocol.wave.client.wavepanel.view.impl.BlipViewImpl; import org.waveprotocol.wave.model.conversation.ConversationBlip; /** * Transfers blips between their paged in and paged out states. * */ public final class BlipPager implements PagingHandler { /** Fills in an existing blip view. */ private final ShallowBlipRenderer blipPopulator; /** Provides access to the document implementation of a blip. */ private final DocProvider docProvider; /** Interprets DOM elements as views. */ private final DomAsViewProvider views; /** Get the view for a particular model */ private final ModelAsViewProvider viewProvider; /** Reveals the registries to use to render a document. */ private final DocumentRegistries registries; /** Logical panel for widgets in paged-in blips to attach themselves to */ private final LogicalPanel logicalPanel; /** * Maps models to implementations. */ interface DocProvider { InteractiveDocument docOf(ConversationBlip blip); } private BlipPager(DocumentRegistries registries, ShallowBlipRenderer blipPopulator, DocProvider docProvider, DomAsViewProvider views, ModelAsViewProvider viewProvider, LogicalPanel logicalPanel) { this.registries = registries; this.blipPopulator = blipPopulator; this.docProvider = docProvider; this.views = views; this.viewProvider = viewProvider; this.logicalPanel = logicalPanel; } /** * Creates a pager. */ public static BlipPager create(final DocumentRegistry<? extends InteractiveDocument> docRegistry, DocumentRegistries registries, DomAsViewProvider views, ModelAsViewProvider viewProvider, ShallowBlipRenderer blipPopulator, LogicalPanel logicalPanel) { DocProvider docProvider = new DocProvider() { @Override public InteractiveDocument docOf(ConversationBlip blip) { return docRegistry.get(blip); } }; return new BlipPager(registries, blipPopulator, docProvider, views, viewProvider, logicalPanel); } /** * Moves all the inline replies of a blip to their default-anchor locations. */ private void saveInlineReplies(BlipMetaDomImpl metaDom) { // Iteration is done via ids, in order to identify the thread to get the // inline -> default location mapping. StringSequence inlineLocators = metaDom.getInlineLocators(); String inlineId = inlineLocators.getFirst(); while (inlineId != null) { AnchorView inlineUi = views.asAnchor(Document.get().getElementById(inlineId)); InlineThreadView threadUi = inlineUi.getThread(); if (threadUi != null) { // Move to default location. String defaultId = ViewIdMapper.defaultOfInlineAnchor(inlineId); AnchorView defaultUi = views.asAnchor(Document.get().getElementById(defaultId)); inlineUi.detach(threadUi); defaultUi.attach(threadUi); } inlineId = inlineLocators.getNext(inlineId); } } @SuppressWarnings("unchecked") @Override public void pageIn(ConversationBlip blip) { BlipViewImpl<BlipViewDomImpl> blipUi = (BlipViewImpl<BlipViewDomImpl>) viewProvider.getBlipView(blip); if (blipUi != null) { BlipViewDomImpl blipDom = blipUi.getIntrinsic(); BlipMetaDomImpl metaDom = ((BlipMetaViewImpl<BlipMetaDomImpl>) blipUi.getMeta()).getIntrinsic(); InteractiveDocument doc = docProvider.docOf(blip); Registries r = registries.get(blip); // Very first thing that must be done is to extract and save the DOM of // inline threads, since content-document rendering will blast them away. saveInlineReplies(metaDom); // Clear content before rendering, so that doodad events caused by rendering // apply on a fresh state. metaDom.clearContent(); doc.startRendering(r, logicalPanel); metaDom.setContent( doc.getDocument().getFullContentView().getDocumentElement().getImplNodelet()); blipPopulator.render(blip, metaDom); } } @SuppressWarnings("unchecked") @Override public void pageOut(ConversationBlip blip) { BlipViewImpl<BlipViewDomImpl> blipUi = (BlipViewImpl<BlipViewDomImpl>) viewProvider.getBlipView(blip); if (blipUi != null) { BlipViewDomImpl blipDom = blipUi.getIntrinsic(); BlipMetaDomImpl metaDom = ((BlipMetaViewImpl<BlipMetaDomImpl>) blipUi.getMeta()).getIntrinsic(); InteractiveDocument doc = docProvider.docOf(blip); // TODO: remove meta instead doc.stopRendering(); metaDom.setContent(null); } } }