GME  13
PartBrowserPane.cpp
Go to the documentation of this file.
00001 // PartBrowserPane.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "PartBrowserPane.h"
00006 #include "PartBrowserPaneFrame.h"
00007 #include "..\Annotator\AnnotationDefs.h"
00008 #include "..\GME\GMEOLEData.h"
00009 #include <algorithm>
00010 
00011 
00012 #ifdef _DEBUG
00013 #define new DEBUG_NEW
00014 #undef THIS_FILE
00015 static char THIS_FILE[] = __FILE__;
00016 #endif
00017 
00018 // from GME
00019 typedef enum { GME_NAME_FONT = 0, GME_PORTNAME_FONT, GME_CONNLABEL_FONT, GME_FONT_KIND_NUM } GMEFontKind;
00020 static int  fontSizes[GME_FONT_KIND_NUM]        = { 18, 15, 12 };
00021 #define GME_DEFAULT_DECORATOR           "MGA.BoxDecorator"
00022 #define DECORATOR_PREF                          "decorator"
00023 typedef CTypedPtrList<CPtrList, CRect *>        CRectList;
00024 
00026 // CPartBrowserPane
00027 
00028 Gdiplus::SmoothingMode          CPartBrowserPane::m_eEdgeAntiAlias = Gdiplus::SmoothingModeHighQuality;         // Edge smoothing mode
00029 Gdiplus::TextRenderingHint      CPartBrowserPane::m_eFontAntiAlias = Gdiplus::TextRenderingHintAntiAlias;       // Text renndering hint mode
00030 
00031 CPartBrowserPane::CPartBrowserPane():
00032         mgaProject(NULL),
00033         mgaMetaModel(NULL),
00034         currentAspectIndex(-1),
00035         omitPaintMessages(true)
00036 {
00037         backgroundColor = ::GetSysColor(COLOR_APPWORKSPACE);
00038         txtMetricFont.CreateFont(fontSizes[GME_NAME_FONT], 0, 0, 0, FW_NORMAL, false, 0, 0, ANSI_CHARSET,
00039                                                          OUT_DEVICE_PRECIS, CLIP_DEFAULT_PRECIS,
00040                                                          PROOF_QUALITY, FF_SWISS, _T("Arial"));
00041 }
00042 
00043 CPartBrowserPane::~CPartBrowserPane()
00044 {
00045         txtMetricFont.DeleteObject();
00046 }
00047 
00048 CComBSTR CPartBrowserPane::GetDecoratorProgId(IMgaMetaFCO* metaFCO)
00049 {
00050         CComBSTR pathBstr(DECORATOR_PREF);
00051         CComBSTR bstrVal;
00052         COMTHROW(metaFCO->get_RegistryValue(pathBstr,&bstrVal));
00053         if (bstrVal.Length() <= 0)
00054                 bstrVal = GME_DEFAULT_DECORATOR;
00055         return bstrVal;
00056 }
00057 
00058 bool CPartBrowserPane::IsPartDisplayable(CComPtr<IMgaMetaPart> metaPart)
00059 {
00060         ASSERT(metaPart != NULL);
00061         VARIANT_BOOL vb_primary;
00062         COMTHROW(metaPart->get_IsPrimary(&vb_primary));
00063         CComPtr<IMgaMetaRole> mmRole;
00064         COMTHROW(metaPart->get_Role(&mmRole));
00065         CComPtr<IMgaMetaFCO> mFco;
00066         COMTHROW(mmRole->get_Kind(&mFco));
00067         objtype_enum oType;
00068         COMTHROW(mFco->get_ObjType(&oType));
00069 
00070         if (vb_primary != VARIANT_FALSE &&
00071                 (oType == OBJTYPE_MODEL ||
00072                  oType == OBJTYPE_REFERENCE ||
00073                  oType != OBJTYPE_CONNECTION))
00074         {
00075                 return true;
00076         }
00077         return false;
00078 }
00079 
00080 bool CPartBrowserPane::FindObject(CPoint &pt, PartWithDecorator& pdt)
00081 {
00082         if (currentAspectIndex < 0 || pdts.size() <= 0)
00083                 return NULL;
00084 
00085         try {
00086                 const std::vector<PartWithDecorator>& pdtv = pdts[currentAspectIndex];
00087                 // calculate the maximum size
00088                 for (std::vector<PartWithDecorator>::const_iterator ii = pdtv.begin(); ii != pdtv.end(); ++ii) {
00089                         ASSERT((*ii).decorator != NULL);
00090                         long x1 = 0; long y1 = 0;
00091                         long x2 = 0; long y2 = 0;
00092                         COMTHROW((*ii).decorator->GetLocation(&x1, &y1, &x2, &y2));
00093                         CRect rc (x1, y1, x2, y2);
00094                         if (rc.PtInRect(pt)) {
00095                                 pdt = (*ii);
00096 
00097                                 long sizeX = 0;
00098                                 long sizeY = 0;
00099                                 COMTHROW((*ii).decorator->GetPreferredSize(&sizeX, &sizeY));
00100 
00101                                 return true;
00102                         }
00103                 }
00104         }
00105         catch (hresult_exception&) {
00106         }
00107 
00108         return false;
00109 }
00110 
00111 void CPartBrowserPane::CreateDecorators(CComPtr<IMgaMetaParts> metaParts)
00112 {
00113         std::vector<PartWithDecorator> pdt;
00114         try {
00115                 CComPtr<IMgaMetaPart> metaPart;
00116                 MGACOLL_ITERATE(IMgaMetaPart, metaParts) {
00117                         metaPart = MGACOLL_ITER;
00118                         if (IsPartDisplayable(metaPart)) {
00119                                 PartWithDecorator tuple;
00120                                 tuple.part = metaPart;
00121 
00122                                 IMgaMetaRolePtr mmRole = metaPart->Role;
00123                                 IMgaMetaFCOPtr mFco = mmRole->Kind;
00124                                 IMgaDecoratorPtr decorator;
00125                                 IMgaElementDecoratorPtr newDecorator;
00126                                 CComBSTR decoratorProgId = GetDecoratorProgId(mFco);
00127 
00128                                 CString nameString;
00129                                 _bstr_t bstrKindName = mFco->Name;
00130                                 _bstr_t bstrRoleName = mmRole->Name;
00131                                 if (bstrKindName == bstrRoleName) {
00132                                         _bstr_t bstrDisplayedName = mFco->DisplayedName;
00133                                         nameString = (const wchar_t*)bstrDisplayedName;
00134                                 }
00135                                 else {
00136                                         nameString = (const wchar_t*)bstrRoleName;
00137                                 }
00138                                 tuple.name = nameString;
00139 
00140                                 HRESULT hres = newDecorator.CreateInstance((LPCWSTR)decoratorProgId);
00141                                 if (FAILED(hres) && hres != CO_E_CLASSSTRING) { // might be an old decorator
00142                                         hres = decorator.CreateInstance(PutInBstr(decoratorProgId));
00143                                 }
00144                                 if (FAILED(hres)) {     // fall back to default decorator
00145                                         COMTHROW(newDecorator.CreateInstance(GME_DEFAULT_DECORATOR));
00146                                 }
00147 
00148                                 if (newDecorator) {
00149                                         tuple.newDecorator = newDecorator;
00150                                         // KMS: this is a workaround for a bug in many decorators: QI(IID_IMgaDecorator) returns E_NOINTERFACE
00151                                         // (Fixed in MetaGME and UML in r1367)
00152                                         decorator = (IMgaDecorator*)(IMgaElementDecorator*)newDecorator;
00153                                         newDecorator->__InitializeEx(mgaProject, metaPart, NULL, NULL /*decorEventSinkIface*/, (ULONGLONG)m_hWnd);
00154                                 } else {
00155                                         decorator->__Initialize(mgaProject, metaPart, NULL);
00156                                 }
00157 
00158                                 long sx, sy;
00159                                 decorator->__GetPreferredSize(&sx, &sy);
00160                                 decorator->__SetLocation(0, 0, sx, sy);
00161                                 tuple.decorator = decorator;
00162 
00163                                 pdt.push_back(tuple);
00164                         }
00165                 }
00166                 MGACOLL_ITERATE_END;
00167         }
00168         catch (hresult_exception& e) {
00169                 _bstr_t error;
00170                 GetErrorInfo(e.hr, error.GetAddress());
00171                 error = L"Part Browser decorator error: " + error;
00172                 CGMEDataSource::get_GME(CComObjPtr<IMgaProject>(mgaProject))->ConsoleMessage(error, MSG_ERROR);
00173                 return;
00174         }
00175         catch (_com_error& e) {
00176                 CGMEDataSource::get_GME(CComObjPtr<IMgaProject>(mgaProject))->ConsoleMessage(_bstr_t(L"Couldn't initialize decorator: " + e.Description()), MSG_ERROR);
00177                 return;
00178         }
00179         std::sort(pdt.begin(), pdt.end(), [](const PartWithDecorator& a, const PartWithDecorator& b){ return a.name < b.name; });
00180         pdts.push_back(std::move(pdt));
00181 }
00182 
00183 void CPartBrowserPane::DestroyDecorators(void)
00184 {
00185         for (std::vector<std::vector<PartWithDecorator> >::iterator ii = pdts.begin(); ii != pdts.end(); ++ii) {
00186                 for (std::vector<PartWithDecorator>::iterator jj = (*ii).begin(); jj != (*ii).end(); ++jj) {
00187                         (*jj).decorator->Destroy();
00188                         if ((*jj).newDecorator) {
00189                                 (*jj).newDecorator.Release();
00190                                 (*jj).newDecorator = NULL;
00191                         }
00192                         (*jj).decorator.Release();
00193                         (*jj).decorator = NULL;
00194                         (*jj).part.Release();
00195                 }
00196                 (*ii).clear();
00197         }
00198         pdts.clear();
00199 }
00200 
00201 void CPartBrowserPane::Resize(CRect r)
00202 {
00203         if (!mgaMetaModel || currentAspectIndex < 0 || pdts.size() <= 0 || currentAspectIndex >= (int)pdts.size())
00204                 return;
00205 
00206         bool oldOmitPaintMessages = omitPaintMessages;
00207         omitPaintMessages = true;
00208         ChangeAspect(currentAspectIndex);
00209         omitPaintMessages = oldOmitPaintMessages;
00210 
00211         const int leftMargin = 10;
00212         const int rightMargin = 10;
00213         const int topMargin = 10;
00214         const int bottomMargin = 30;
00215 
00216         const int xPadding = 10;
00217         const int yPadding = 30;
00218 
00219         // set the location
00220         int objColumn = 0;
00221         int leftStartPos = leftMargin + maxSize.cx / 2;
00222         int rowHeight = 0;
00223 
00224         // calculate the actual offset
00225         int objNumInRow = (r.Width() - leftMargin - rightMargin + xPadding) / (maxSize.cx + xPadding);
00226         if (objNumInRow < 1) {
00227                 objNumInRow = 1;
00228                 leftStartPos = r.Width() / 2 - 3;
00229         }
00230 
00231         // the pt contains the x center point, and y top point
00232         CPoint pt = CPoint(leftStartPos, topMargin);
00233 
00234         try {
00235                 const std::vector<PartWithDecorator>& pdtv = pdts[currentAspectIndex];
00236                 // calculate the maximum size
00237                 for (std::vector<PartWithDecorator>::const_iterator ii = pdtv.begin(); ii != pdtv.end(); ++ii) {
00238                         ASSERT((*ii).decorator != NULL);
00239                         long sizeX = 0;
00240                         long sizeY = 0;
00241                         COMTHROW((*ii).decorator->GetPreferredSize(&sizeX, &sizeY));
00242                         CSize size(sizeX, sizeY);
00243 
00244                         // calculate the row height
00245                         if (objColumn == 0) {
00246                                 rowHeight = size.cy;
00247 
00248                                 std::vector<PartWithDecorator>::const_iterator iibak = ii;
00249                                 for (std::vector<PartWithDecorator>::const_iterator jj = ++ii; jj != pdtv.end() && (objColumn + 1) < objNumInRow; ++jj) {
00250                                         ASSERT((*jj).decorator != NULL);
00251                                         long sizeX2 = 0;
00252                                         long sizeY2 = 0;
00253                                         COMTHROW((*jj).decorator->GetPreferredSize(&sizeX2, &sizeY2));
00254                                         CSize size2 (sizeX2, sizeY2);
00255 
00256                                         if (rowHeight < size2.cy)
00257                                                 rowHeight = size2.cy;
00258 
00259                                         ++objColumn;
00260                                 }
00261                                 ii = iibak;
00262 
00263                                 objColumn = 0;
00264                                 pt.y += rowHeight / 2;
00265                         }
00266 
00267                         // set the location (based on center: pt is the center)
00268                         COMTHROW((*ii).decorator->SetLocation(pt.x - (size.cx - size.cx / 2), pt.y - (size.cy - size.cy / 2), pt.x + size.cx / 2, pt.y + size.cy / 2));
00269 
00270                         if (++objColumn >= objNumInRow) {
00271                                 objColumn = 0;
00272                                 pt.x = leftStartPos;
00273                                 pt.y += rowHeight / 2 + yPadding;
00274                         } else {
00275                                 pt.x += maxSize.cx + xPadding;
00276                         }
00277                 }
00278         }
00279         catch (hresult_exception&) {
00280         }
00281 
00282         omitPaintMessages = false;
00283 
00284         // if no object in this row
00285         if (objColumn == 0)
00286                 pt.y -= yPadding;
00287         else
00288                 pt.y += rowHeight / 2;
00289 
00290         pt.y += bottomMargin;
00291 
00292         CPartBrowserPaneFrame* parent = (CPartBrowserPaneFrame*)GetParent();
00293         ASSERT(parent != NULL);
00294 
00295         parent->SetLogicalHeight(pt.y);
00296         parent->SetPageHeight(r.Height());
00297         parent->SetScrollBar();
00298 
00299         Invalidate();
00300 }
00301 
00302 void CPartBrowserPane::SetCurrentProject(CComPtr<IMgaProject> project)
00303 {
00304         if (mgaProject != NULL)
00305                 mgaProject.Release();
00306         mgaProject = project;
00307 }
00308 
00309 void CPartBrowserPane::SetMetaModel(CComPtr<IMgaMetaModel> meta)
00310 {
00311         CComPtr<IMgaRegistrar> registrar;
00312         COMTHROW(registrar.CoCreateInstance(CComBSTR(L"Mga.MgaRegistrar")));
00313         ASSERT(registrar != NULL);
00314         edgesmoothmode_enum edgeSmoothMode;
00315         COMTHROW(registrar->get_EdgeSmoothMode(REGACCESS_USER, &edgeSmoothMode));
00316         m_eEdgeAntiAlias = (Gdiplus::SmoothingMode)edgeSmoothMode;
00317         fontsmoothmode_enum fontSmoothMode;
00318         COMTHROW(registrar->get_FontSmoothMode(REGACCESS_USER, &fontSmoothMode));
00319         m_eFontAntiAlias = (Gdiplus::TextRenderingHint)fontSmoothMode;
00320 
00321         if (mgaMetaModel != NULL)
00322                 mgaMetaModel.Release();
00323         mgaMetaModel = meta;
00324 
00325         DestroyDecorators();
00326         // Store parts and create & initialize decorators
00327         // FIXME: don't do this if PartBrowser is not displayed, it is expensive
00328         // FIXME: lazily instantiate when aspect is changed
00329         if (meta) {
00330                 CComPtr<IMgaMetaAspects> mmAspects;
00331                 COMTHROW(mgaMetaModel->get_Aspects(&mmAspects));
00332                 long aspect_count = 0;
00333                 COMTHROW(mmAspects->get_Count(&aspect_count));
00334                 CComPtr<IMgaMetaAspect> mmAspect;
00335                 MGACOLL_ITERATE(IMgaMetaAspect, mmAspects) {
00336                         mmAspect = MGACOLL_ITER;
00337 
00338                         CComPtr<IMgaMetaParts> metaParts;
00339                         COMTHROW(mmAspect->get_Parts(&metaParts));
00340                         CreateDecorators(metaParts);
00341                 }
00342                 MGACOLL_ITERATE_END;
00343         } else
00344                 Invalidate(TRUE);
00345 }
00346 
00347 void CPartBrowserPane::SetBgColor(COLORREF bgColor)
00348 {
00349         backgroundColor = bgColor;
00350 }
00351 
00352 void CPartBrowserPane::ChangeAspect(int index)
00353 {
00354         currentAspectIndex = index;
00355         if (currentAspectIndex < 0 || pdts.size() <= 0)
00356                 return;
00357 
00358         // create a DC for text metric
00359         CDC textMetric;
00360         textMetric.CreateCompatibleDC(NULL);
00361         CFont* oldCFont = textMetric.SelectObject(&txtMetricFont);
00362         HFONT oldFont = (HFONT)oldCFont->GetSafeHandle();
00363 
00364         // just to be safe
00365         maxSize.cx = 30;
00366         maxSize.cy = 10;
00367 
00368         try {
00369                 const std::vector<PartWithDecorator>& pdtv = pdts[currentAspectIndex];
00370                 // calculate the maximum size
00371                 for (std::vector<PartWithDecorator>::const_iterator ii = pdtv.begin(); ii != pdtv.end(); ++ii) {
00372                         ASSERT((*ii).part != NULL);
00373                         ASSERT((*ii).decorator != NULL);
00374 
00375                         long sizeX = 0;
00376                         long sizeY = 0;
00377                         COMTHROW((*ii).decorator->GetPreferredSize(&sizeX, &sizeY));
00378                         CSize size(sizeX, sizeY);
00379 
00380                         if (maxSize.cx < size.cx)
00381                                 maxSize.cx = size.cx;
00382 
00383                         if (maxSize.cy < size.cy)
00384                                 maxSize.cy = size.cy;
00385 
00386                         int text_cx = textMetric.GetTextExtent((*ii).name).cx;
00387                         if (maxSize.cx < text_cx)
00388                                 maxSize.cx = text_cx;
00389                 }
00390         }
00391         catch (hresult_exception&) {
00392         }
00393 
00394         CPartBrowserPaneFrame* parent = (CPartBrowserPaneFrame*)GetParent();
00395         ASSERT(parent != NULL);
00396 
00397         Invalidate();
00398 
00399         CFont* oldCFont2 = CFont::FromHandle(oldFont);
00400         textMetric.SelectObject(oldCFont2);
00401 }
00402 
00403 
00404 BEGIN_MESSAGE_MAP(CPartBrowserPane, CWnd)
00405         //{{AFX_MSG_MAP(CPartBrowserPane)
00406         ON_WM_PAINT()
00407         ON_WM_ERASEBKGND()
00408         ON_WM_LBUTTONDOWN()
00409         //}}AFX_MSG_MAP
00410 END_MESSAGE_MAP()
00411 
00412 
00414 // CPartBrowserPane message handlers
00415 
00416 void CPartBrowserPane::OnPaint()
00417 {
00418         if (omitPaintMessages) {
00419                 CWnd::OnPaint();
00420                 return;
00421         }
00422 
00423         CPartBrowserPaneFrame* parent = (CPartBrowserPaneFrame*)GetParent();
00424         ASSERT(parent != NULL);
00425 
00426         CPaintDC dc(this); // device context for painting
00427         dc.SetWindowOrg(0, parent->GetScrollPosition ());
00428 
00429         if (pdts.size() > 0 && currentAspectIndex >= 0) {
00430                 try {
00431                         const std::vector<PartWithDecorator>& pdtv = pdts[currentAspectIndex];
00432                         for (std::vector<PartWithDecorator>::const_iterator ii = pdtv.begin(); ii != pdtv.end(); ++ii) {
00433                                 if ((*ii).newDecorator) {
00434                                         // GME-339
00435                                         Gdiplus::Graphics gdipGraphics(dc.m_hDC);
00436                                         gdipGraphics.SetPageUnit(Gdiplus::UnitPixel);
00437                                         gdipGraphics.SetSmoothingMode(m_eEdgeAntiAlias);
00438                                         gdipGraphics.SetTextRenderingHint(m_eFontAntiAlias);
00439                                         COMTHROW((*ii).newDecorator->DrawEx((ULONG)dc.m_hDC, (ULONGLONG)(&gdipGraphics)));
00440                                 } else {
00441                                         COMTHROW((*ii).decorator->Draw((ULONG)dc.m_hDC));
00442                                 }
00443                         }
00444                 }
00445                 catch (hresult_exception&) {
00446                 }
00447         }
00448 
00449         // Do not call CWnd::OnPaint() for painting messages
00450 }
00451 
00452 BOOL CPartBrowserPane::OnEraseBkgnd(CDC* pDC)
00453 {
00454         RECT r;
00455         GetClientRect(&r);
00456         pDC->FillSolidRect(&r, backgroundColor);
00457         return TRUE;
00458         
00459 //      return CWnd::OnEraseBkgnd(pDC);
00460 }
00461 
00462 void CPartBrowserPane::OnLButtonDown(UINT nFlags, CPoint point) 
00463 {
00464 //      CGMEEventLogger::LogGMEEvent("CPartBrowserPane::OnLButtonDown\r\n");
00465         
00466         // Needed to flush the Object Inspector and the Browser (JIRA #GME-52)
00467         SetFocus();
00468 
00469         CPartBrowserPaneFrame* parent = (CPartBrowserPaneFrame*)GetParent();
00470         ASSERT(parent != NULL);
00471 
00472         point.y += parent->GetScrollPosition ();
00473 
00474         PartWithDecorator pdt;
00475         bool found = FindObject(point, pdt);
00476 
00477         if (found) {
00478 //              CGMEEventLogger::LogGMEEvent("    LButton over " + guiObj->GetName() + "\r\n");
00479 
00480                 CRect rectAwake = CRect(point.x, point.y, point.x + 1, point.y + 1);
00481                 rectAwake.InflateRect(3, 3);
00482 
00483                 long x1 = 0; long y1 = 0;
00484                 long x2 = 0; long y2 = 0;
00485                 COMTHROW(pdt.decorator->GetLocation(&x1, &y1, &x2, &y2));
00486                 CRect partRect (x1, y1, x2, y2);
00487                 CPoint ptClickOffset(point.x - partRect.left, point.y - partRect.top);
00488 
00489                 CRectList rects;
00490                 rects.AddTail(&partRect);
00491 
00492                 CRectList dummyAnnList;
00493                 CGMEDataDescriptor desc(rects, dummyAnnList, point, ptClickOffset);
00494 //              CGMEDataDescriptor::destructList(rects);
00495 
00496                 CGMEDataSource dataSource(mgaProject);
00497                 CComPtr<IMgaMetaRole> mmRole;
00498                 COMTHROW(pdt.part->get_Role(&mmRole));
00499                 dataSource.SetMetaRole(mmRole);
00500                 dataSource.CacheDescriptor(&desc);
00501                 DROPEFFECT de = dataSource.DoDragDrop(DROPEFFECT_COPY, &rectAwake);
00502         }
00503 
00504         CWnd::OnLButtonDown(nFlags, point);
00505 }