001 /*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005
006 package org.bridj.cpp.mfc;
007
008 import org.bridj.BridJ;
009 import org.bridj.Callback;
010 import org.bridj.NativeObject;
011 import org.bridj.Pointer;
012 import org.bridj.util.Utils;
013 import org.bridj.cpp.CPPRuntime;
014
015 import java.lang.reflect.Method;
016 import java.lang.reflect.Type;
017 import java.util.HashSet;
018 import java.util.Map;
019 import java.util.Set;
020
021 /**
022 *
023 * @author Olivier
024 */
025 public class MFCRuntime extends CPPRuntime {
026 Method mfcGetMessageMap;
027 String mfcGetMessageMapMangling;
028 Callback mfcGetMessageMapCallback;
029
030 Set<Class<?>> hasMessageMap = new HashSet<Class<?>>();
031
032 @Override
033 public <T extends NativeObject> Class<? extends T> getActualInstanceClass(Pointer<T> pInstance, Type officialType) {
034 Class officialTypeClass = Utils.getClass(officialType);
035 // For MFC classes, use GetRuntimeClass()
036 if (CObject.class.isAssignableFrom(officialTypeClass)) {
037 Pointer<CRuntimeClass> pClass = new CObject((Pointer)pInstance, this).GetRuntimeClass();
038 if (pClass != null) {
039 CRuntimeClass rtc = pClass.get();
040 try {
041 Class<? extends T> type = (Class)getMFCClass(rtc.m_lpszClassName());
042 if (officialTypeClass == null || officialTypeClass.isAssignableFrom(type))
043 return type;
044 } catch (ClassNotFoundException ex) {}
045 return officialTypeClass;
046 }
047 }
048
049 // TODO Auto-generated method stub
050 return super.getActualInstanceClass(pInstance, officialType);
051 }
052
053 private Class<?> getMFCClass(Pointer<Byte> mLpszClassName) throws ClassNotFoundException {
054 throw new ClassNotFoundException(mLpszClassName.getCString());
055 }
056
057 public void getExtraFieldsOfNewClass(Class<?> type, Map<String, Type> out) {
058 //super.getExtraFieldsOfNewClass(type, out);
059 if (!hasMessageMap.contains(type))
060 return;
061
062 out.put("messageMap", Pointer.class);
063 }
064
065 public void getOverriddenVirtualMethods(Map<String, Pointer<?>> out) {
066 //super.getVirtualMethodBindings(out);
067 out.put("mfcGetMessageMap", Pointer.pointerTo(mfcGetMessageMapCallback));
068 }
069
070 @Override
071 public void register(Type type) {
072 super.register(type);
073 Class typeClass = Utils.getClass(type);
074
075 MessageMapBuilder map = new MessageMapBuilder();
076 for (Method method : typeClass.getMethods()) {
077
078 OnCommand onCommand = method.getAnnotation(OnCommand.class);
079 if (onCommand != null)
080 map.add(method, onCommand);
081
082 OnCommandEx onCommandEx = method.getAnnotation(OnCommandEx.class);
083 if (onCommandEx != null)
084 map.add(method, onCommandEx);
085
086 OnUpdateCommand onUpdateCommand = method.getAnnotation(OnUpdateCommand.class);
087 if (onUpdateCommand != null)
088 map.add(method, onUpdateCommand);
089
090 OnRegisteredMessage onRegisteredMessage = method.getAnnotation(OnRegisteredMessage.class);
091 if (onRegisteredMessage != null)
092 map.add(method, onRegisteredMessage);
093
094 OnMessage onMessage = method.getAnnotation(OnMessage.class);
095 if (onMessage != null)
096 map.add(method, onMessage);
097 }
098 if (!map.isEmpty())
099 map.register(this, typeClass);
100
101 }
102 }