GME
13
|
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 }