1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.ole.win32.OlePropertyChangeSink;
14 
15 
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.SWTException;
18 import org.eclipse.swt.internal.ole.win32.COM;
19 import org.eclipse.swt.internal.ole.win32.extras;
20 import org.eclipse.swt.internal.ole.win32.ifs;
21 
22 import org.eclipse.swt.ole.win32.OleControlSite;
23 import org.eclipse.swt.ole.win32.OleEventTable;
24 import org.eclipse.swt.ole.win32.OleListener;
25 import org.eclipse.swt.ole.win32.OleEvent;
26 import org.eclipse.swt.ole.win32.OleEventTable;
27 import org.eclipse.swt.ole.win32.OLE;
28 
29 final class OlePropertyChangeSink {
30 
31     private OleControlSite controlSite;
32     //private IUnknown objIUnknown;
33 
34     //private COMObject iUnknown;
35     private _IPropertyNotifySinkImpl iPropertyNotifySink;
36 
37     private int refCount;
38 
39     private int propertyCookie;
40 
41     private OleEventTable eventTable;
42 
43 this(OleControlSite controlSite) {
44 
45     this.controlSite = controlSite;
46 
47     createCOMInterfaces();
48 }
49 void addListener(int propertyID, OleListener listener) {
50     if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
51     if (eventTable is null) eventTable = new OleEventTable ();
52     eventTable.hook(propertyID, listener);
53 }
54 int AddRef() {
55     refCount++;
56     return refCount;
57 }
58 void connect(IUnknown objIUnknown) {
59 
60     // Set up property change notification sink
61     IConnectionPointContainer cpc;
62     if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
63         IConnectionPoint cp;
64         if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
65             uint cookie;
66             if (cp.Advise(iPropertyNotifySink, &cookie) is COM.S_OK) {
67                 propertyCookie = cookie;
68             }
69             cp.Release();
70         }
71         cpc.Release();
72     }
73 }
74 protected void createCOMInterfaces() {
75     // register each of the interfaces that this object implements
76     iPropertyNotifySink = new _IPropertyNotifySinkImpl(this);
77 }
78 void disconnect(IUnknown objIUnknown) {
79 
80     // disconnect property notification sink
81     if (propertyCookie !is 0 && objIUnknown !is null) {
82         IConnectionPointContainer cpc;
83         if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
84             IConnectionPoint cp;
85             if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
86                 if (cp.Unadvise(propertyCookie) is COM.S_OK) {
87                     propertyCookie = 0;
88                 }
89                 cp.Release();
90             }
91             cpc.Release();
92         }
93     }
94 }
95 private void disposeCOMInterfaces() {
96     iPropertyNotifySink = null;
97 }
98 /**
99 * Notify listeners of an event.
100 * <p>
101 *   This method notifies all listeners that an event
102 * has occurred.
103 *
104 * @param eventType the desired SWT event
105 * @param event the event data
106 *
107 * @exception IllegalArgumentException <ul>
108 *       <li>ERROR_NULL_ARGUMENT when handler is null</li>
109 * </ul>
110 * @exception SWTException <ul>
111 *       <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
112 *       <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
113 *   </ul>
114 */
115 private void notifyListener (int eventType, OleEvent event) {
116     if (event is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
117     if (eventTable is null) return;
118     event.type = eventType;
119     event.widget = controlSite;
120     eventTable.sendEvent (event);
121 }
122 package int OnChanged(int dispID) {
123     if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
124     OleEvent event = new OleEvent();
125     event.detail = OLE.PROPERTY_CHANGED;
126     notifyListener(dispID,event);
127     return COM.S_OK;
128 }
129 package int OnRequestEdit(int dispID) {
130     if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
131     OleEvent event = new OleEvent();
132     event.doit = true;
133     event.detail = OLE.PROPERTY_CHANGING;
134     notifyListener(dispID,event);
135     return (event.doit) ? COM.S_OK : COM.S_FALSE;
136 }
137 protected HRESULT QueryInterface(REFCIID riid, void ** ppvObject) {
138     if (riid is null || ppvObject is null)
139         return COM.E_INVALIDARG;
140 
141     if (COM.IsEqualGUID(riid, &COM.IIDIPropertyNotifySink)) {
142         *ppvObject = cast(void*)cast(IPropertyNotifySink)iPropertyNotifySink;
143         AddRef();
144         return COM.S_OK;
145     }
146     *ppvObject = null;
147     return COM.E_NOINTERFACE;
148 }
149 int Release() {
150     refCount--;
151     if (refCount is 0) {
152         disposeCOMInterfaces();
153     }
154     return refCount;
155 }
156 void removeListener(int propertyID, OleListener listener) {
157     if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
158     if (eventTable is null) return;
159     eventTable.unhook (propertyID, listener);
160 }
161 }
162 
163 
164 private class _IPropertyNotifySinkImpl : IPropertyNotifySink {
165 
166     OlePropertyChangeSink   parent;
167     this(OlePropertyChangeSink  p) { parent = p; }
168 extern (Windows):
169     // interface of IUnknown
170     HRESULT QueryInterface(REFCIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
171     ULONG AddRef()  { return parent.AddRef(); }
172     ULONG Release() { return parent.Release(); }
173 
174     // interface of IPropertyNotifySink
175     int OnChanged(int dispID) { return parent.OnChanged(dispID); }
176     int OnRequestEdit(int dispID) { return parent.OnRequestEdit(dispID); }
177 }
178 
179 
180 
181