View Javadoc
1   package org.vaadin.peter.contextmenu.client;
2   
3   import org.vaadin.peter.contextmenu.ContextMenu;
4   import org.vaadin.peter.contextmenu.client.ContextMenuState.ContextMenuItemState;
5   
6   import com.google.gwt.core.client.GWT;
7   import com.google.gwt.dom.client.EventTarget;
8   import com.google.gwt.event.dom.client.ContextMenuEvent;
9   import com.google.gwt.event.dom.client.ContextMenuHandler;
10  import com.google.gwt.event.logical.shared.CloseEvent;
11  import com.google.gwt.event.logical.shared.CloseHandler;
12  import com.google.gwt.user.client.Element;
13  import com.google.gwt.user.client.ui.PopupPanel;
14  import com.google.gwt.user.client.ui.Widget;
15  import com.vaadin.client.ComponentConnector;
16  import com.vaadin.client.ServerConnector;
17  import com.vaadin.client.Util;
18  import com.vaadin.client.communication.RpcProxy;
19  import com.vaadin.client.communication.StateChangeEvent;
20  import com.vaadin.client.extensions.AbstractExtensionConnector;
21  import com.vaadin.client.ui.VScrollTable;
22  import com.vaadin.client.ui.VTree;
23  import com.vaadin.shared.ui.Connect;
24  
25  /**
26   * ContextMenuConnector is client side object that receives updates from server
27   * and passes them to context menu client side widget. Connector is also
28   * responsible for handling user interaction and communicating it back to
29   * server.
30   * 
31   * @author Peter Lehto / Vaadin Ltd
32   */
33  @Connect(ContextMenu.class)
34  public class ContextMenuConnector extends AbstractExtensionConnector {
35  	private static final long serialVersionUID = 3830712282306785118L;
36  
37  	private ContextMenuWidget widget;
38  
39  	private Widget extensionTarget;
40  
41  	private ContextMenuServerRpc clientToServerRPC = RpcProxy.create(
42  			ContextMenuServerRpc.class, this);
43  
44  	private CloseHandler<PopupPanel> contextMenuCloseHandler = new CloseHandler<PopupPanel>() {
45  		@Override
46  		public void onClose(CloseEvent<PopupPanel> popupPanelCloseEvent) {
47  			clientToServerRPC.contextMenuClosed();
48  		}
49  	};
50  
51  	private final ContextMenuHandler contextMenuHandler = new ContextMenuHandler() {
52  
53  		@Override
54  		public void onContextMenu(ContextMenuEvent event) {
55  			event.preventDefault();
56  			event.stopPropagation();
57  
58  			EventTarget eventTarget = event.getNativeEvent().getEventTarget();
59  
60  			ComponentConnector connector = Util.getConnectorForElement(
61  					getConnection(), getConnection().getUIConnector()
62  							.getWidget(), (Element) eventTarget.cast());
63  
64  			Widget clickTargetWidget = connector.getWidget();
65  
66  			if (extensionTarget.equals(clickTargetWidget)) {
67  				if (getState().isOpenAutomatically()) {
68  					widget.showContextMenu(event.getNativeEvent().getClientX(),
69  							event.getNativeEvent().getClientY());
70  				} else {
71  					clientToServerRPC.onContextMenuOpenRequested(event
72  							.getNativeEvent().getClientX(), event
73  							.getNativeEvent().getClientY(), connector
74  							.getConnectorId());
75  				}
76  			}
77  		}
78  	};
79  
80  	@SuppressWarnings("serial")
81  	private ContextMenuClientRpc serverToClientRPC = new ContextMenuClientRpc() {
82  
83  		@Override
84  		public void showContextMenu(int x, int y) {
85  			widget.showContextMenu(x, y);
86  		}
87  	};
88  
89  	@Override
90  	protected void init() {
91  		widget = GWT.create(ContextMenuWidget.class);
92  		widget.addCloseHandler(contextMenuCloseHandler);
93  		registerRpc(ContextMenuClientRpc.class, serverToClientRPC);
94  	}
95  
96  	@Override
97  	public ContextMenuState getState() {
98  		return (ContextMenuState) super.getState();
99  	}
100 
101 	@Override
102 	public void onStateChanged(StateChangeEvent stateChangeEvent) {
103 		super.onStateChanged(stateChangeEvent);
104 
105 		widget.clearItems();
106 
107 		for (ContextMenuItemState rootItem : getState().getRootItems()) {
108 			widget.addRootMenuItem(rootItem, this);
109 		}
110 	}
111 
112 	@Override
113 	protected void extend(ServerConnector extensionTarget) {
114 		this.extensionTarget = ((ComponentConnector) extensionTarget)
115 				.getWidget();
116 
117 		// Table and Tree are currently handled with their internal
118 		// ItemClickListeners as their current implementations are not too
119 		// extension friendly.
120 		if (this.extensionTarget instanceof VScrollTable) {
121 			return;
122 		} else if (this.extensionTarget instanceof VTree) {
123 			return;
124 		}
125 
126 		this.extensionTarget.addDomHandler(contextMenuHandler,
127 				ContextMenuEvent.getType());
128 	}
129 }