import java.util.HashMap;
import java.util.Iterator;
-import java.util.Map;
+import java.util.Vector;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.ScrollListener;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.itmill.toolkit.terminal.gwt.client.Client;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
private boolean initializedAndAttached = false;
- private Grid tHead = new Grid(1,1);
+ private TableHead tHead = new TableHead();
private ScrollPanel bodyContainer = new ScrollPanel();
if(uidl == null)
return;
int columnCount = uidl.getChidlCount();
- if(rowHeaders)
+ int colIndex = 0;
+ if(rowHeaders) {
columnCount++;
- tHead.resizeColumns(columnCount);
+ HeaderCell c = (HeaderCell) tHead.getHeaderCell(0);
+ if(c == null) {
+ tHead.setHeaderCell(0, new HeaderCell("0", ""));
+ }
+ colIndex++;
+ }
for(Iterator it = uidl.getChildIterator();it.hasNext();) {
UIDL col = (UIDL) it.next();
String cid = col.getStringAttribute("cid");
- int colIndex = getColIndexByKey(cid);
- if(colIndex > -1) {
- HeaderCell c = (HeaderCell) tHead.getWidget(0, colIndex);
- if(c != null && c.getColKey().equals(cid)) {
- c.setText(col.getStringAttribute("caption"));
- } else {
- c = new HeaderCell(cid, col.getStringAttribute("caption"));
- tHead.setWidget(0, colIndex, c );
- }
- if(col.hasAttribute("sortable")) {
- c.setSortable(true);
- if(cid.equals(sortColumn))
- c.setSorted(true);
- else
- c.setSorted(false);
- }
+ HeaderCell c = (HeaderCell) tHead.getHeaderCell(colIndex);
+ if(c != null && c.getColKey().equals(cid)) {
+ c.setText(col.getStringAttribute("caption"));
+ } else {
+ c = new HeaderCell(cid, col.getStringAttribute("caption"));
+ tHead.setHeaderCell(colIndex, c);
}
- }
- if(rowHeaders) {
- HeaderCell c = (HeaderCell) tHead.getWidget(0, 0);
- if(c == null) {
- tHead.setWidget(0, 0, new HeaderCell("0", ""));
+ if(col.hasAttribute("sortable")) {
+ c.setSortable(true);
+ if(cid.equals(sortColumn))
+ c.setSorted(true);
+ else
+ c.setSorted(false);
}
+ colIndex++;
}
}
private int getColIndexByKey(String colKey) {
- return Integer.parseInt(colKey) - 1 + (rowHeaders ? 1 : 0);
+ // return 0 if asked for rowHeaders
+ if("0".equals(colKey))
+ return 0;
+ int index = -1;
+ for (int i = 0; i < columnOrder.length; i++) {
+ if(columnOrder[i].equals(colKey)) {
+ index = i;
+ break;
+ }
+ }
+ if(rowHeaders)
+ index++;
+ return index;
}
private String getColKeyByIndex(int index) {
- return ((HeaderCell) tHead.getWidget(0, index)).getColKey();
+ return tHead.getHeaderCell(index).getColKey();
}
private void setColWidth(int colIndex, int w) {
- HeaderCell cell = (HeaderCell) tHead.getWidget(0, colIndex);
+ HeaderCell cell = tHead.getHeaderCell(colIndex);
cell.setWidth(w);
tBody.setColWidth(colIndex, w);
String cid = cell.getColKey();;
private int getRenderedRowCount() {
return tBody.getLastRendered()-tBody.getFirstRendered();
}
+
+ private void reOrderColumn(String columnKey, int newIndex) {
+
+ int oldIndex = getColIndexByKey(columnKey);
+
+ // Change header order
+ tHead.moveCell(oldIndex, newIndex);
+
+ // Change body order
+ tBody.moveCol(oldIndex, newIndex);
+
+ // build new columnOrder and update it to server
+
+ String[] newOrder = new String[columnOrder.length];
+
+ Iterator hCells = tHead.iterator();
+
+ if(rowHeaders)
+ hCells.next();
+ int index = 0;
+ while(hCells.hasNext()) {
+ newOrder[index++] = ((HeaderCell) hCells.next()).getColKey();
+ }
+ columnOrder = newOrder;
+ client.updateVariable(id, "columnorder", newOrder, false);
+
+ }
/**
* This method has logick which rows needs to be requested from
protected void onAttach() {
super.onAttach();
+ int bodyWidth = tBody.getOffsetWidth();
// sync column widths
initColumnWidths();
}
if(width < 0) {
+ bodyWidth = tBody.getOffsetWidth();
bodyContainer.setWidth((tBody.getOffsetWidth() + getScrollBarWidth() ) + "px");
headerContainer.setWidth((tBody.getOffsetWidth()) + "px");
} else {
headerContainer.setWidth(width + "px");
}
+ tHead.disableBrowserIntelligence();
+
if(firstvisible > 0)
bodyContainer.setScrollPosition(firstvisible*tBody.getRowHeight());
* "natural widths and saves the values.
*/
private void initColumnWidths() {
- int cols = tHead.getCellCount(0);
- CellFormatter hf = tHead.getCellFormatter();
- for (int i = 0; i < cols; i++) {
- Element hCell = hf.getElement(0, i);
- int hw = DOM.getIntAttribute(hCell, "offsetWidth");
- int cw = tBody.getColWidth(i);
- int w = (hw > cw ? hw : cw) + IScrollTableBody.CELL_EXTRA_WIDTH;
- setColWidth(i , w);
- }
+ Iterator headCells = tHead.iterator();
+ int i = 0;
+ while(headCells.hasNext()) {
+ Element hCell = ((HeaderCell) headCells.next()).getElement();
+ int hw = DOM.getIntAttribute(hCell, "offsetWidth");
+ int cw = tBody.getColWidth(i);
+ int w = (hw > cw ? hw : cw) + IScrollTableBody.CELL_EXTRA_WIDTH;
+ setColWidth(i , w);
+ i++;
+ }
}
private int getScrollBarWidth() {
private static final int MINIMUM_COL_WIDTH = 20;
- // TODO create a simple single row table widget that has these widgets as cells
- // and change next line to ...DOM.createTD();
- // Grid is way too overkill for this and it removes on extra div from document structure
- Element td = DOM.createDiv();
+ Element td = DOM.createTD();
Element captionContainer = DOM.createDiv();
private boolean moved;
+ private int closestSlot;
+
private HeaderCell(){};
case Event.ONMOUSEDOWN:
dragging = true;
moved = false;
+ colIndex = getColIndexByKey(cid);
DOM.setCapture(getElement());
System.out.println("Started column reordering");
this.headerX = tHead.getAbsoluteLeft();
break;
case Event.ONMOUSEUP:
dragging = false;
+ if(!moved) {
+ // sort
+ break;
+ }
System.out.println("Stopped column reordering");
+ tHead.removeSlotFocus();
+ if(closestSlot != colIndex && closestSlot != (colIndex + 1) ) {
+ if(closestSlot > colIndex)
+ reOrderColumn(cid, closestSlot - 1);
+ else
+ reOrderColumn(cid, closestSlot);
+ }
DOM.releaseCapture(getElement());
break;
case Event.ONMOUSEMOVE:
System.out.print("Dragging column, optimal index...");
int x = DOM.eventGetClientX(event);
int slotX = headerX;
- int closestIndex = 0;
+ closestSlot = colIndex;
int closestDistance = -1;
int start = 0;
if(rowHeaders) {
start++;
- slotX += getColWidth(getColKeyByIndex(0));
}
- for(int i = start ; i < columnWidths.size(); i++ ) {
- String colKey = getColKeyByIndex(i);
+ for(int i = start; i <= columnWidths.size() ; i++ ) {
+ if(i > 0) {
+ String colKey = getColKeyByIndex(i-1);
+ slotX += getColWidth(colKey);
+ }
int dist = Math.abs(x - slotX);
if(closestDistance == -1 || dist < closestDistance) {
closestDistance = dist;
- closestIndex = i;
+ closestSlot = i;
}
- slotX += getColWidth(colKey);
}
- focusSlot(closestIndex);
- System.out.println(closestIndex);
-
+ tHead.focusSlot(closestSlot);
+ System.out.println(closestSlot);
}
break;
default:
}
}
- private void focusSlot(int slot) {
- // TODO consider some workaround for this
- removeSlotFocus();
- DOM.setStyleAttribute(tHead.getCellFormatter().getElement(0, slot), "borderLeft", "2px solid black");
- }
-
- private void removeSlotFocus() {
- for(int i = 0; i < tHead.getColumnCount();i++)
- DOM.setStyleAttribute(tHead.getCellFormatter().getElement(0, i), "borderLeft", "none");
- }
-
private int getClosestColumnIndex(int x) {
return 1;
}
}
+ public class TableHead extends Panel {
+
+ private static final int WRAPPER_WIDTH = 9000;
+
+ Vector cells = new Vector();
+
+ Element div = DOM.createDiv();
+ Element table = DOM.createTable();
+ Element tBody = DOM.createTBody();
+ Element tr = DOM.createTR();
+
+ private int focusedSlot = -1;
+
+ public TableHead() {
+ DOM.appendChild(table, tBody);
+ DOM.appendChild(tBody, tr);
+ DOM.appendChild(div, table);
+ setElement(div);
+ }
+
+ public void disableBrowserIntelligence() {
+ DOM.setStyleAttribute(div, "width", WRAPPER_WIDTH +"px");
+ }
+
+ public void setHeaderCell(int index, HeaderCell cell) {
+ if(index < cells.size()) {
+ // replace
+ // TODO remove old correctly
+ // insert to right slot
+ } else if( index == cells.size()) {
+ //append
+ adopt(cell, tr);
+ cells.add(cell);
+ } else {
+ throw new RuntimeException("Header cells must be appended in order");
+ }
+ }
+
+ public HeaderCell getHeaderCell(int index) {
+ if(index < cells.size())
+ return (HeaderCell) cells.get(index);
+ else
+ return null;
+ }
+
+ public void moveCell(int oldIndex, int newIndex) {
+ HeaderCell hCell = getHeaderCell(oldIndex);
+ Element cell = hCell.getElement();
+
+ cells.remove(oldIndex);
+ DOM.removeChild(tr, cell);
+
+ DOM.insertChild(tr, cell, newIndex);
+ cells.insertElementAt(hCell, newIndex);
+ }
+
+ public Iterator iterator() {
+ return cells.iterator();
+ }
+
+ public boolean remove(Widget w) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private void focusSlot(int index) {
+ removeSlotFocus();
+ if(index > 0)
+ DOM.setStyleAttribute(DOM.getChild(tr, index - 1), "borderRight", "2px solid black");
+ else
+ DOM.setStyleAttribute(DOM.getChild(tr, index), "borderLeft", "2px solid black");
+ focusedSlot = index;
+ }
+
+ private void removeSlotFocus() {
+ if(focusedSlot < 0)
+ return;
+ if(focusedSlot == 0)
+ DOM.setStyleAttribute(DOM.getChild(tr, focusedSlot), "borderLeft", "none");
+ else if( focusedSlot > 0)
+ DOM.setStyleAttribute(DOM.getChild(tr, focusedSlot - 1), "borderRight", "none");
+ focusedSlot = -1;
+ }
+
+
+ }
+
}