Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

656 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dme_controls/dmepanel.h"
  7. #include "tier1/KeyValues.h"
  8. #include "dme_controls/dmecontrols.h"
  9. #include "vgui_controls/combobox.h"
  10. #include "datamodel/dmelement.h"
  11. #include "dme_controls/dmecontrols_utils.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. using namespace vgui;
  15. //-----------------------------------------------------------------------------
  16. // All DmePanels used by the system must be listed here to link them in
  17. //-----------------------------------------------------------------------------
  18. USING_DMEPANEL_FACTORY( CDmeElementPanel, DmElement );
  19. USING_DMEPANEL_FACTORY( CDmeSourceSkinPanel, DmeSourceSkin );
  20. USING_DMEPANEL_FACTORY( CAssetBuilder, DmeMakefile );
  21. USING_DMEPANEL_FACTORY( CDmeSourceDCCFilePanel, DmeSourceDCCFile );
  22. USING_DMEPANEL_FACTORY( CDmeDagRenderPanel, DmeDag );
  23. USING_DMEPANEL_FACTORY( CDmeDagRenderPanel, DmeSourceAnimation );
  24. USING_DMEPANEL_FACTORY( CDmeDagRenderPanel, DmeSourceSkin );
  25. USING_DMEPANEL_FACTORY( CDmeDagRenderPanel, DmeDCCMakefile );
  26. USING_DMEPANEL_FACTORY( CDmeDagEditPanel, DmeDag );
  27. USING_DMEPANEL_FACTORY( CDmeDagEditPanel, DmeSourceAnimation );
  28. USING_DMEPANEL_FACTORY( CDmeDagEditPanel, DmeSourceSkin );
  29. USING_DMEPANEL_FACTORY( CDmeDagEditPanel, DmeDCCMakefile );
  30. USING_DMEPANEL_FACTORY( CDmeMDLPanel, DmeMDLMakefile );
  31. //-----------------------------------------------------------------------------
  32. // constructor, destructor
  33. //-----------------------------------------------------------------------------
  34. CDmePanel::CDmePanel( vgui::Panel *pParent, const char *pPanelName, bool bComboBoxVisible ) :
  35. BaseClass( pParent, pPanelName )
  36. {
  37. m_pEditorNames = new vgui::ComboBox( this, "EditorDisplayNames", 6, false );
  38. if ( bComboBoxVisible )
  39. {
  40. m_pEditorNames->AddActionSignalTarget( this );
  41. }
  42. else
  43. {
  44. m_pEditorNames->SetVisible( false );
  45. }
  46. m_pDmeEditorPanel = NULL;
  47. m_hElement = NULL;
  48. SetDropEnabled( true );
  49. }
  50. CDmePanel::~CDmePanel()
  51. {
  52. DeleteCachedPanels();
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Scheme
  56. //-----------------------------------------------------------------------------
  57. void CDmePanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  58. {
  59. BaseClass::ApplySchemeSettings( pScheme );
  60. m_pEditorNames->SetFont( pScheme->GetFont( "DefaultVerySmall" ) );
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Layout
  64. //-----------------------------------------------------------------------------
  65. void CDmePanel::PerformLayout()
  66. {
  67. BaseClass::PerformLayout();
  68. int w, h;
  69. GetSize( w, h );
  70. if ( m_pEditorNames->IsVisible() )
  71. {
  72. m_pEditorNames->SetBounds( 1, 1, w-2, 20 );
  73. if ( m_pDmeEditorPanel )
  74. {
  75. m_pDmeEditorPanel->SetBounds( 0, 24, w, h-24 );
  76. }
  77. }
  78. else
  79. {
  80. if ( m_pDmeEditorPanel )
  81. {
  82. m_pDmeEditorPanel->SetBounds( 0, 0, w, h );
  83. }
  84. }
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Drag/drop
  88. //-----------------------------------------------------------------------------
  89. bool CDmePanel::IsDroppable( CUtlVector< KeyValues * >& msglist )
  90. {
  91. if ( msglist.Count() != 1 )
  92. return false;
  93. KeyValues *data = msglist[ 0 ];
  94. CDmElement *ptr = GetElementKeyValue<CDmElement>( data, "dmeelement" );
  95. if ( !ptr )
  96. return false;
  97. if ( ptr == m_hElement.Get() )
  98. return false;
  99. return true;
  100. }
  101. void CDmePanel::OnPanelDropped( CUtlVector< KeyValues * >& msglist )
  102. {
  103. if ( msglist.Count() != 1 )
  104. return;
  105. KeyValues *data = msglist[ 0 ];
  106. CDmElement *ptr = GetElementKeyValue<CDmElement>( data, "dmeelement" );
  107. if ( !ptr )
  108. return;
  109. // Already browsing
  110. if ( ptr == m_hElement.Get() )
  111. return;
  112. SetDmeElement( ptr );
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Sets the default editor type
  116. //-----------------------------------------------------------------------------
  117. void CDmePanel::SetDefaultEditorType( const char *pEditorType )
  118. {
  119. m_DefaultEditorType = pEditorType;
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Populate editor name combo box
  123. //-----------------------------------------------------------------------------
  124. void CDmePanel::PopulateEditorNames( const char *pPanelName )
  125. {
  126. m_pEditorNames->RemoveAll();
  127. m_pEditorNames->SetText( "" );
  128. if ( !m_pEditorNames->IsVisible() )
  129. {
  130. SetEditor( pPanelName );
  131. return;
  132. }
  133. if ( !m_hElement.Get() )
  134. {
  135. OnTextChanged();
  136. return;
  137. }
  138. const char *pPreferredEditor = NULL;
  139. if ( m_LastUsedEditorType.Defined( m_hElement->GetTypeString() ) )
  140. {
  141. pPreferredEditor = m_LastUsedEditorType[ m_hElement->GetTypeString() ].Get();
  142. }
  143. else
  144. {
  145. pPreferredEditor = m_DefaultEditorType;
  146. }
  147. int nBestInheritanceDepth = -1;
  148. int nActiveItemID = -1;
  149. bool bFoundPanelName = false;
  150. DmeFactoryHandle_t h = DmePanelFirstFactory( m_hElement.Get() );
  151. for ( ; h != DMEFACTORY_HANDLE_INVALID; h = DmePanelNextFactory( h, m_hElement.Get() ) )
  152. {
  153. const char *pDisplayName = DmePanelFactoryDisplayName( h );
  154. const char *pEditorName = DmePanelFactoryName( h );
  155. KeyValues *pKeyValues = new KeyValues( "entry", "editorName", pEditorName );
  156. int nItemID = m_pEditorNames->AddItem( pDisplayName, pKeyValues );
  157. if ( pPanelName && !Q_stricmp( pPanelName, pEditorName ) )
  158. {
  159. nBestInheritanceDepth = 0;
  160. nActiveItemID = nItemID;
  161. bFoundPanelName = true;
  162. continue;
  163. }
  164. if ( pPreferredEditor && !bFoundPanelName && !Q_stricmp( pPreferredEditor, pEditorName ) )
  165. {
  166. nBestInheritanceDepth = 0;
  167. nActiveItemID = nItemID;
  168. continue;
  169. }
  170. // Don't select this as the default if it's not a default factory
  171. if ( !DmePanelFactoryIsDefault(h) )
  172. continue;
  173. // Choose this factory if it's more derived than the previous best
  174. const char *pElementType = DmePanelFactoryElementType( h );
  175. int nInheritanceDepth = m_hElement->GetInheritanceDepth( pElementType );
  176. Assert( nInheritanceDepth >= 0 );
  177. if ( nBestInheritanceDepth >= 0 && ( nInheritanceDepth >= nBestInheritanceDepth ) )
  178. continue;
  179. nBestInheritanceDepth = nInheritanceDepth;
  180. nActiveItemID = nItemID;
  181. }
  182. if ( m_pEditorNames->GetItemCount() == 0 )
  183. {
  184. // ItemCount == 0;
  185. m_pEditorNames->SetText( "" );
  186. m_CurrentEditorName = NULL;
  187. OnTextChanged();
  188. return;
  189. }
  190. if ( nActiveItemID >= 0 )
  191. {
  192. m_pEditorNames->ActivateItem( nActiveItemID );
  193. }
  194. else
  195. {
  196. m_pEditorNames->ActivateItemByRow( 0 );
  197. }
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Called when the dme element was changed
  201. //-----------------------------------------------------------------------------
  202. void CDmePanel::OnDmeElementChanged()
  203. {
  204. PostActionSignal( new KeyValues( "DmeElementChanged" ) );
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Context menu support
  208. //-----------------------------------------------------------------------------
  209. void CDmePanel::OnOpenContextMenu( KeyValues *params )
  210. {
  211. // Forward the context menu message to the DME panel
  212. KeyValues *pMsg = params->MakeCopy();
  213. if ( m_pDmeEditorPanel )
  214. {
  215. PostMessage( m_pDmeEditorPanel->GetVPanel(), pMsg );
  216. }
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Copy/paste support
  220. //-----------------------------------------------------------------------------
  221. void CDmePanel::PostMessageToDmePanel( const char *pMessage )
  222. {
  223. if ( m_pDmeEditorPanel )
  224. {
  225. PostMessage( m_pDmeEditorPanel->GetVPanel(), new KeyValues( pMessage ) );
  226. }
  227. }
  228. void CDmePanel::OnCut()
  229. {
  230. PostMessageToDmePanel( "OnCut" );
  231. }
  232. void CDmePanel::OnCopy()
  233. {
  234. PostMessageToDmePanel( "OnCopy" );
  235. }
  236. void CDmePanel::OnPaste()
  237. {
  238. PostMessageToDmePanel( "OnPaste" );
  239. }
  240. void CDmePanel::OnPasteInsert()
  241. {
  242. PostMessageToDmePanel( "OnPasteInsert" );
  243. }
  244. void CDmePanel::OnPasteReference()
  245. {
  246. PostMessageToDmePanel( "OnPasteReference" );
  247. }
  248. void CDmePanel::OnEditDelete()
  249. {
  250. PostMessageToDmePanel( "OnEditDelete" );
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Called when a child of the dme panel switches the thing it's looking at
  254. //-----------------------------------------------------------------------------
  255. void CDmePanel::OnViewedElementChanged( KeyValues *kv )
  256. {
  257. // This is kind of tricky. It's called by the element properties tree
  258. // when doing the back/forward searching. Just calling the normal SetDmeElement
  259. // doesn't work because it reorders the history. What we want is to
  260. // populate the combo box without causing the OnTextChanged message to get sent.
  261. // FIXME: Perhaps it would be better to extract the back/forward/search
  262. // out of the element properties tree and put it into the dme panel?
  263. CDmElement *pElement = GetElementKeyValue<CDmElement>( kv, "dmeelement" );
  264. if ( pElement == m_hElement )
  265. return;
  266. // If the current editor isn't supported by this new element, then just reset. Too bad.
  267. bool bFound = false;
  268. if ( m_CurrentEditorName.Length() && pElement )
  269. {
  270. DmeFactoryHandle_t h = DmePanelFirstFactory( pElement );
  271. for ( ; h != DMEFACTORY_HANDLE_INVALID; h = DmePanelNextFactory( h, pElement ) )
  272. {
  273. const char *pEditorName = DmePanelFactoryName( h );
  274. if ( !Q_stricmp( m_CurrentEditorName, pEditorName ) )
  275. {
  276. bFound = true;
  277. break;
  278. }
  279. }
  280. }
  281. if ( !bFound )
  282. {
  283. SetDmeElement( pElement );
  284. return;
  285. }
  286. // Remove obsolete items
  287. int nCount = m_pEditorNames->GetItemCount();
  288. while ( --nCount >= 0 )
  289. {
  290. int nItemID = m_pEditorNames->GetItemIDFromRow( nCount );
  291. KeyValues *kv = m_pEditorNames->GetItemUserData( nItemID );
  292. if ( Q_stricmp( m_CurrentEditorName, kv->GetString( "editorName" ) ) )
  293. {
  294. m_pEditorNames->DeleteItem( nItemID );
  295. }
  296. }
  297. // Just want to populate the combo box with new items
  298. DmeFactoryHandle_t h = DmePanelFirstFactory( pElement );
  299. for ( ; h != DMEFACTORY_HANDLE_INVALID; h = DmePanelNextFactory( h, pElement ) )
  300. {
  301. const char *pEditorName = DmePanelFactoryName( h );
  302. if ( Q_stricmp( pEditorName, m_CurrentEditorName ) )
  303. {
  304. const char *pDisplayName = DmePanelFactoryDisplayName( h );
  305. KeyValues *pKeyValues = new KeyValues( "entry", "editorName", pEditorName );
  306. m_pEditorNames->AddItem( pDisplayName, pKeyValues );
  307. }
  308. }
  309. m_hElement = pElement;
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Delete cached panels
  313. //-----------------------------------------------------------------------------
  314. void CDmePanel::DeleteCachedPanels()
  315. {
  316. int nCount = m_EditorPanelCache.GetNumStrings();
  317. for ( int i = 0; i < nCount; ++i )
  318. {
  319. int nEditorCount = m_EditorPanelCache[ i ].Count();
  320. for ( int j = 0; j < nEditorCount; ++j )
  321. {
  322. m_EditorPanelCache[ i ][ j ].m_pEditorPanel->MarkForDeletion();
  323. }
  324. }
  325. m_EditorPanelCache.Clear();
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Refreshes the current panel owing to external change
  329. // Values only means no topological change
  330. //-----------------------------------------------------------------------------
  331. void CDmePanel::Refresh( bool bValuesOnly )
  332. {
  333. if ( m_pDmeEditorPanel )
  334. {
  335. KeyValues *pKeyValues = new KeyValues( "ElementChangedExternally", "valuesOnly", bValuesOnly );
  336. PostMessage( m_pDmeEditorPanel, pKeyValues );
  337. }
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Deactivates the current editor
  341. //-----------------------------------------------------------------------------
  342. void CDmePanel::DeactivateCurrentEditor()
  343. {
  344. if ( m_pDmeEditorPanel )
  345. {
  346. m_pDmeEditorPanel->SetParent( (vgui::Panel*)NULL );
  347. m_pDmeEditorPanel = NULL;
  348. m_CurrentEditorName = NULL;
  349. }
  350. }
  351. //-----------------------------------------------------------------------------
  352. // Switch to a new editor
  353. //-----------------------------------------------------------------------------
  354. void CDmePanel::SetEditor( const char *pEditorName )
  355. {
  356. if ( pEditorName && !Q_stricmp( m_CurrentEditorName, pEditorName ) )
  357. return;
  358. DeactivateCurrentEditor();
  359. if ( !m_hElement.Get() || !pEditorName )
  360. return;
  361. if ( m_EditorPanelCache.Defined( pEditorName ) )
  362. {
  363. CUtlVector< EditorPanelMap_t > &entries = m_EditorPanelCache[ pEditorName ];
  364. int nCount = entries.Count();
  365. for ( int i = 0; i < nCount; ++i )
  366. {
  367. EditorPanelMap_t &entry = entries[i];
  368. if ( !m_hElement->IsA( entry.m_pFactory->m_pElementType ) )
  369. continue;
  370. m_pDmeEditorPanel = entry.m_pEditorPanel;
  371. m_pDmeEditorPanel->SetParent( this );
  372. entry.m_pFactory->SetDmeElement( m_pDmeEditorPanel, m_hElement );
  373. break;
  374. }
  375. }
  376. if ( !m_pDmeEditorPanel )
  377. {
  378. EditorPanelMap_t entry;
  379. if ( CreateDmePanel( this, "DmePanelEditor", m_hElement, pEditorName, &entry ) )
  380. {
  381. m_EditorPanelCache[ pEditorName ].AddToTail( entry );
  382. m_pDmeEditorPanel = entry.m_pEditorPanel;
  383. }
  384. }
  385. if ( m_pDmeEditorPanel )
  386. {
  387. // Store the last selected type of editor
  388. m_LastUsedEditorType[ m_hElement->GetTypeString() ] = pEditorName;
  389. m_CurrentEditorName = pEditorName;
  390. m_pDmeEditorPanel->AddActionSignalTarget( this );
  391. }
  392. InvalidateLayout();
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Called when a new element in the combo box has been selected
  396. //-----------------------------------------------------------------------------
  397. void CDmePanel::OnTextChanged()
  398. {
  399. KeyValues *kv = m_pEditorNames->GetActiveItemUserData();
  400. const char *pEditorName = kv ? kv->GetString( "editorName", NULL ) : NULL;
  401. SetEditor( pEditorName );
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Setting a new element
  405. //-----------------------------------------------------------------------------
  406. void CDmePanel::SetDmeElement( CDmElement *pDmeElement, bool bForce, const char *pPanelName )
  407. {
  408. if ( ( m_hElement == pDmeElement ) && !bForce )
  409. {
  410. if ( !pPanelName || !Q_stricmp( pPanelName, m_CurrentEditorName.Get() ) )
  411. return;
  412. }
  413. m_hElement = pDmeElement;
  414. m_CurrentEditorName = NULL;
  415. // Populate the editor type list
  416. PopulateEditorNames( pPanelName );
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Statics for the panel factory
  420. //-----------------------------------------------------------------------------
  421. CBaseDmePanelFactory* CBaseDmePanelFactory::s_pFirstDmePanelFactory;
  422. //-----------------------------------------------------------------------------
  423. // Constructor
  424. //-----------------------------------------------------------------------------
  425. CBaseDmePanelFactory::CBaseDmePanelFactory( const char *pElementType, const char *pEditorName,
  426. const char *pEditorDisplayName, bool bIsDefault, bool bIsOverride )
  427. {
  428. // Prior to linking this in, look to see if this has been overridden
  429. CBaseDmePanelFactory *pPrevFactory = NULL;
  430. for( CBaseDmePanelFactory* pFactory = s_pFirstDmePanelFactory; pFactory;
  431. pPrevFactory = pFactory, pFactory = pFactory->m_pNext )
  432. {
  433. if ( !Q_stricmp( pFactory->m_pElementType, pElementType ) &&
  434. !Q_stricmp( pFactory->m_pEditorDisplayName, pEditorDisplayName ) )
  435. {
  436. // Collision found! If this is not an override, then we've been overridden
  437. if ( !bIsOverride )
  438. {
  439. AssertMsg( pFactory->m_bIsOverride, ( "Two DmePanel factories have the same name (\"%s\") + type (\"%s\")!\n", pElementType, pEditorName ) );
  440. return;
  441. }
  442. // If this *is* an override, replace the previous version
  443. AssertMsg( !pFactory->m_bIsOverride, ( "Two DmePanel factories have the same name (\"%s\") + type (\"%s\")!\n", pElementType, pEditorName ) );
  444. if ( pPrevFactory )
  445. {
  446. pPrevFactory->m_pNext = pFactory->m_pNext;
  447. }
  448. else
  449. {
  450. s_pFirstDmePanelFactory = pFactory->m_pNext;
  451. }
  452. break;
  453. }
  454. }
  455. m_pNext = s_pFirstDmePanelFactory;
  456. s_pFirstDmePanelFactory = this;
  457. m_pElementType = pElementType;
  458. m_pEditorName = pEditorName;
  459. m_pEditorDisplayName = pEditorDisplayName;
  460. m_bIsDefault = bIsDefault;
  461. m_bIsOverride = bIsOverride;
  462. }
  463. //-----------------------------------------------------------------------------
  464. // Dme Panel factory iteration methods
  465. //-----------------------------------------------------------------------------
  466. DmeFactoryHandle_t DmePanelFirstFactory( CDmElement *pElement )
  467. {
  468. CBaseDmePanelFactory *pFactory = CBaseDmePanelFactory::s_pFirstDmePanelFactory;
  469. for ( ; pFactory; pFactory = pFactory->m_pNext )
  470. {
  471. if ( !pElement || pElement->IsA( pFactory->m_pElementType ) )
  472. return (DmeFactoryHandle_t)pFactory;
  473. }
  474. return DMEFACTORY_HANDLE_INVALID;
  475. }
  476. DmeFactoryHandle_t DmePanelNextFactory( DmeFactoryHandle_t h, CDmElement *pElement )
  477. {
  478. CBaseDmePanelFactory *pFactory = (CBaseDmePanelFactory*)h;
  479. if ( !pFactory )
  480. return DMEFACTORY_HANDLE_INVALID;
  481. for ( pFactory = pFactory->m_pNext; pFactory; pFactory = pFactory->m_pNext )
  482. {
  483. if ( !pElement || pElement->IsA( pFactory->m_pElementType ) )
  484. return (DmeFactoryHandle_t)pFactory;
  485. }
  486. return DMEFACTORY_HANDLE_INVALID;
  487. }
  488. //-----------------------------------------------------------------------------
  489. // Dme Panel factory info methods
  490. //-----------------------------------------------------------------------------
  491. const char *DmePanelFactoryName( DmeFactoryHandle_t h )
  492. {
  493. CBaseDmePanelFactory *pFactory = (CBaseDmePanelFactory*)h;
  494. return pFactory ? pFactory->m_pEditorName : NULL;
  495. }
  496. const char *DmePanelFactoryDisplayName( DmeFactoryHandle_t h )
  497. {
  498. CBaseDmePanelFactory *pFactory = (CBaseDmePanelFactory*)h;
  499. return pFactory ? pFactory->m_pEditorDisplayName : NULL;
  500. }
  501. const char *DmePanelFactoryElementType( DmeFactoryHandle_t h )
  502. {
  503. CBaseDmePanelFactory *pFactory = (CBaseDmePanelFactory*)h;
  504. return pFactory ? pFactory->m_pElementType : NULL;
  505. }
  506. bool DmePanelFactoryIsDefault( DmeFactoryHandle_t h )
  507. {
  508. CBaseDmePanelFactory *pFactory = (CBaseDmePanelFactory*)h;
  509. return pFactory ? pFactory->m_bIsDefault : false;
  510. }
  511. //-----------------------------------------------------------------------------
  512. // Dme Panel factory methods
  513. //-----------------------------------------------------------------------------
  514. bool CDmePanel::CreateDmePanel( vgui::Panel *pParent, const char *pPanelName, CDmElement *pElement, const char *pEditorName, EditorPanelMap_t *pMap )
  515. {
  516. int nBestInheritanceDepth = -1;
  517. CBaseDmePanelFactory *pBestFactory = NULL;
  518. CBaseDmePanelFactory *pFactory = CBaseDmePanelFactory::s_pFirstDmePanelFactory;
  519. for ( ; pFactory; pFactory = pFactory->m_pNext )
  520. {
  521. if ( !pElement->IsA( pFactory->m_pElementType ) )
  522. continue;
  523. if ( pEditorName )
  524. {
  525. if ( !Q_stricmp( pEditorName, pFactory->m_pEditorName ) )
  526. {
  527. pBestFactory = pFactory;
  528. break;
  529. }
  530. continue;
  531. }
  532. // No editor name specified? Only use default factories
  533. if ( !pFactory->m_bIsDefault )
  534. continue;
  535. // Choose this factory if it's more derived than the previous best
  536. int nInheritanceDepth = pElement->GetInheritanceDepth( pFactory->m_pElementType );
  537. Assert( nInheritanceDepth >= 0 );
  538. if ( nBestInheritanceDepth >= 0 && ( nInheritanceDepth > nBestInheritanceDepth ) )
  539. continue;
  540. nBestInheritanceDepth = nInheritanceDepth;
  541. pBestFactory = pFactory;
  542. }
  543. if ( pBestFactory )
  544. {
  545. pMap->m_pFactory = pBestFactory;
  546. pMap->m_pEditorPanel = pBestFactory->CreateDmePanel( pParent, pPanelName, pElement );
  547. return true;
  548. }
  549. return false;
  550. }