| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.swt.ole.win32; |
| |
| |
| import org.eclipse.swt.*; |
| import org.eclipse.swt.internal.*; |
| import org.eclipse.swt.internal.ole.win32.*; |
| import org.eclipse.swt.internal.win32.*; |
| |
| final class OlePropertyChangeSink { |
| |
| private OleControlSite controlSite; |
| //private IUnknown objIUnknown; |
| |
| private COMObject iUnknown; |
| private COMObject iPropertyNotifySink; |
| |
| private int refCount; |
| |
| private int propertyCookie; |
| |
| private OleEventTable eventTable; |
| |
| OlePropertyChangeSink(OleControlSite controlSite) { |
| |
| this.controlSite = controlSite; |
| |
| createCOMInterfaces(); |
| } |
| void addListener(int propertyID, OleListener listener) { |
| if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT); |
| if (eventTable == null) eventTable = new OleEventTable (); |
| eventTable.hook(propertyID, listener); |
| } |
| int AddRef() { |
| refCount++; |
| return refCount; |
| } |
| void connect(IUnknown objIUnknown) { |
| |
| // Set up property change notification sink |
| long /*int*/[] ppvObject = new long /*int*/[1]; |
| if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) { |
| IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]); |
| if (cpc.FindConnectionPoint(COM.IIDIPropertyNotifySink, ppvObject) == COM.S_OK) { |
| IConnectionPoint cp = new IConnectionPoint(ppvObject[0]); |
| int[] cookie = new int[1]; |
| if (cp.Advise(iPropertyNotifySink.getAddress(), cookie) == COM.S_OK) { |
| propertyCookie = cookie[0]; |
| } |
| cp.Release(); |
| } |
| cpc.Release(); |
| } |
| } |
| private void createCOMInterfaces() { |
| // register each of the interfaces that this object implements |
| iUnknown = new COMObject(new int[]{2, 0, 0}){ |
| @Override |
| public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);} |
| @Override |
| public long /*int*/ method1(long /*int*/[] args) {return AddRef();} |
| @Override |
| public long /*int*/ method2(long /*int*/[] args) {return Release();} |
| }; |
| |
| iPropertyNotifySink = new COMObject(new int[]{2, 0, 0, 1, 1}){ |
| @Override |
| public long /*int*/ method0(long /*int*/[] args) {return QueryInterface(args[0], args[1]);} |
| @Override |
| public long /*int*/ method1(long /*int*/[] args) {return AddRef();} |
| @Override |
| public long /*int*/ method2(long /*int*/[] args) {return Release();} |
| @Override |
| public long /*int*/ method3(long /*int*/[] args) {return OnChanged((int)/*64*/args[0]);} |
| @Override |
| public long /*int*/ method4(long /*int*/[] args) {return OnRequestEdit((int)/*64*/args[0]);} |
| }; |
| } |
| void disconnect(IUnknown objIUnknown) { |
| |
| // disconnect property notification sink |
| if (propertyCookie != 0 && objIUnknown != null) { |
| long /*int*/[] ppvObject = new long /*int*/[1]; |
| if (objIUnknown.QueryInterface(COM.IIDIConnectionPointContainer, ppvObject) == COM.S_OK) { |
| IConnectionPointContainer cpc = new IConnectionPointContainer(ppvObject[0]); |
| if (cpc.FindConnectionPoint(COM.IIDIPropertyNotifySink, ppvObject) == COM.S_OK) { |
| IConnectionPoint cp = new IConnectionPoint(ppvObject[0]); |
| if (cp.Unadvise(propertyCookie) == COM.S_OK) { |
| propertyCookie = 0; |
| } |
| cp.Release(); |
| } |
| cpc.Release(); |
| } |
| } |
| } |
| private void disposeCOMInterfaces() { |
| if (iUnknown != null) iUnknown.dispose(); |
| iUnknown = null; |
| if (iPropertyNotifySink != null) iPropertyNotifySink.dispose(); |
| iPropertyNotifySink = null; |
| } |
| /** |
| * Notify listeners of an event. |
| * <p> |
| * This method notifies all listeners that an event |
| * has occurred. |
| * |
| * @param eventType the desired SWT event |
| * @param event the event data |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT when handler is null</li> |
| * </ul> |
| * @exception SWTException <ul> |
| * <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li> |
| * <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li> |
| * </ul> |
| */ |
| private void notifyListener (int eventType, OleEvent event) { |
| if (event == null) OLE.error (SWT.ERROR_NULL_ARGUMENT); |
| if (eventTable == null) return; |
| event.type = eventType; |
| event.widget = controlSite; |
| eventTable.sendEvent (event); |
| } |
| private int OnChanged(int dispID) { |
| if (eventTable == null || !eventTable.hooks(dispID)) return COM.S_OK; |
| OleEvent event = new OleEvent(); |
| event.detail = OLE.PROPERTY_CHANGED; |
| notifyListener(dispID,event); |
| return COM.S_OK; |
| } |
| private int OnRequestEdit(int dispID) { |
| if (eventTable == null || !eventTable.hooks(dispID)) return COM.S_OK; |
| OleEvent event = new OleEvent(); |
| event.doit = true; |
| event.detail = OLE.PROPERTY_CHANGING; |
| notifyListener(dispID,event); |
| return (event.doit) ? COM.S_OK : COM.S_FALSE; |
| } |
| private int QueryInterface(long /*int*/ riid, long /*int*/ ppvObject) { |
| if (riid == 0 || ppvObject == 0) |
| return COM.E_INVALIDARG; |
| GUID guid = new GUID(); |
| COM.MoveMemory(guid, riid, GUID.sizeof); |
| if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) { |
| OS.MoveMemory(ppvObject, new long /*int*/[] {iUnknown.getAddress()}, C.PTR_SIZEOF); |
| AddRef(); |
| return COM.S_OK; |
| } |
| if (COM.IsEqualGUID(guid, COM.IIDIPropertyNotifySink)) { |
| OS.MoveMemory(ppvObject, new long /*int*/[] {iPropertyNotifySink.getAddress()}, C.PTR_SIZEOF); |
| AddRef(); |
| return COM.S_OK; |
| } |
| OS.MoveMemory(ppvObject, new long /*int*/[] {0}, C.PTR_SIZEOF); |
| return COM.E_NOINTERFACE; |
| } |
| int Release() { |
| refCount--; |
| if (refCount == 0) { |
| disposeCOMInterfaces(); |
| } |
| return refCount; |
| } |
| void removeListener(int propertyID, OleListener listener) { |
| if (listener == null) OLE.error (SWT.ERROR_NULL_ARGUMENT); |
| if (eventTable == null) return; |
| eventTable.unhook (propertyID, listener); |
| } |
| } |