blob: 3fca1b1befdb7c4baae3638ed93d41863ee1c802 [file] [log] [blame]
// Copyright (C) 2008 The Android Open Source Project
//
// 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 com.google.gerrit.client.ui;
import com.google.gerrit.client.Gerrit;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import java.util.Iterator;
public abstract class FancyFlexTable<RowItem> extends Composite {
private static final FancyFlexTableImpl impl =
GWT.create(FancyFlexTableImpl.class);
protected static final int C_ARROW = 0;
protected final MyFlexTable table;
protected FancyFlexTable() {
table = createFlexTable();
table.addStyleName(Gerrit.RESOURCES.css().changeTable());
table.setWidth("100%");
initWidget(table);
table.setText(0, C_ARROW, "");
table.getCellFormatter().addStyleName(0, C_ARROW, Gerrit.RESOURCES.css().iconHeader());
}
protected MyFlexTable createFlexTable() {
return new MyFlexTable();
}
protected RowItem getRowItem(final int row) {
return FancyFlexTable.<RowItem> getRowItem(table.getCellFormatter()
.getElement(row, 0));
}
protected void setRowItem(final int row, final RowItem item) {
setRowItem(table.getCellFormatter().getElement(row, 0), item);
}
protected void resetHtml(final SafeHtml body) {
for (final Iterator<Widget> i = table.iterator(); i.hasNext();) {
i.next();
i.remove();
}
impl.resetHtml(table, body);
}
protected void scrollIntoView(final int topRow, final int endRow) {
final CellFormatter fmt = table.getCellFormatter();
final Element top = DOM.getParent(fmt.getElement(topRow, C_ARROW));
final Element end = DOM.getParent(fmt.getElement(endRow, C_ARROW));
final int rTop = top.getAbsoluteTop();
final int rEnd = end.getAbsoluteTop() + end.getOffsetHeight();
final int rHeight = rEnd - rTop;
final int sTop = Document.get().getScrollTop();
final int sHeight = Document.get().getClientHeight();
final int sEnd = sTop + sHeight;
final int nTop;
if (sHeight <= rHeight) {
// The region is larger than the visible area, make the top
// exactly the top of the region, its the most visible area.
//
nTop = rTop;
} else if (sTop <= rTop && rTop <= sEnd) {
// At least part of the region is already visible.
//
if (rEnd <= sEnd) {
// ... actually its all visible. Don't scroll.
//
return;
}
// Move only enough to make the end visible.
//
nTop = sTop + (rHeight - (sEnd - rTop));
} else {
// None of the region is visible. Make it visible.
//
nTop = rTop;
}
Document.get().setScrollTop(nTop);
}
protected void applyDataRowStyle(final int newRow) {
table.getCellFormatter().addStyleName(newRow, C_ARROW, Gerrit.RESOURCES.css().iconCell());
table.getCellFormatter().addStyleName(newRow, C_ARROW, Gerrit.RESOURCES.css().leftMostCell());
}
/**
* Get the td element that contains another element.
*
* @param target the child element whose parent td is required.
* @return the td containing element {@code target}; null if {@code target} is
* not a member of this table.
*/
protected Element getParentCell(final Element target) {
final Element body = FancyFlexTableImpl.getBodyElement(table);
for (Element td = target; td != null && td != body; td = DOM.getParent(td)) {
// If it's a TD, it might be the one we're looking for.
if ("td".equalsIgnoreCase(td.getTagName())) {
// Make sure it's directly a part of this table.
Element tr = DOM.getParent(td);
if (DOM.getParent(tr) == body) {
return td;
}
}
}
return null;
}
/** @return the row of the child element; -1 if the child is not in the table. */
protected int rowOf(final Element target) {
final Element td = getParentCell(target);
if (td == null) {
return -1;
}
final Element tr = DOM.getParent(td);
final Element body = DOM.getParent(tr);
return DOM.getChildIndex(body, tr);
}
/** @return the cell of the child element; -1 if the child is not in the table. */
protected int columnOf(final Element target) {
final Element td = getParentCell(target);
if (td == null) {
return -1;
}
final Element tr = DOM.getParent(td);
return DOM.getChildIndex(tr, td);
}
protected static class MyFlexTable extends FlexTable {
}
private static final native <ItemType> void setRowItem(Element td, ItemType c)
/*-{ td['__gerritRowItem'] = c; }-*/;
private static final native <ItemType> ItemType getRowItem(Element td)
/*-{ return td['__gerritRowItem']; }-*/;
}