/**
* Copyright 2009 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.editor.selection.content;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import org.waveprotocol.wave.client.editor.content.ContentElement;
import org.waveprotocol.wave.client.editor.content.ContentNode;
import org.waveprotocol.wave.client.editor.impl.NodeManager;
import org.waveprotocol.wave.model.document.util.DocHelper;
import org.waveprotocol.wave.model.document.util.FilteredView.Skip;
import org.waveprotocol.wave.model.document.util.FocusedPointRange;
import org.waveprotocol.wave.model.document.util.Point;
/**
* @author danilatos@google.com (Daniel Danilatos)
*/
public final class SelectionUtil {
/**
* Attempt to place the caret before the element, or in as near a valid
* selection location as possible.
*/
// TODO(danilatos): Should it be the selection helper's job to do this
// filtering to ensure a valid selection?
public static void placeCaretBeforeElement(SelectionHelper selection, ContentElement element) {
selection.setCaret(
DocHelper.getFilteredPoint(element.getRenderedContentView(),
Point.<ContentNode>inElement(element.getParentElement(), element)));
}
/**
* Attempt to place the caret after the element, or in as near a valid
* selection location as possible.
*/
// TODO(danilatos): Should it be the selection helper's job to do this
// filtering to ensure a valid selection?
public static void placeCaretAfterElement(SelectionHelper selection, ContentElement element) {
selection.setCaret(
DocHelper.getFilteredPoint(element.getRenderedContentView(),
Point.<ContentNode>inElement(element.getParentElement(), element.getNextSibling())));
}
/**
* Takes an html selection and returns it, or null if it's not related to editor content.
*
* @param htmlSelection Selection range to filter.
* @return htmlSelection or null if there's no related content.
*/
public static FocusedPointRange<Node> filterNonContentSelection(
FocusedPointRange<Node> htmlSelection) {
if (htmlSelection == null) {
return null; // quick exit
}
// get just the focus point, finding the element it is inside.
Point<Node> htmlFocus = htmlSelection.getFocus();
Element el;
if (htmlFocus.isInTextNode()) {
el = htmlFocus.getContainer().getParentElement();
} else {
el = htmlFocus.getContainer().cast();
}
// Assume given range is always in the editor, the htmlHelper should guarantee that.
while (!NodeManager.hasBackReference(el)) {
if (NodeManager.getTransparency(el) == Skip.DEEP
|| el.getPropertyBoolean(ContentElement.COMPLEX_IMPLEMENTATION_MARKER)) {
// Exception: when we explicitly want the selection still to be reported
if (!NodeManager.mayContainSelectionEvenWhenDeep(el)) {
htmlSelection = null;
break;
}
}
el = el.getParentElement();
}
return htmlSelection;
}
private SelectionUtil() {}
}