GME
13
|
00001 #include "stdafx.h" 00002 #include "MakeSimpleClosure.h" 00003 #include "GUIDCreate.h" 00004 #include <algorithm> 00005 00006 //--------------------------------------------------------------------------- 00007 // C L A S S CSimpleSelectClosure 00008 // enabler of SmartCopy 00009 //--------------------------------------------------------------------------- 00010 #define GLOBAL_ID_STR "guid" 00011 00012 bool CSimpleSelectClosure::isValidSelection() 00013 { 00014 // be more permissive than the base class 00015 // allows connections thru refport also 00016 return true; 00017 } 00018 00019 void CSimpleSelectClosure::manageGuid( CComObjPtr<IMgaObject> object) 00020 { 00021 if( object) 00022 { 00023 CComObjPtr<IMgaRegNode> regnode; 00024 00025 CComObjPtr<IMgaFCO> fco; 00026 object.QueryInterface( fco); 00027 if( fco) COMTHROW( fco->get_RegistryNode( CComBSTR( GLOBAL_ID_STR), PutOut( regnode))); 00028 else 00029 { 00030 CComObjPtr<IMgaFolder> folder; 00031 object.QueryInterface( folder); 00032 if( folder) COMTHROW( folder->get_RegistryNode( CComBSTR( GLOBAL_ID_STR), PutOut( regnode))); 00033 else ASSERT(0); 00034 } 00035 00036 // in case object is in Library, do not write anything into registry 00037 VARIANT_BOOL vbLibrary; 00038 COMTHROW( object->get_IsLibObject( &vbLibrary ) ); 00039 00040 if( regnode && !vbLibrary) 00041 { 00042 long status; 00043 COMTHROW( regnode->get_Status(&status) ); 00044 if( status != ATTSTATUS_HERE) //UNDEFINED, METADEF, INVALID, ARCHETYPE1,2,... 00045 COMTHROW( regnode->put_Value( GuidCreate::newGuid())); 00046 } 00047 } 00048 } 00049 00050 // there is not much magic: process down the hierarchy (folders and models) 00051 void CSimpleSelectClosure::procObj( IMgaObject* obj) 00052 { 00053 ASSERT( obj != NULL ); 00055 //if ( m_iIntoLibraries != LIB_CONT && isInLibrary( obj)) // if no intention to step into libraries and the object is in a library then return 00056 // return; 00057 // library elements are handled the same way as the usual objects, 00058 // except no guids are stored in their registry 00059 00060 objtype_enum objtype; 00061 COMTHROW( obj->get_ObjType( &objtype) ); 00062 00063 // now mark the object itself (with a guid), later mark its dependents (ref, mem) 00064 manageGuid( obj); 00065 00066 switch( objtype) 00067 { 00068 case OBJTYPE_FOLDER: 00069 { 00070 if ( m_bFolderContainment) 00071 { 00072 CComObjPtr<IMgaFolder> f; 00073 COMTHROW( ::QueryInterface( obj, f) ); 00074 procFolder( f); 00075 } 00076 break; 00077 } 00078 case OBJTYPE_MODEL: 00079 { 00080 if ( m_bContainment) 00081 { 00082 CComObjPtr<IMgaModel> m; 00083 COMTHROW( ::QueryInterface( obj, m) ); 00084 00085 procModel( m); 00086 } 00087 break; 00088 } 00089 00090 case OBJTYPE_ATOM: break; 00091 case OBJTYPE_REFERENCE: 00092 { 00093 CComObjPtr<IMgaReference> r; 00094 COMTHROW( ::QueryInterface( obj, r) ); 00095 00096 // mark its referred object (if any) 00097 CComObjPtr<IMgaFCO> refd; 00098 COMTHROW( r->get_Referred( PutOut( refd))); 00099 manageGuid( CComObjPtr<IMgaObject>( refd)); 00100 break; 00101 } 00102 case OBJTYPE_CONNECTION: 00103 { 00104 CComObjPtr<IMgaConnection> c; 00105 COMTHROW( ::QueryInterface( obj, c) ); 00106 00107 CComObjPtrVector<IMgaConnPoint> cps; 00108 COMTHROW( c->get_ConnPoints( PutOut( cps))); 00109 for( unsigned int i = 0; i < cps.size(); ++i) 00110 { 00111 // mark the endpoint 00112 CComObjPtr<IMgaFCO> target; 00113 COMTHROW( cps[i]->get_Target(PutOut(target)) ); 00114 manageGuid( CComObjPtr<IMgaObject>( target)); 00115 00116 // mark the ref chain 00117 CComObjPtrVector<IMgaFCO> refs; 00118 COMTHROW( cps[i]->get_References(PutOut(refs)) ); 00119 for( unsigned int i = 0; i < refs.size(); ++i) 00120 manageGuid( CComObjPtr<IMgaObject>( refs[i])); 00121 } 00122 00123 break; 00124 } 00125 case OBJTYPE_SET: 00126 { 00127 CComObjPtr<IMgaSet> s; 00128 COMTHROW( ::QueryInterface( obj, s) ); 00129 CComObjPtrVector<IMgaFCO> mems; 00130 COMTHROW( s->get_Members( PutOut( mems))); 00131 for( unsigned int i = 0; i < mems.size(); ++i) 00132 manageGuid( CComObjPtr<IMgaObject>( mems[i])); 00133 break; 00134 } 00135 }; 00136 } 00137 00138 void CSimpleSelectClosure::preProcess() 00139 { 00140 send2Console("[Smart Copy] Working..."); 00141 } 00142 00143 void CSimpleSelectClosure::postProcess() 00144 { 00145 //remove specified unneeded kinds 00146 if( removeExcludedKinds()) 00147 { // all objects were removed by the filter 00148 send2Console( "[Smart Copy] No object in selection."); 00149 return; 00150 } 00151 00152 // sort the elements based on: basetypes first, connections last rule 00153 std::sort( m_selFcos.begin(), m_selFcos.end(), ConnsAndDerivsLast()); 00154 00155 selectTop(); // calculate the parentless objects 00156 autoWrap(); // wrapping (resets the Top values) 00157 // normally if objects selected from the View 00158 // would not wrap much 00159 // if initial objects selected from the activebrowser 00160 // it might have to do something 00161 00162 checkMeta( m_topFolds, m_topFcos); // calculate the accepting kind 00163 00164 std::string res_str; 00165 getAccKindsInString( res_str); 00166 if( !res_str.empty()) send2Console( "[Smart Copy] The following kinds may accept the copied data: " + res_str + "."); 00167 else send2Console( "[Smart Copy] Possible accepting kind not found based on the meta."); 00168 } 00169 00170 bool CSimpleSelectClosure::removeExcludedKinds() 00171 { 00172 // we filter out the excluded kinds even from the initially selected objects 00173 // that is why we don't use the base's kindfilter mechanism (that filters out 00174 // only children of models, folders) 00175 // worth to mention: connections are initially selected by the GUI if both of 00176 // their ends is selected also, thus it may happen that the user would like 00177 // connections excluded, but if they are initially selected by the mechanism 00178 // outlined above then the base's filter would not catch that 00179 CComObjPtrVector<IMgaFCO>::iterator it = m_selFcos.begin(); 00180 while( it != m_selFcos.end()) 00181 { 00182 CComQIPtr<IMgaAtom> a = *it; 00183 CComQIPtr<IMgaConnection> c = *it; 00184 CComQIPtr<IMgaReference> r = *it; 00185 CComQIPtr<IMgaSet> s = *it; 00186 00187 if( m_bExclAtom && a // if atom and atoms need to be excluded OR 00188 || m_bExclConn && c // ... 00189 || m_bExclRef && r 00190 || m_bExclSet && s) 00191 it = m_selFcos.erase( it); // erase will step forward the iterator 00192 else 00193 ++it; 00194 } 00195 00196 return m_selFcos.size() + m_selFolds.size() == 0; // all objects were removed by the filter 00197 } 00198 00199 bool ConnsAndDerivsLast::operator()( const CComObjPtr<IMgaFCO>& p1, const CComObjPtr<IMgaFCO>& p2) const 00200 { 00201 // used for sort. 00202 // 0th rule: derived types will be put after the archetypes 00203 // 1st rule: Connections will be put in the back of the vector 00204 // 2nd rule: if the two elements are both connections or none of them is connection then sort on ID 00205 // returns true if p1 precedes p2 00206 00207 objtype_enum objtype1, objtype2; 00208 CComObjPtr<IMgaFCO> bas1, bas2; 00209 COMTHROW( p1->get_ArcheType( PutOut(bas1))); // returns 0 for archetypes 00210 COMTHROW( p2->get_ArcheType( PutOut(bas2))); 00211 bool p1_is_der = bas1 != 0; 00212 bool p2_is_der = bas2 != 0; 00213 COMTHROW( p1->get_ObjType( &objtype1)); 00214 COMTHROW( p2->get_ObjType( &objtype2)); 00215 00216 // compare on deriv or not? 00217 bool sim = objtype1 == objtype2; 00218 if( sim && p1_is_der != p2_is_der) 00219 return p2_is_der;//IF p1 is F, p2 is T ->ret true, IF p1 is T, p2 is F ->ret false 00220 00221 // sim is F or p1_is_der == p2_is_der 00222 00223 // compare on conn or not? 00224 bool c1 = objtype1 == OBJTYPE_CONNECTION; 00225 bool c2 = objtype2 == OBJTYPE_CONNECTION; 00226 00227 if( c1 == c2) 00228 { 00229 //return true;// the predicate must be a strict weak ordering, so let's compare the IDs 00230 CComBstrObj bstr1, bstr2; 00231 COMTHROW( p1->get_ID( PutOut( bstr1))); 00232 COMTHROW( p2->get_ID( PutOut( bstr2))); 00233 return bstr1.Compare( bstr2) < 0; 00234 } 00235 else 00236 return c2; // IF c2 is T, c1 is F -> ret true, IF c2 is F, c1 is T ->ret false 00237 }