/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.block;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import org.waveprotocol.wave.client.common.util.MeasurerInstance;
import org.waveprotocol.wave.client.paging.Block;
import org.waveprotocol.wave.client.wavepanel.block.BlockStructure.Node;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.util.StringMap;
/**
* Exposes a view structure as pageable blocks.
*
*/
public final class PageableBlockStructure {
/**
* Wraps a structural node in order to provide behaviour.
* This is temporary until the pager is flyweighted.
*/
private class NodeImpl implements Block {
private final Node source;
private Element dom;
public NodeImpl(Node source) {
this.source = source;
}
@Override
public NodeImpl getParent() {
return adapt(source.getParent());
}
@Override
public NodeImpl getFirstChild() {
return adapt(source.getFirstChild());
}
@Override
public NodeImpl getLastChild() {
return adapt(source.getLastChild());
}
@Override
public NodeImpl getNextSibling() {
return adapt(source.getNextSibling());
}
@Override
public NodeImpl getPreviousSibling() {
return adapt(source.getPreviousSibling());
}
//
// Paging nature.
//
private Element getElement() {
if (dom == null) {
String domId = source.getId();
dom = Document.get().getElementById(domId);
if (dom == null) {
throw new RuntimeException("Block is missing: " + domId);
}
}
return dom;
}
@Override
public double getStart() {
return MeasurerInstance.get().top(getRoot().getElement(), getElement());
}
@Override
public double getEnd() {
return MeasurerInstance.get().bottom(getRoot().getElement(), getElement());
}
@Override
public void pageIn() {
handler.pageIn(source);
}
@Override
public void pageOut() {
handler.pageOut(source);
}
@Override
public double getChildrenOrigin() {
return 0;
}
}
public interface PageHandler {
void pageIn(Node block);
void pageOut(Node block);
}
private final StringMap<NodeImpl> nodes = CollectionUtils.createStringMap();
private final BlockStructure view;
private final PageHandler handler;
private PageableBlockStructure(PageHandler handler, BlockStructure view) {
this.handler = handler;
this.view = view;
}
public static PageableBlockStructure create(PageHandler handler, BlockStructure view) {
return new PageableBlockStructure(handler, view);
}
private NodeImpl adapt(Node source) {
if (source == null) {
return null;
}
String id = source.getId();
NodeImpl block = nodes.get(id);
if (block == null) {
block = new NodeImpl(source);
nodes.put(id, block);
}
return block;
}
public NodeImpl getRoot() {
return adapt(view.getRoot());
}
public NodeImpl getNode(String id) {
return adapt(view.getNode(id));
}
}