--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client.ui;
+
+import com.google.gwt.user.client.Command;
+import com.itmill.toolkit.terminal.gwt.client.Client;
+
+/**
+ *
+ */
+public class IAction implements Command {
+
+ IActionOwner owner;
+
+ String targetKey = "";
+ String actionKey = "";
+
+ String iconUrl = null;
+
+ String caption = "";
+
+ public IAction(IActionOwner owner) {
+ this.owner = owner;
+ }
+
+ public IAction(IActionOwner owner, String target, String action) {
+ this(owner);
+ this.targetKey = target;
+ this.actionKey = action;
+ }
+
+
+ /**
+ * Sends message to server that this action has been fired.
+ * Messages are "standard" Toolkit messages whose value is comma
+ * separated pair of targetKey (row, treeNod ...) and actions id.
+ *
+ * Variablename is always "action".
+ *
+ * Actions are always sent immediatedly to server.
+ */
+ public void execute() {
+ owner.getClient().updateVariable(
+ owner.getPaintableId(),
+ "action",
+ targetKey + "," + actionKey,
+ true);
+ owner.getClient().getContextMenu().hide();
+ }
+
+ public String getActionKey() {
+ return actionKey;
+ }
+
+ public void setActionKey(String actionKey) {
+ this.actionKey = actionKey;
+ }
+
+ public String getTargetKey() {
+ return targetKey;
+ }
+
+ public void setTargetKey(String targetKey) {
+ this.targetKey = targetKey;
+ }
+
+ public String getHTMLRepresentation() {
+ StringBuffer sb = new StringBuffer();
+ if(iconUrl != null) {
+ sb.append("<img src=\""+iconUrl+"\" alt=\"icon\" />");
+ }
+ sb.append(caption);
+ return sb.toString();
+ }
+
+ public String getCaption() {
+ return caption;
+ }
+
+ public void setCaption(String caption) {
+ this.caption = caption;
+ }
+}
+
+/**
+ * Action owner must provide a set of actions for context menu
+ * and IAction objects.
+ */
+interface IActionOwner {
+
+ /**
+ * @return Array of IActions
+ */
+ public IAction[] getActions();
+
+ public Client getClient();
+
+ public String getPaintableId();
+}
\ No newline at end of file
--- /dev/null
+package com.itmill.toolkit.terminal.gwt.client.ui;
+
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.MenuBar;
+import com.google.gwt.user.client.ui.MenuItem;
+import com.google.gwt.user.client.ui.PopupPanel;
+
+public class IContextMenu extends PopupPanel {
+
+ private IActionOwner actionOwner;
+
+ private CMenuBar menu = new CMenuBar();
+
+ /**
+ * This method should be used only by Client object as
+ * only one per client should exists. Request an instance
+ * via client.getContextMenu();
+ *
+ * @param cli to be set as an owner of menu
+ */
+ public IContextMenu() {
+ super(true);
+ setWidget(menu);
+ setStyleName("i-contextmenu");
+ }
+
+ /**
+ * Sets the element from which to build menu
+ * @param ao
+ */
+ public void setActionOwner(IActionOwner ao) {
+ this.actionOwner = ao;
+ }
+
+ /**
+ * Shows context menu at given location.
+ *
+ * @param left
+ * @param top
+ */
+ public void showAt(int left, int top) {
+ menu.clearItems();
+ IAction[] actions = actionOwner.getActions();
+ for (int i = 0; i < actions.length; i++) {
+ IAction a = actions[i];
+ menu.addItem(new MenuItem(a.getHTMLRepresentation(), true, a));
+ }
+
+ setPopupPosition(left, top);
+
+ show();
+ }
+
+ public void showAt(IActionOwner ao, int left, int top) {
+ setActionOwner(ao);
+ showAt(left, top);
+
+ }
+
+ /**
+ * Extend standard Gwt MenuBar to set proper settings and
+ * to override onPopupClosed method so that PopupPanel gets
+ * closed.
+ */
+ class CMenuBar extends MenuBar {
+ public CMenuBar() {
+ super(true);
+ }
+
+ public void onPopupClosed(PopupPanel sender, boolean autoClosed) {
+ super.onPopupClosed(sender, autoClosed);
+ IContextMenu.this.hide();
+ }
+ }
+}
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
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.Panel;
import com.google.gwt.user.client.ui.ScrollListener;
private String[] columnOrder;
private Client client;
- private String id;
+ private String paintableId;
private boolean immediate;
private String sortColumn;
private boolean columnReordering;
+ /**
+ * This map contains captions and icon urls for
+ * actions like:
+ * * "33_c" -> "Edit"
+ * * "33_i" -> "http://dom.com/edit.png"
+ */
+ private HashMap actionMap = new HashMap();
+
public IScrollTable() {
headerContainer.setStyleName("iscrolltable-header");
headerContainer.add(tHead);
return;
this.client = client;
- this.id = uidl.getStringAttribute("id");
+ this.paintableId = uidl.getStringAttribute("id");
this.immediate = uidl.getBooleanAttribute("immediate");
this.totalRows = uidl.getIntAttribute("totalrows");
this.pageLength = uidl.getIntAttribute("pagelength");
}
private void updateActionMap(UIDL c) {
- // TODO Auto-generated method stub
+ Iterator it = c.getChildIterator();
+ while(it.hasNext()) {
+ UIDL action = (UIDL) it.next();
+ String key = action.getStringAttribute("key");
+ String caption = action.getStringAttribute("caption");
+ actionMap.put(key + "_c", caption);
+ if(action.hasAttribute("icon")) {
+ // TODO need some uri handling ??
+ actionMap.put(key + "_i", action.getStringAttribute("icon"));
+ }
+ }
}
+
+ public String getActionCaption(String actionKey) {
+ return (String) actionMap.get(actionKey + "_c");
+ }
+
+ public String getActionIcon(String actionKey) {
+ return (String) actionMap.get(actionKey + "_i");
+ }
+
private void updateHeader(UIDL uidl) {
if(uidl == null)
newOrder[index++] = ((HeaderCell) hCells.next()).getColKey();
}
columnOrder = newOrder;
- client.updateVariable(id, "columnorder", newOrder, false);
+ client.updateVariable(paintableId, "columnorder", newOrder, false);
}
int lastRendered = tBody.getLastRendered();
int firstRendered = tBody.getFirstRendered();
if( postLimit <= lastRendered && preLimit >= firstRendered ) {
- client.updateVariable(this.id, "firstvisible", firstRowInViewPort, false);
+ client.updateVariable(this.paintableId, "firstvisible", firstRowInViewPort, false);
return; // scrolled withing "non-react area"
}
public void run() {
client.console.log("Getting " + reqRows + " rows from " + reqFirstRow);
- client.updateVariable(id, "firstvisible", firstRowInViewPort, false);
- client.updateVariable(id, "reqfirstrow", reqFirstRow, false);
- client.updateVariable(id, "reqrows", reqRows, true);
+ client.updateVariable(paintableId, "firstvisible", firstRowInViewPort, false);
+ client.updateVariable(paintableId, "reqfirstrow", reqFirstRow, false);
+ client.updateVariable(paintableId, "reqrows", reqRows, true);
}
public int getReqFirstRow() {
if(sortable) {
if(sortColumn.equals(cid)) {
// just toggle order
- client.updateVariable(id, "sortascending", !sortAscending, false);
+ client.updateVariable(paintableId, "sortascending", !sortAscending, false);
} else {
// set table scrolled by this column
- client.updateVariable(id, "sortcolumn", cid, false);
+ client.updateVariable(paintableId, "sortcolumn", cid, false);
}
// get also cache columns at the same request
bodyContainer.setScrollPosition(0);
}
- public class IScrollTableRow extends Panel {
+ public class IScrollTableRow extends Panel implements IActionOwner {
Vector childWidgets = new Vector();
private boolean selected = false;
private int rowKey;
+ private String[] actionKeys = null;
+
private IScrollTableRow(int rowKey) {
this.rowKey = rowKey;
- this.selected = selected;
setElement(DOM.createElement("tr"));
- DOM.sinkEvents(getElement(), Event.BUTTON_RIGHT | Event.ONCLICK);
+ DOM.sinkEvents(getElement(), Event.ONCLICK);
+ disableContextMenu(getElement());
setStyleName("iscrolltable-row");
}
+ private native void disableContextMenu(Element el) /*-{
+ var row = this;
+ el.oncontextmenu = function(e) {
+ if(!e)
+ e = window.event;
+ row.@com.itmill.toolkit.terminal.gwt.client.ui.IScrollTable.IScrollTableBody.IScrollTableRow::showContextMenu(Lcom/google/gwt/user/client/Event;)(e);
+ return false;
+ };
+ }-*/;
+
public String getKey() {
return String.valueOf(rowKey);
}
public IScrollTableRow(UIDL uidl) {
this(uidl.getIntAttribute("key"));
+
+ // row header
if(uidl.hasAttribute("caption"))
addCell(uidl.getStringAttribute("caption"));
+
+ if(uidl.hasAttribute("al"))
+ actionKeys = uidl.getStringArrayAttribute("al");
+
Iterator cells = uidl.getChildIterator();
while(cells.hasNext()) {
Object cell = cells.next();
(( Paintable) cellContent).updateFromUIDL((UIDL) cell, client);
}
}
- if(uidl.hasAttribute("selected"))
+ if(uidl.hasAttribute("selected") && !isSelected())
toggleSelection();
}
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
- case Event.BUTTON_RIGHT:
- // TODO
- System.out.println("Context menu");
- break;
-
case Event.ONCLICK:
- System.out.println("Row click");
+ client.console.log("Row click");
if(selectMode > ITable.SELECT_MODE_NONE) {
toggleSelection();
- client.updateVariable(id, "selected", selectedRowKeys.toArray(), immediate);
+ client.updateVariable(paintableId, "selected", selectedRowKeys.toArray(), immediate);
}
break;
}
super.onBrowserEvent(event);
}
+
+ public void showContextMenu(Event event) {
+ client.console.log("Context menu");
+ if(actionKeys != null) {
+ int left = DOM.eventGetClientX(event);
+ int top = DOM.eventGetClientY(event);
+ client.getContextMenu().showAt(this, left, top);
+ }
+ }
public boolean isSelected() {
return selected;
setStyleName("iscrolltable-row");
}
}
-
- }
+ public IAction[] getActions() {
+ if(actionKeys == null)
+ return new IAction[] {};
+ IAction[] actions = new IAction[actionKeys.length];
+ for (int i = 0; i < actions.length; i++) {
+ String actionKey = actionKeys[i];
+ IAction a = new IAction(this, String.valueOf(rowKey), actionKey);
+ a.setCaption(getActionCaption(actionKey));
+ actions[i] = a;
+ }
+ return actions;
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ public String getPaintableId() {
+ return paintableId;
+ }
+ }
}
public void deselectAll() {