GME  13
GUIObject.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 
00003 #include <stdio.h>
00004 #define _USE_MATH_DEFINES
00005 #include <math.h>
00006 #include "GMEApp.h"
00007 #include "GMEstd.h"
00008 #include "GMEOLEData.h"
00009 #include "PendingObjectPosRequest.h"
00010 #include "GMEView.h"
00011 #include "GraphicsUtil.h"
00012 #include "GuiMeta.h"
00013 #include "GuiObject.h"
00014 #include "ModelGrid.h"
00015 #include "DecoratorEventSink.h"
00016 #include "AnnotatorEventSink.h"
00017 
00018 #include "AutoRoute/AutoRouterGraph.h"
00019 #include "AutoRoute/AutoRouter.h"
00020 #include "AutoRoute/AutoRouterPath.h"
00021 
00022 #include "GMEEventLogger.h"
00023 #include "MainFrm.h"
00024 
00025 
00026 CModelGrid modelGrid;
00027 
00029 
00030 static void SetSize(CRect& location, CSize s)
00031 {
00032         location.left = max(GME_GRID_SIZE, location.left / GME_GRID_SIZE * GME_GRID_SIZE);
00033         location.top = max(GME_GRID_SIZE, location.top / GME_GRID_SIZE * GME_GRID_SIZE);
00034         location.right = location.left + s.cx;
00035         location.bottom = location.top + s.cy;
00036 }
00037 
00038 void SetLocation(CRect& location, CPoint pt)
00039 {
00040         CSize s = location.Size();
00041         location.top = pt.y;
00042         location.left = pt.x;
00043         SetSize(location, s);
00044 }
00045 
00047 
00049 // Non-virtual methods of CGuiAspect
00051 CGuiAspect::CGuiAspect(CGuiMetaAspect* meta, CGuiObject* p, int ind, int pind, CComPtr<IMgaDecorator>& decor,
00052                                            CComPtr<IMgaElementDecorator>& newDecor, CComObjPtr<CDecoratorEventSink>& decorEventSink):
00053         guiMeta(meta),
00054         parent(p),
00055         index(ind),
00056         parentIndex(pind),
00057         decorator(decor),
00058         newDecorator(newDecor),
00059         decoratorEventSink(decorEventSink),
00060         routerBox(0),
00061         routerNameBox(0)
00062 {
00063         try {
00064                 COMTHROW(decor->GetFeatures(&features));
00065         }
00066         catch (hresult_exception &) {
00067                 features = 0UL;
00068         }
00069         name = meta->name;
00070         if (parent->IsReal()) {
00071                 InitPorts();
00072         }
00073 
00074         if (features & F_ANIMATION) {
00075                 parent->IncrementAnimRefCnt();
00076         }
00077 }
00078 
00079 CGuiAspect::~CGuiAspect()
00080 {
00081         if (newDecorator) {
00082                 COMTHROW(newDecorator->Destroy());
00083                 newDecorator.Release();
00084                 newDecorator = NULL;
00085         } else {
00086                 COMTHROW(decorator->Destroy());
00087         }
00088         decorator.Release();
00089         decorator = NULL;
00090         if (decoratorEventSink != NULL) {
00091                 decoratorEventSink.Release();
00092                 decoratorEventSink = NULL;
00093         }
00094         POSITION pos = ports.GetHeadPosition();
00095         while(pos) {
00096                 delete ports.GetNext(pos);
00097         }
00098         if (features & F_ANIMATION) {
00099                 parent->DecrementAnimRefCnt();
00100         }
00101 }
00102 
00103 void CGuiAspect::InitPorts()
00104 {
00105         CComPtr<IMgaFCOs> portFcos;
00106         COMTHROW(decorator->GetPorts(&portFcos));
00107         if (portFcos) {
00108                 CComPtr<IMgaFCO> fco;
00109                 MGACOLL_ITERATE(IMgaFCO,portFcos) {
00110                         fco = MGACOLL_ITER;
00111                         CGuiPort *p = new CGuiPort(this,fco);
00112                         ports.AddTail(p);
00113                 }
00114                 MGACOLL_ITERATE_END;
00115         }
00116         CGuiPort *p = new CGuiPort(this,parent->mgaFco);
00117         ports.AddTail(p);
00118 
00119 }
00120 
00121 void CGuiAspect::SetLocation(const CRect& location)
00122 {
00123         loc = location; 
00124         
00125         try {
00126                 COMTHROW(decorator->SetLocation(location.left, location.top, location.right, location.bottom));
00127                 long sx, sy, ex, ey;
00128                 COMTHROW(decorator->GetLabelLocation(&sx, &sy, &ex, &ey));
00129                 
00130                 /*
00131                 sx = min(sx, location.right-1);
00132                 ex = max(ex, location.left+1);
00133                 sy = min(sy, location.bottom-1);
00134                 ey = max(ey, location.top+1);
00135                 */
00136                 if (sx != 0 && ex != 0 && sy != 0 && ey != 0) {
00137                         sx = min(sx, location.right+1);
00138                         ex = max(ex, location.left-1);
00139                         sy = min(sy, location.bottom+1);
00140                         ey = max(ey, location.top-1);
00141                 }
00142                 nameLoc.SetRect(sx, sy, ex, ey);
00143         } catch (hresult_exception &) {
00144                         ASSERT(false);
00145         }
00146 }
00148 // Static methods of CGuiAspect
00150 
00152 // Virtual methods of CGuiAspect
00154 
00155 
00157 
00159 // Non-virtual methods of CGuiPort
00161 CGuiPort::CGuiPort(CGuiAspect* asp, CComPtr<IMgaFCO> fco) : parent(asp), mgaFco(fco)
00162 {
00163         CComBSTR bstr;
00164         COMTHROW(fco->get_Name(&bstr));
00165         CopyTo(bstr,name);
00166 
00167         bstr.Empty();
00168         COMTHROW(fco->get_ID(&bstr));
00169         CopyTo(bstr,id);
00170 
00171         COMTHROW(fco->get_Meta(&metaFco));
00172 
00173         COMTHROW(fco->get_MetaRole(&metaRole));
00174 
00175         if (!IsRealPort()) {
00176                 ReadARPreferences();
00177         }
00178 
00179 }
00180 
00181 bool CGuiPort::GetPreference(CString &val, CString path)
00182 {
00183         VERIFY(mgaFco);
00184         CComBSTR pathBstr;
00185         CopyTo(path, pathBstr);
00186         CComBSTR bstrVal;
00187         COMTHROW(mgaFco->get_RegistryValue(pathBstr,&bstrVal));
00188         CopyTo(bstrVal, val);
00189         return !val.IsEmpty();
00190 }
00191 
00192 
00193 
00194 void CGuiPort::ReadARPreferences()
00195 {
00196         CString val;
00197         if (GetPreference(val, AUTOROUTER_PREF)) {
00198                 autorouterPrefs[GME_START_NORTH] = (val.Find(_T("N")) != -1);
00199                 autorouterPrefs[GME_START_EAST] = (val.Find(_T("E")) != -1);
00200                 autorouterPrefs[GME_START_SOUTH] = (val.Find(_T("S")) != -1);
00201                 autorouterPrefs[GME_START_WEST] = (val.Find(_T("W")) != -1);
00202                 autorouterPrefs[GME_END_NORTH] = (val.Find(_T("n")) != -1);
00203                 autorouterPrefs[GME_END_EAST] = (val.Find(_T("e")) != -1);
00204                 autorouterPrefs[GME_END_SOUTH] = (val.Find(_T("s")) != -1);
00205                 autorouterPrefs[GME_END_WEST] = (val.Find(_T("w")) != -1);
00206         }
00207         else {
00208                 if (parent->GetParent()->dynamic_cast_CGuiCompound() != NULL) {
00209                         autorouterPrefs[GME_START_NORTH] = true;
00210                         autorouterPrefs[GME_START_EAST] = false;
00211                         autorouterPrefs[GME_START_SOUTH] = true;
00212                         autorouterPrefs[GME_START_WEST] = false;
00213                         autorouterPrefs[GME_END_NORTH] = true;
00214                         autorouterPrefs[GME_END_EAST] = false;
00215                         autorouterPrefs[GME_END_SOUTH] = true;
00216                         autorouterPrefs[GME_END_WEST] = false;
00217                 } else {
00218                         autorouterPrefs[GME_START_NORTH] = true;
00219                         autorouterPrefs[GME_START_EAST] = true;
00220                         autorouterPrefs[GME_START_SOUTH] = true;
00221                         autorouterPrefs[GME_START_WEST] = true;
00222                         autorouterPrefs[GME_END_NORTH] = true;
00223                         autorouterPrefs[GME_END_EAST] = true;
00224                         autorouterPrefs[GME_END_SOUTH] = true;
00225                         autorouterPrefs[GME_END_WEST] = true;
00226                 }
00227         }
00228 }
00229 
00230 bool CGuiPort::GetARPref(int dir)
00231 {
00232         if (IsRealPort()) {
00233                 CRect parentLoc = parent->GetLocation();
00234                 if (GetLocation().CenterPoint().x < (parentLoc.Size().cx / 2)) {
00235                         autorouterPrefs[GME_START_NORTH] = false;
00236                         autorouterPrefs[GME_START_EAST] = false;
00237                         autorouterPrefs[GME_START_SOUTH] = false;
00238                         autorouterPrefs[GME_START_WEST] = true;
00239                         autorouterPrefs[GME_END_NORTH] = false;
00240                         autorouterPrefs[GME_END_EAST] = false;
00241                         autorouterPrefs[GME_END_SOUTH] = false;
00242                         autorouterPrefs[GME_END_WEST] = true;
00243                 } else {
00244                         autorouterPrefs[GME_START_NORTH] = false;
00245                         autorouterPrefs[GME_START_EAST] = true;
00246                         autorouterPrefs[GME_START_SOUTH] = false;
00247                         autorouterPrefs[GME_START_WEST] = false;
00248                         autorouterPrefs[GME_END_NORTH] = false;
00249                         autorouterPrefs[GME_END_EAST] = true;
00250                         autorouterPrefs[GME_END_SOUTH] = false;
00251                         autorouterPrefs[GME_END_WEST] = false;
00252 
00253                 }
00254         }
00255         return autorouterPrefs[dir];
00256 }
00257 
00258 
00259 bool CGuiPort::IsVisible()                      // called on a tmp obj that only exists to get this info
00260 {
00261         bool visible = true;
00262         VERIFY(parent);
00263         VERIFY(parent->parent);
00264         CComPtr<IMgaFCO> fco = parent->parent->mgaFco;
00265         CComBSTR bstr = L"GME/ports";
00266         CComPtr<IMgaRegNode> root;
00267         COMTHROW(fco->get_RegistryNode(bstr,&root));
00268         CComPtr<IMgaRegNodes> nodes;
00269 
00270         VARIANT_BOOL vb = VARIANT_TRUE;
00271         COMTHROW(root->get_SubNodes(vb,&nodes));
00272         MGACOLL_ITERATE(IMgaRegNode,nodes) {
00273                 CComPtr<IMgaRegNode> reg;
00274                 reg = MGACOLL_ITER;
00275                 CComPtr<IMgaFCO> portFco;
00276                 COMTHROW(reg->get_FCOValue(&portFco));
00277                 if(IsEqualObject(portFco,mgaFco)) {
00278                         CComPtr<IMgaRegNode> subreg;
00279                         CComBSTR path = L"visible";
00280                         COMTHROW(reg->get_SubNodeByName(path,&subreg));
00281                         if(subreg != 0) {
00282                                 CComBSTR val;
00283                                 COMTHROW(subreg->get_Value(&val));
00284                                 CString value;
00285                                 CopyTo(val,value);
00286                                 int v;
00287                                 if(_stscanf((LPCTSTR)value,_T("%d"),&v) > 0)
00288                                         visible = v ? true : false;
00289                         }
00290                         break;
00291                 }
00292         }
00293         MGACOLL_ITERATE_END;
00294         return visible;
00295 }
00296 
00297 void CGuiPort::SetVisible(bool v)       // called on a tmp obj that only exists to set this info
00298 {
00299         VERIFY(parent);
00300         VERIFY(parent->parent);
00301         CComPtr<IMgaFCO> fco = parent->parent->mgaFco;
00302         CComBSTR id;
00303         CComBSTR bstr = L"GME/ports/";
00304         COMTHROW(mgaFco->get_ID(&id));
00305         bstr += id;
00306         CComPtr<IMgaRegNode> reg;
00307         COMTHROW(fco->get_RegistryNode(bstr,&reg));
00308         COMTHROW(reg->put_FCOValue(mgaFco));
00309         CComBSTR path = L"visible";
00310         CComPtr<IMgaRegNode> subreg;
00311         COMTHROW(reg->get_SubNodeByName(path,&subreg));
00312         CComBSTR bstrval = v ? L"1" : L"0";
00313         COMTHROW(subreg->put_Value(bstrval));
00314 }
00315 
00316 CRect CGuiPort::GetLocation()
00317 {
00318         long sx = 0;
00319         long sy = 0;
00320         long ex = 0;
00321         long ey = 0;
00322         if (!IsRealPort()) {
00323                 CSize size = parent->GetLocation().Size();
00324                 sx = sy = 0;
00325                 ex = size.cx;
00326                 ey = size.cy;
00327         }
00328         else {
00329                 try {
00330                         parent->GetDecorator()->GetPortLocation(mgaFco, &sx, &sy, &ex, &ey);
00331                 }
00332                 catch(hresult_exception& e) {
00333                         if (e.hr != E_DECORATOR_PORTNOTFOUND) {
00334                                 throw e;
00335                         }
00336                 }
00337         }
00338         return CRect(sx, sy, ex, ey);
00339 }
00340 
00341 bool CGuiPort::IsRealPort() {
00342         return !mgaFco.IsEqualObject(parent->GetParent()->mgaFco);
00343 }
00344 
00346 // Static methods of CGuiPort
00348 
00350 // Virtual methods of CGuiPort
00352 
00354 
00355 AnnotatorDecoratorData::AnnotatorDecoratorData()
00356 {
00357         decorator = NULL;
00358         annotatorEventSink = NULL;
00359 }
00360 
00361 AnnotatorDecoratorData::AnnotatorDecoratorData(CComPtr<IMgaElementDecorator>& nD, CComObjPtr<CAnnotatorEventSink>& aES,
00362                                                                                            const CRect& loc):
00363         decorator(nD),
00364         annotatorEventSink(aES),
00365         location(loc)
00366 {
00367 }
00368 
00369 AnnotatorDecoratorData::~AnnotatorDecoratorData()
00370 {
00371 }
00372 
00373 
00375 
00377 // Non-virtual methods of CGuiAnnotator
00379 CGuiAnnotator::CGuiAnnotator(CComPtr<IMgaModel>& pModel, CComPtr<IMgaRegNode>& mRootNode, CGMEView* vw, int numAsp)
00380 {
00381         model = pModel;
00382         rootNode = mRootNode;
00383         numParentAspects = numAsp;
00384         parentAspect = 0;
00385         grayedOut = false;
00386         view = vw;
00387         special = false;
00388 
00389         for (int i = 0; i < numAsp; i++) {
00390                 decoratorData.push_back(new AnnotatorDecoratorData());
00391         }
00392 
00393         try {
00394                 CComBSTR bName;
00395                 COMTHROW(rootNode->get_Name(&bName));
00396                 name = bName;
00397 
00398                 long st; // if main node status is inherited it means it is a special node
00399                 COMTHROW(rootNode->get_Status( &st));
00400                 if( st > ATTSTATUS_HERE)
00401                         special = true;
00402 
00403                 id = view->name + _T(":") + name;               // Fake id
00404 
00405                 CComPtr<IMgaRegNode> aspRootNode;
00406                 CComBSTR aspRootName(AN_ASPECTS);
00407                 COMTHROW(rootNode->get_SubNodeByName(aspRootName, &aspRootNode));
00408 
00409                 if (aspRootNode) {
00410                         CComPtr<IMgaRegNodes>   aspNodes;
00411                         COMTHROW(aspRootNode->get_SubNodes(VARIANT_TRUE, &aspNodes));
00412                         MGACOLL_ITERATE(IMgaRegNode, aspNodes) {
00413                                 CComPtr<IMgaRegNode>    aspNode;
00414                                 aspNode = MGACOLL_ITER;
00415                                 CComBSTR aspName;
00416                                 COMTHROW(aspNode->get_Name(&aspName));
00417                                 CString aspNameStr(aspName);
00418                                 if (aspNameStr != AN_DEFASPECT) {
00419                                         CGuiMetaAspect *guiMetaAsp = view->guiMeta->FindAspect(aspNameStr);
00420                                         if (guiMetaAsp) {
00421                                                 ReadLocation(guiMetaAsp->index, aspNode);
00422                                                 InitDecorator(guiMetaAsp->index);
00423                                         }
00424                                 }
00425                         }
00426                         MGACOLL_ITERATE_END;
00427 
00428                         CComPtr<IMgaRegNode> defAspNode;
00429                         CComBSTR defAspName(AN_DEFASPECT);
00430                         COMTHROW(aspRootNode->get_SubNodeByName(defAspName, &defAspNode));
00431                         long status;
00432                         COMTHROW(defAspNode->get_Status(&status));
00433                         if (status != ATTSTATUS_UNDEFINED) {
00434                                 for (int i = 0; i < numParentAspects; i++) {
00435                                         if (decoratorData[i]->decorator == NULL) {
00436                                                 ReadLocation(i, defAspNode);
00437                                                 InitDecorator(i);
00438                                         }
00439                                 }
00440                         }
00441                 }
00442         }
00443         catch(hresult_exception &e) {
00444                 for (std::vector<AnnotatorDecoratorData*>::iterator ii = decoratorData.begin(); ii != decoratorData.end(); ++ii) {
00445                         if ((*ii)->decorator != NULL) {
00446                                 COMTHROW((*ii)->decorator->Destroy());
00447                                 (*ii)->decorator.Release();
00448                                 (*ii)->decorator = NULL;
00449                         }
00450                         if ((*ii)->annotatorEventSink != NULL) {
00451                                 (*ii)->annotatorEventSink.Release();
00452                                 (*ii)->annotatorEventSink = NULL;
00453                         }
00454                         delete (*ii);
00455                 }
00456                 decoratorData.clear();
00457 
00458                 numParentAspects = 0;
00459                 parentAspect = 0;
00460                 throw hresult_exception(e.hr);
00461                 return;
00462         }
00463 }
00464 
00465 CGuiAnnotator::~CGuiAnnotator()
00466 {
00467         for (std::vector<AnnotatorDecoratorData*>::iterator ii = decoratorData.begin(); ii != decoratorData.end(); ++ii) {
00468                 if ((*ii)->decorator != NULL) {
00469                         COMTHROW((*ii)->decorator->Destroy());
00470                         (*ii)->decorator.Release();
00471                         (*ii)->decorator = NULL;
00472                 }
00473                 if ((*ii)->annotatorEventSink != NULL) {
00474                         (*ii)->annotatorEventSink.Release();
00475                         (*ii)->annotatorEventSink = NULL;
00476                 }
00477                 delete (*ii);
00478         }
00479         decoratorData.clear();
00480 }
00481 
00482 void CGuiAnnotator::InitDecorator(int asp)
00483 {
00484         try {
00485                 CString progId = AN_DECORATOR_PROGID;
00486                 COMTHROW(decoratorData[asp]->decorator.CoCreateInstance(PutInBstr(progId)));
00487 
00488                 CComPtr<IMgaElementDecoratorEvents> annotatorEventSinkIface;
00489                 ::CreateComObject(decoratorData[asp]->annotatorEventSink);
00490                 HRESULT hr = ::QueryInterface((IMgaElementDecoratorEvents*)(decoratorData[asp]->annotatorEventSink.p),
00491                                                                           &annotatorEventSinkIface);
00492                 if (SUCCEEDED(hr)) {
00493                         decoratorData[asp]->annotatorEventSink->SetView(view);
00494                         decoratorData[asp]->annotatorEventSink->SetGuiAnnotator(this);
00495                 }
00496                 CComBSTR param(AN_PARAM_ROOTNODE);
00497                 CComVariant value(rootNode);
00498                 COMTHROW(decoratorData[asp]->decorator->SetParam(param, value));
00499 
00500                 COMTHROW(decoratorData[asp]->decorator->InitializeEx(theApp.mgaProject, NULL, NULL, annotatorEventSinkIface, (ULONGLONG)view->m_hWnd));
00501 
00502                 long sx, sy;
00503                 COMTHROW(decoratorData[asp]->decorator->GetPreferredSize(&sx, &sy));
00504                 decoratorData[asp]->location.right = decoratorData[asp]->location.left + sx;
00505                 decoratorData[asp]->location.bottom = decoratorData[asp]->location.top + sy;
00506 
00507                 COMTHROW(decoratorData[asp]->decorator->SetLocation(decoratorData[asp]->location.left, decoratorData[asp]->location.top,
00508                                                                                                                         decoratorData[asp]->location.right, decoratorData[asp]->location.bottom));
00509         }
00510         catch (hresult_exception &) {
00511                 AfxMessageBox(_T("Cannot initialize annotator for annotation: ") + name, MB_OK | MB_ICONSTOP);
00512                 decoratorData[asp]->decorator = NULL;
00513         }
00514 }
00515 
00516 bool CGuiAnnotator::IsVisible(int aspect)
00517 {
00518         if (aspect < 0) {
00519                 aspect = parentAspect;
00520         }
00521         return (decoratorData[aspect]->decorator != NULL);
00522 }
00523 
00524 bool CGuiAnnotator::IsResizable(void) const
00525 {
00526         if (decoratorData[parentAspect]->decorator) {
00527                 try {
00528                         feature_code fc = 0;
00529                         COMTHROW(decoratorData[parentAspect]->decorator->GetFeatures(&fc));
00530                         return ((fc & F_RESIZABLE) != 0);
00531                 }
00532                 catch (hresult_exception &) {
00533                         AfxMessageBox(_T("Error in annotator [method IsResizable()]"));
00534                 }
00535         }
00536 
00537         return false;
00538 }
00539 
00540 void CGuiAnnotator::Draw(HDC pDC, Gdiplus::Graphics* gdip)
00541 {
00542         ASSERT(sizeof(ULONG) == sizeof(HDC));
00543         if (decoratorData[parentAspect]->decorator) {
00544                 try {
00545                         COMTHROW(decoratorData[parentAspect]->decorator->DrawEx((ULONG)pDC, (ULONGLONG)gdip));
00546                 }
00547                 catch (hresult_exception &) {
00548                         AfxMessageBox(_T("Error in annotator [method Draw()]"));
00549                 }
00550         }
00551 }
00552 
00553 void CGuiAnnotator::GrayOut(bool set)
00554 {
00555         if (decoratorData[parentAspect]->decorator) {
00556                 grayedOut = set;
00557                 try {
00558                         COMTHROW(decoratorData[parentAspect]->decorator->SetActive(set ? VARIANT_FALSE : VARIANT_TRUE));
00559                 }
00560                 catch (hresult_exception &) {
00561                 }
00562         }
00563 }
00564 
00565 const CRect& CGuiAnnotator::GetLocation(int aspect)
00566 {
00567         if (aspect < 0) {
00568                 aspect = parentAspect;
00569         }
00570         return decoratorData[aspect]->location;
00571 }
00572 
00573 void  CGuiAnnotator::SetLocation(const CRect& toLoc, int aspect, bool doMga)
00574 {
00575         if (aspect < 0) {
00576                 aspect = parentAspect;
00577         }
00578 
00579         CRect loc(toLoc);
00580         if (loc.left < 0) {
00581                 loc.right += -loc.left;
00582                 loc.left = 0;
00583         }
00584         if (loc.top < 0) {
00585                 loc.bottom += -loc.top;
00586                 loc.top = 0;
00587         }
00588 
00589         decoratorData[aspect]->location = loc;
00590         try {
00591                 COMTHROW(decoratorData[aspect]->decorator->SetLocation(loc.left, loc.top, loc.right, loc.bottom));
00592         }
00593         catch (hresult_exception &) {
00594                 AfxMessageBox(_T("Cannot set location of annotation ") + name);
00595         }
00596 
00597         if (doMga) {
00598                 WriteLocation(aspect);
00599         }
00600 }
00601 
00602 void  CGuiAnnotator::ReadLocation(int aspect, CComPtr<IMgaRegNode>& aspNode)
00603 {
00604         decoratorData[aspect]->location.left = 0;
00605         decoratorData[aspect]->location.top = 0;
00606 
00607         try {
00608                 CComBSTR bstr;
00609                 COMTHROW(aspNode->get_Value(&bstr));
00610                 CString str(bstr);
00611                 long lx, ly;
00612                 if(_stscanf(str,_T("%d,%d"), &lx, &ly) == 2) {
00613                         decoratorData[aspect]->location.left = lx;
00614                         decoratorData[aspect]->location.top = ly;
00615                         return;
00616                 }
00617         }
00618         catch (hresult_exception &) {
00619         }
00620         try {
00621                 CComPtr<IMgaRegNode> rootNode;
00622                 COMTHROW(aspNode->get_ParentNode(&rootNode));
00623                 CComBSTR bstrRoot;
00624                 COMTHROW(rootNode->get_Value(&bstrRoot));
00625                 CString strRoot(bstrRoot);
00626                 long lxr, lyr;
00627                 if(_stscanf(strRoot,_T("%d,%d"), &lxr, &lyr) == 2) {
00628                         decoratorData[aspect]->location.left = lxr;
00629                         decoratorData[aspect]->location.top = lyr;
00630                         return;
00631                 }
00632         }
00633         catch (hresult_exception &) {
00634         }
00635 }
00636 
00637 void  CGuiAnnotator::WriteLocation(int aspect)
00638 {
00639         if (aspect < 0) {
00640                 aspect = parentAspect;
00641         }
00642 
00643         OLECHAR bbc[40];
00644         _snwprintf(bbc, 40, OLESTR("%ld,%ld"), decoratorData[aspect]->location.left, decoratorData[aspect]->location.top);
00645         CComBSTR bb(bbc);
00646 
00647 
00648         CComPtr<IMgaRegNode> aspRoot;
00649         CComBSTR aspRootName(AN_ASPECTS);
00650         COMTHROW(rootNode->get_SubNodeByName(aspRootName, &aspRoot));
00651 
00652         CComPtr<IMgaRegNode> aspNode;
00653         CComBSTR aspName(view->guiMeta->FindAspect(aspect)->name);
00654         COMTHROW(aspRoot->get_SubNodeByName(aspName, &aspNode));
00655 
00656         COMTHROW(aspNode->put_Value(bb));
00657 }
00658 
00660 // Static methods of CGuiAnnotator
00662 void CGuiAnnotator::SetAspect(CGuiAnnotatorList& list, int asp)
00663 {
00664         POSITION pos = list.GetHeadPosition();
00665         while (pos) {
00666                 list.GetNext(pos)->SetAspect(asp);
00667         }
00668 }
00669 
00670 void CGuiAnnotator::GrayOutAnnotations(CGuiAnnotatorList& list, bool set)
00671 {
00672         POSITION pos = list.GetHeadPosition();
00673         while (pos) {
00674                 list.GetNext(pos)->GrayOut(set);
00675         }
00676 }
00677 
00678 
00679 void CGuiAnnotator::NudgeAnnotations(CGuiAnnotatorList& annotatorList, int right, int down)
00680 {
00681         CGMEEventLogger::LogGMEEvent(_T("CGuiAnnotator::NudgeAnnotations "));
00682         GMEEVENTLOG_GUIANNOTATORS(annotatorList);
00683         ASSERT(right == 0 || down == 0); // cannot nudge diagonally for now
00684         POSITION pos = annotatorList.GetHeadPosition();
00685         while(pos) {
00686                 CGuiAnnotator* ann = annotatorList.GetNext(pos);
00687                 VERIFY(ann->IsVisible());
00688                 CRect rect = ann->GetLocation();
00689                 rect.top += down * GME_GRID_SIZE;
00690                 rect.bottom += down * GME_GRID_SIZE;
00691                 rect.left += right * GME_GRID_SIZE;
00692                 rect.right += right * GME_GRID_SIZE;
00693                 ann->SetLocation(rect);
00694         }
00695 }
00696 
00697 void CGuiAnnotator::GetExtent(CGuiAnnotatorList& annotatorList, CRect& rect)
00698 {
00699         CGuiAnnotator* ann;
00700         CRect cur1, cur2;
00701         POSITION pos = annotatorList.GetHeadPosition();
00702         rect = CRect(0,0,0,0);
00703         while(pos) {
00704                 ann = annotatorList.GetNext(pos);
00705                 if(ann && ann->IsVisible()) {
00706                         cur2 = ann->GetLocation();
00707                         cur1 = rect;
00708                         rect.UnionRect(&cur1, &cur2);
00709                 }
00710         }
00711 }
00712 
00713 void CGuiAnnotator::GetRectList(CGuiAnnotatorList &annotatorList, CRectList &annRects)
00714 {
00715         POSITION pos = annotatorList.GetHeadPosition();
00716         while(pos) {
00717                 CRect* rect = new CRect(annotatorList.GetNext(pos)->GetLocation());
00718                 annRects.AddTail(rect);
00719         }
00720 }
00721 
00722 
00723 void CGuiAnnotator::FindUpperLeft(CGuiAnnotatorList& anns, int& left, int& top)
00724 {
00725         bool start = true;
00726         POSITION pos = anns.GetHeadPosition();
00727         CGuiAnnotator* ann;
00728         CRect r;
00729         while(pos) {
00730                 ann = anns.GetNext(pos);
00731                 if(ann->IsVisible()) {
00732                         r = ann->GetLocation();
00733                         if(start) {
00734                                 left = r.left;
00735                                 top = r.top;
00736                                 start = false;
00737                         }
00738                         else {
00739                                 if(r.left < left)
00740                                         left = r.left;
00741                                 if(r.top < top)
00742                                         top = r.top;
00743                         }
00744                 }
00745         }
00746 }
00747 
00748 void CGuiAnnotator::ShiftAnnotations(CGuiAnnotatorList& annList, CPoint& shiftBy)
00749 {
00750         CGMEEventLogger::LogGMEEvent(_T("CGuiAnnotator::ShiftAnnotations "));
00751         GMEEVENTLOG_GUIANNOTATORS(annList);
00752         POSITION pos = annList.GetHeadPosition();
00753         while(pos) {
00754                 CGuiAnnotator* ann = annList.GetNext(pos);
00755                 VERIFY(ann->IsVisible());
00756                 CRect newLoc = ann->GetLocation();
00757                 newLoc.OffsetRect(shiftBy);
00758                 ann->SetLocation(newLoc);
00759         }
00760 }
00761 
00762 // static
00763 int CGuiAnnotator::Hide(CComPtr<IMgaRegNode>& mRootNode )
00764 {
00765         CComBSTR val;
00766         COMTHROW(mRootNode->get_Value( &val));
00767         COMTHROW(mRootNode->put_Value( val));
00768         // thus we made the value of the annotator defined 'HERE'
00769         // which will decide whether an annotation regnode is virtual (inherited) or not
00770 
00771         CComBSTR bstr(L"1");
00772 
00773         // hidden node set to true
00774         CComPtr<IMgaRegNode> hideNode;
00775         CComBSTR hideNm(AN_HIDDEN);
00776         COMTHROW(mRootNode->get_SubNodeByName( hideNm, &hideNode));
00777         COMTHROW( hideNode->put_Value( bstr));
00778 
00779         return S_OK;
00780 }
00781 
00782 // static
00783 bool CGuiAnnotator::Showable( CComPtr<IMgaRegNode>& mRootNode, CComPtr<IMgaFCO>& baseType )
00784 {   // decides whether an annotation should be displayed in case of a subtype/instance
00785         // Subtype/instance may have: owned annotations (not present in the ancestor) -> main status = ATTSTATUS_HERE
00786         //                            inherited annotations                           -> main status = ATTSTATUS_INHERITED1,2,...
00787         //                            inherited, but modified annotations             -> main status = ATTSTATUS_HERE
00788         try {
00789                 CComBSTR bName;
00790                 COMTHROW(mRootNode->get_Name(&bName));
00791 
00792                 bool hidden_set = false;
00793                 CComPtr<IMgaRegNode> hideNode;
00794                 CComBSTR hideNm(AN_HIDDEN);
00795                 COMTHROW(mRootNode->get_SubNodeByName( hideNm, &hideNode));
00796                 if (hideNode)
00797                 {
00798                         long hideStatus;
00799                         COMTHROW( hideNode->get_Status( &hideStatus));
00800                         if( hideStatus != ATTSTATUS_UNDEFINED)  // meta, here or inherited
00801                         {
00802                                 CComBSTR bstr;
00803                                 COMTHROW( hideNode->get_Value( &bstr));
00804                                 if( bstr == L"1")
00805                                         return false;
00806                         }
00807                 }
00808 
00809                 if (baseType->GetRegistryValue(mRootNode->Path).length())
00810                 {
00811                         CComPtr<IMgaRegNode> inheritNode;
00812                         CComBSTR inhName(AN_INHERITABLE);
00813                         COMTHROW(mRootNode->get_SubNodeByName( inhName, &inheritNode));
00814 
00815                         if (inheritNode) {
00816                                 CComBSTR bstr;
00817                                 COMTHROW(inheritNode->get_Value( &bstr));
00818                                 if (bstr == L"1") // if "inheritable" is 1 show it
00819                                         return true;
00820                         }
00821                 }
00822                 else
00823                 {
00824                         return true;
00825                 }
00826         }
00827         catch(hresult_exception &e) {
00828                 throw hresult_exception(e.hr);
00829                 return false;
00830         }
00831 
00832         return false;
00833 }
00834 
00836 // Virtual methods of CGuiAnnotator
00838 
00839 
00840 
00842 
00844 // Non-virtual methods of CGuiFco
00846 
00847 CGuiFco::CGuiFco(CComPtr<IMgaFCO>& pt, CComPtr<IMgaMetaRole>& role, CGMEView* vw, int numAsp) :
00848         CGuiBase(),
00849         mgaFco(pt),
00850         metaRole(role),
00851         view(vw),
00852         numParentAspects(numAsp),
00853         parentAspect(0),
00854         grayedOut(false),
00855         isType(false)
00856 {
00857         {
00858                 CComBSTR bstr;
00859                 COMTHROW(role->get_Name(&bstr));
00860                 CopyTo(bstr, roleName);
00861         }
00862         {
00863                 CComBSTR bstr;
00864                 COMTHROW(role->get_DisplayedName(&bstr));
00865                 CopyTo(bstr, roleDisplayedName);
00866         }
00867         {
00868                 COMTHROW(role->get_Kind(&metaFco));
00869         }
00870         {
00871                 CComBSTR bstr;
00872                 COMTHROW(metaFco->get_Name(&bstr));
00873                 CopyTo(bstr, kindName);
00874         }
00875         {
00876                 CComBSTR bstr;
00877                 COMTHROW(metaFco->get_DisplayedName(&bstr));
00878                 CopyTo(bstr, kindDisplayedName);
00879         }
00880         if (pt) {
00881                 CComBSTR bstr;
00882                 COMTHROW(mgaFco->get_ID(&bstr));
00883                 CopyTo(bstr, id);
00884         }
00885         if (pt) {
00886                 CComBSTR bstr;
00887                 COMTHROW(mgaFco->get_Name(&bstr));
00888                 CopyTo(bstr, name);
00889         }
00890 
00891         metaref_type metaRef;
00892         COMTHROW(metaFco->get_MetaRef(&metaRef));
00893         guiMeta = CGuiMetaProject::theInstance->GetGuiMetaFco(metaRef);
00894 }
00895 
00896 metaref_type CGuiFco::GetRoleMetaRef()
00897 {
00898         metaref_type tp;
00899         VERIFY(metaRole);
00900         COMTHROW(metaRole->get_MetaRef(&tp));
00901         return tp;
00902 }
00903 
00904 bool CGuiFco::IsPrimary(CGuiMetaModel* guiMetaModel, int aspectInd)
00905 {
00906         bool prim = false;
00907         CGuiMetaAspect *aspect = guiMetaModel->FindAspect(aspectInd);
00908         if(aspect)
00909                 prim = CGuiFco::IsPrimary(guiMetaModel, aspect, metaRole);
00910         return prim;
00911 }
00912 
00913 bool CGuiFco::IsPrimary(CGuiMetaModel* guiMetaModel, CGuiMetaAspect* aspect)
00914 {
00915         return CGuiFco::IsPrimary(guiMetaModel, aspect, metaRole);
00916 }
00917 
00918 bool CGuiFco::GetPreference(CString& val, CString path)
00919 {
00920         CComBSTR pathBstr;
00921         CopyTo(path, pathBstr);
00922         CComBSTR bstrVal;
00923         if (mgaFco) {
00924                 COMTHROW(mgaFco->get_RegistryValue(pathBstr, &bstrVal));
00925         }
00926         else {
00927                 COMTHROW(metaFco->get_RegistryValue(pathBstr, &bstrVal));
00928         }
00929         CopyTo(bstrVal, val);
00930         return !val.IsEmpty();
00931 }
00932 
00933 
00934 bool CGuiFco::GetPreference(int& val, CString path, bool hex)
00935 {
00936         CComBSTR pathBstr;
00937         CopyTo(path, pathBstr);
00938         CComBSTR bstrVal;
00939         if(mgaFco == 0) {
00940                 COMTHROW(metaFco->get_RegistryValue(pathBstr, &bstrVal));
00941         }
00942         else {
00943                 COMTHROW(mgaFco->get_RegistryValue(pathBstr, &bstrVal));
00944         }
00945         CString strVal;
00946         CopyTo(bstrVal,strVal);
00947         return (_stscanf(strVal,hex ? _T("%x") : _T("%d"),&val) == 1);
00948 }
00949 
00950 bool CGuiFco::GetColorPreference(unsigned long& color, CString path)
00951 {
00952         int i;
00953         if(GetPreference(i,path,true)) {
00954                 unsigned int r = (i & 0xff0000) >> 16;
00955                 unsigned int g = (i & 0xff00) >> 8;
00956                 unsigned int b = i & 0xff;
00957                 color = RGB(r,g,b);
00958                 return true;
00959         }
00960         return false;
00961 }
00962 
00963 CGuiMetaModel *CGuiFco::GetGuiMetaParent()
00964 {
00965         CComPtr<IMgaMetaModel>  metaParent;
00966         COMTHROW(metaRole->get_ParentModel(&metaParent));
00967         VERIFY(metaParent);
00968         metaref_type metaRef;
00969         COMTHROW(metaParent->get_MetaRef(&metaRef));
00970         return CGuiMetaProject::theInstance->GetGuiMetaModel(metaRef);
00971 
00972 }
00973 
00975 // Static methods of CGuiFco
00977 bool CGuiFco::IsPrimary(CGuiMetaModel* guiMetaModel, CGuiMetaAspect* guiAspect, CComPtr<IMgaMetaRole>& metaRole)
00978 {
00979         VARIANT_BOOL prim = VARIANT_FALSE;
00980         CComPtr<IMgaMetaAspect> mAspect;
00981         guiAspect->GetMetaAspect(mAspect);
00982         CComPtr<IMgaMetaPart> part;
00983         guiMetaModel->GetPartByRole(metaRole, mAspect, part);
00984         if(part != 0)
00985                 COMTHROW(part->get_IsPrimary(&prim));
00986         return prim != VARIANT_FALSE;
00987 }
00988 
00989 void CGuiFco::SetAspect(CGuiFcoList& modelList, int asp)
00990 {
00991         POSITION pos = modelList.GetHeadPosition();
00992         while(pos)
00993                 modelList.GetNext(pos)->SetAspect(asp);
00994 }
00995 
00996 CGuiObject* CGuiFco::FindObject(CComPtr<IMgaFCO>& fco, CGuiFcoList& fcoList)
00997 {
00998         POSITION pos = fcoList.GetHeadPosition();
00999         while(pos) {
01000                 CGuiFco* ofco = fcoList.GetNext(pos);
01001                 ASSERT(ofco != NULL);
01002                 CGuiObject* obj = ofco->dynamic_cast_CGuiObject();
01003                 if (obj) {
01004                         VARIANT_BOOL b;
01005                         COMTHROW(obj->mgaFco->get_IsEqual(fco, &b));
01006                         if (b)
01007                                 return obj;
01008                 }
01009         }
01010         return 0;
01011 }
01012 
01013 CGuiConnection* CGuiFco::FindConnection(CComPtr<IMgaFCO>& fco, CGuiConnectionList& conns)
01014 {
01015         POSITION pos = conns.GetHeadPosition();
01016         while(pos) {
01017                 CGuiConnection* conn = conns.GetNext(pos);
01018                 VARIANT_BOOL b;
01019                 COMTHROW(conn->mgaFco->get_IsEqual(fco, &b));
01020                 if(b != VARIANT_FALSE)
01021                         return conn;
01022         }
01023         return 0;
01024 }
01025 
01026 
01027 void CGuiFco::GrayOutFcos(CGuiFcoList& list, bool set)
01028 {
01029         POSITION pos = list.GetHeadPosition();
01030         while(pos)
01031                 list.GetNext(pos)->GrayOut(set);
01032 }
01033 
01034 void CGuiFco::GrayOutFcos(CGuiConnectionList& list, bool set)
01035 {
01036         POSITION pos = list.GetHeadPosition();
01037         while(pos)
01038                 list.GetNext(pos)->GrayOut(set);
01039 }
01040 
01041 void CGuiFco::GrayOutNonInternalConnections(CGuiConnectionList& list)
01042 {
01043         POSITION pos = list.GetHeadPosition();
01044         while(pos) {
01045                 CGuiConnection *conn = list.GetNext(pos);
01046                 if(conn->src && conn->dst)
01047                         conn->GrayOut(conn->src->grayedOut || conn->dst->grayedOut);
01048         }
01049 }
01050 
01051 void CGuiFco::ResetFlags(CGuiFcoList& list)
01052 {
01053         POSITION pos = list.GetHeadPosition();
01054         while(pos)
01055                 list.GetNext(pos)->flag = 0;
01056 }
01057 
01059 // Virtual methods of CGuiFco
01061 
01062 
01063 CGuiMetaAttributeList *CGuiFco::GetMetaAttributes()
01064 {
01065         return &guiMeta->attrs;
01066 }
01067 
01068 
01070 
01072 // Non-virtual methods of CGuiObject
01074 CGuiObject::CGuiObject(CComPtr<IMgaFCO>& pt, CComPtr<IMgaMetaRole>& role, CGMEView* vw, int numAsp) : CGuiFco(pt, role, vw, numAsp)
01075 {
01076         guiAspects.SetSize(numAsp);
01077         for (int i = 0; i<numAsp; i++) {
01078                 guiAspects[i] = NULL;
01079         }
01080 }
01081 
01082 void CGuiObject::InitObject(CWnd* viewWnd)
01083 {
01084         try {
01085                 CComPtr<IMgaMetaParts> mmParts;
01086                 COMTHROW(metaRole->get_Parts(&mmParts));
01087                 MGACOLL_ITERATE(IMgaMetaPart,mmParts) {
01088                         CComPtr<IMgaMetaPart> mmPart;
01089                         mmPart = MGACOLL_ITER;
01090                         CComPtr<IMgaMetaAspect> mmAspect;
01091                         COMTHROW(mmPart->get_ParentAspect(&mmAspect));
01092                         CComBSTR bstr;
01093                         COMTHROW(mmAspect->get_Name(&bstr));
01094                         CString aspName;
01095                         CopyTo(bstr,aspName);
01096                         CGuiMetaAspect *guiMetaAsp = GetGuiMetaParent()->FindAspect(aspName);
01097                         VERIFY(guiMetaAsp);
01098                         VERIFY(guiMetaAsp->index < numParentAspects);
01099                         CString decoratorStr;
01100                         GetDecoratorStr(decoratorStr);
01101                         InitAspect(guiMetaAsp->index, mmPart, decoratorStr, viewWnd);
01102                 }
01103                 MGACOLL_ITERATE_END;
01104 
01105                 CString hotspotPref;
01106                 GetPreference(hotspotPref, HOTSPOT_PREF);
01107                 if (hotspotPref == HOTSPOT_FALSE) {
01108                         isHotspotEnabled = false;
01109                 }
01110                 else {
01111                         isHotspotEnabled = true;
01112                 }
01113         }
01114         catch(hresult_exception &e) {
01115                 numParentAspects = 0;
01116                 parentAspect = 0;
01117                 throw hresult_exception(e.hr);
01118                 return;
01119         }
01120         if (IsReal()) {
01121                 ReadAllLocations();
01122         }
01123         else {
01124                 SetAllSizesToNative();
01125         }
01126 }
01127 
01128 CGuiObject::~CGuiObject()
01129 {
01130         if (view) {
01131                 POSITION ppos = view->pendingRequests.GetHeadPosition();
01132                 while (ppos) {
01133                         POSITION tmp = ppos;
01134                         CPendingObjectPosRequest *req = dynamic_cast<CPendingObjectPosRequest*> (view->pendingRequests.GetNext(ppos));
01135                         if (req) {
01136                                 if ( req->object == this ) {
01137                                         view->pendingRequests.RemoveAt(tmp);
01138                                         delete req;
01139                                 }
01140                         }
01141                 }
01142         }
01143 
01144         for (int i = 0; i < guiAspects.GetSize(); i++) {
01145                 delete guiAspects[i];
01146         }
01147         guiAspects.RemoveAll();
01148 }
01149 
01150 void CGuiObject::InitAspect(int asp, CComPtr<IMgaMetaPart>& metaPart, CString& decorStr, CWnd* viewWnd)
01151 {
01152         VERIFY(asp < numParentAspects);
01153         CGuiMetaAspect* metaAspect = GetKindAspect(metaPart);
01154         VERIFY(metaAspect);
01155 
01156         CString progId;
01157         CStringList params;
01158         CStringList values;
01159 
01160         if (!decorStr.IsEmpty()) {      // no decorator progId and no paarmeters => use default box decorator later
01161                 if (decorStr.FindOneOf(_T("\n\t ,=")) == -1) {  // just a progId, no parameters
01162                         progId = decorStr;
01163                 } else {        // there is some parameter
01164                         LPTSTR lpsz = new TCHAR[decorStr.GetLength()+1];
01165                         LPTSTR tok = new TCHAR[decorStr.GetLength()+1];
01166                         _tcscpy(lpsz, decorStr);
01167                         int curpos = 0, tokpos = 0;
01168                         int state = 0;  // 0:progid, 1:var, 2:val
01169                         bool    gotOne = false;
01170                         TCHAR   ch;
01171 
01172                         while ( (ch = lpsz[curpos++]) != 0) {
01173                                 if (ch == _T('\n') || ch == _T('\t') || ch == _T(' ')) {
01174                                         if (gotOne) {
01175                                                 state = 1;
01176                                                 gotOne = false;
01177                                                 tok[tokpos] = 0;
01178                                                 progId = tok;
01179                                                 tokpos = 0;
01180                                         }
01181                                         continue;
01182                                 }
01183                                 switch (state) {
01184                                         case 0:
01185                                                 gotOne = true;
01186                                                 tok[tokpos++] = ch;
01187                                                 break;
01188                                         case 1:
01189                                                 if (ch == _T('=')) {
01190                                                         state = 2;
01191                                                         tok[tokpos] = 0;
01192                                                         params.AddTail(tok);
01193                                                         tokpos = 0;
01194                                                 }
01195                                                 else {
01196                                                         tok[tokpos++] = ch;
01197                                                 }
01198                                                 break;
01199                                         case 2:
01200                                                 if (ch == _T(',')) {
01201                                                         state = 1;
01202                                                         tok[tokpos] = 0;
01203                                                         values.AddTail(tok);
01204                                                         tokpos = 0;
01205                                                 }
01206                                                 else {
01207                                                         tok[tokpos++] = ch;
01208                                                 }
01209                                                 break;
01210                                 }
01211                         }
01212                         if (state == 0) {
01213                                 tok[tokpos] = 0;
01214                                 progId = tok;
01215                         }
01216                         if (state == 2) {
01217                                 tok[tokpos] = 0;
01218                                 values.AddTail(tok);
01219                         }
01220 
01221                         delete [] lpsz; // WAS: delete lpsz;
01222                         delete [] tok;; // WAS: delete tok;;
01223                 }
01224         }
01225 
01226         if (progId.IsEmpty()) {
01227                 progId = GME_DEFAULT_DECORATOR;
01228         }
01229         CComPtr<IMgaDecorator> decor;
01230         CComPtr<IMgaElementDecorator> newDecor;
01231 
01232         CComObjPtr<CDecoratorEventSink> decoratorEventSink;
01233         try {
01234                 CComPtr<IMgaElementDecoratorEvents> decoratorEventSinkIface;
01235                 HRESULT hres = newDecor.CoCreateInstance(PutInBstr(progId));
01236                 if (FAILED(hres) && hres != CO_E_CLASSSTRING) { // might be an old decorator
01237                         hres = decor.CoCreateInstance(PutInBstr(progId));
01238                 }
01239                 if (FAILED(hres)) {     // fall back to default decorator
01240                         if (this->view->uncreatableDecorators.find(progId) == this->view->uncreatableDecorators.end())
01241                         {
01242                                 CMainFrame::theInstance->m_console.Message(_T("Cannot create ") + progId + _T(" decorator! Trying default (") + GME_DEFAULT_DECORATOR + _T(") decorator."), 3);
01243                                 this->view->uncreatableDecorators.insert(progId);
01244                         }
01245                         progId = GME_DEFAULT_DECORATOR;
01246                         COMTHROW(newDecor.CoCreateInstance(PutInBstr(progId)));
01247                 }
01248 
01249                 if (newDecor) {
01250                         ::CreateComObject(decoratorEventSink);
01251                         HRESULT hr = ::QueryInterface((IMgaElementDecoratorEvents*)decoratorEventSink.p, &decoratorEventSinkIface);
01252                         if (SUCCEEDED(hr)) {
01253                                 decoratorEventSink->SetView(view);
01254                                 decoratorEventSink->SetGuiObject(this);
01255                         } else {
01256                                 ASSERT(false);
01257                         }
01258                         decor = CComQIPtr<IMgaDecorator>(newDecor);
01259                 }
01260 
01261                 // It seems that SetParam fails before InitializeEx, so this was probably never tested...
01262                 POSITION ppos = params.GetHeadPosition();
01263                 POSITION vpos = values.GetHeadPosition();
01264                 while (ppos && vpos) {
01265                         CComBSTR param(params.GetNext(ppos));
01266                         CComVariant value(values.GetNext(vpos));
01267                         COMTHROW(decor->SetParam(param, value));
01268                 }
01269                 // *************************************************************************************
01270 
01271                 if (newDecor)
01272                         COMTHROW(newDecor->InitializeEx(theApp.mgaProject, metaPart, mgaFco, decoratorEventSinkIface, (ULONGLONG)viewWnd->m_hWnd));
01273                 else
01274                         COMTHROW(decor->Initialize(theApp.mgaProject, metaPart, mgaFco));
01275 
01276                 if (CGMEView::showConnectedPortsOnly )
01277                 {
01278                         CComVariant value(VARIANT_TRUE);
01279                         CComBSTR param(DEC_CONNECTED_PORTS_ONLY_PARAM);
01280                         COMTHROW(decor->SetParam(param,value));
01281                 }
01282         }
01283         catch (hresult_exception&) {
01284                 CMainFrame::theInstance->m_console.Message(_T("Cannot create ") + progId + _T(" decorator."), 3);
01285         }
01286         guiAspects[asp] = new CGuiAspect(metaAspect, this, metaAspect->index, asp, decor, newDecor, decoratorEventSink);
01287         parentAspect = 0;
01288 }
01289 
01290 void CGuiObject::GetDecoratorStr(CString& decorStr)
01291 {
01292         if (!GetPreference(decorStr, DECORATOR_PREF))
01293                 decorStr = GME_DEFAULT_DECORATOR;
01294 }
01295 
01296 void CGuiObject::SetObjectLocation(CRect& rect, int aspect, bool doMga)
01297 {
01298         if(aspect < 0)
01299                 aspect = parentAspect;
01300         VERIFY(aspect >= 0);
01301         VERIFY(guiAspects[aspect] != NULL);
01302         CRect loc = guiAspects[aspect]->GetLocation();
01303         // if (IsReal()) {
01304         loc.MoveToXY(rect.left, rect.top);
01305         guiAspects[aspect]->SetLocation(loc);
01306         if(IsReal() && doMga)
01307                 WriteLocation(aspect);
01308 }
01309 
01310 void CGuiObject::SetSize(CSize& s, int aspect, bool doMga)
01311 {
01312         if(aspect < 0)
01313                 aspect = parentAspect;
01314         VERIFY(aspect >= 0);
01315         VERIFY(guiAspects[aspect] != NULL);
01316         CRect loc = guiAspects[aspect]->GetLocation();
01317         ::SetSize(loc,s);
01318         guiAspects[aspect]->SetLocation(loc);
01319         if(IsReal() && doMga)
01320                 WriteLocation(aspect);
01321 }
01322 
01323 void CGuiObject::SetAllSizes(CSize& s, bool doMga)
01324 {
01325         for(int i = 0; i < numParentAspects; i++)
01326                 if(guiAspects[i] != NULL)
01327                         SetSize(s,i,doMga);
01328 }
01329 
01330 void CGuiObject::SetLocation(CRect& r, int aspect, bool doMga/*, bool savePreferredSize*/)
01331 {
01332         if(aspect < 0)
01333                 aspect = parentAspect;
01334         VERIFY(aspect >= 0);
01335         VERIFY(guiAspects[aspect] != NULL);
01336         guiAspects[aspect]->SetLocation(r);
01337         if(IsReal() && doMga)
01338                 WriteLocation(aspect/*, savePreferredSize*/);
01339 }
01340 
01341 CSize CGuiObject::GetNativeSize(int aspect)
01342 {
01343         if(aspect < 0)
01344                 aspect = parentAspect;
01345         VERIFY(aspect >= 0);
01346         if(guiAspects[aspect] == NULL)
01347                 return CSize(0,0);
01348         try {
01349                 long sizex, sizey;
01350                 COMTHROW(guiAspects[aspect]->GetDecorator()->GetPreferredSize(&sizex, &sizey));
01351                 return CSize(sizex, sizey);
01352         }
01353         catch (hresult_exception &) {
01354                 return false;
01355         }
01356         //return true;// unreachable code
01357 }
01358 
01359 
01360 void CGuiObject::SetAllSizesToNative()
01361 {
01362         CSize s;
01363         for(int i = 0; i < numParentAspects; i++) {
01364                 if(guiAspects[i]) {
01365                         s=GetNativeSize(i);
01366                         CRect loc(0, 0, 0, 0);
01367                         guiAspects[i]->SetLocation(loc);
01368                         SetSize(s, i, false);
01369                 }
01370         }
01371 }
01372 
01373 void CGuiObject::GetNeighbors(CGuiFcoList& list)
01374 {
01375         VERIFY(GetCurrentAspect());
01376         CGuiPortList& portList = GetCurrentAspect()->GetPortList();
01377         POSITION ppos = portList.GetHeadPosition();
01378         while (ppos) {
01379                 CGuiPort *port = portList.GetNext(ppos);
01380                 POSITION cpos = port->GetInConns().GetHeadPosition();
01381                 while(cpos) {
01382                         CGuiConnection *conn = port->GetInConns().GetNext(cpos);
01383                         if(conn->src->flag == 0) {
01384                                 list.AddTail(conn->src);
01385                                 conn->src->flag = 1;
01386                         }
01387                 }
01388                 cpos = port->GetOutConns().GetHeadPosition();
01389                 while(cpos) {
01390                         CGuiConnection *conn = port->GetOutConns().GetNext(cpos);
01391                         if(conn->dst->flag == 0) {
01392                                 list.AddTail(conn->dst);
01393                                 conn->dst->flag = 1;
01394                         }
01395                 }
01396         }
01397 }
01398 
01399 void CGuiObject::GetRelationsInOut(CGuiConnectionList& p_list, bool p_inOrOut)
01400 {
01401         VERIFY(GetCurrentAspect());
01402         
01403         // acquire ports
01404         CGuiPortList& portList = GetCurrentAspect()->GetPortList();
01405         POSITION ppos = portList.GetHeadPosition();
01406         while (ppos) 
01407         {
01408                 // one port
01409                 CGuiPort *port = portList.GetNext(ppos);
01410 
01411                 ASSERT( port); 
01412                 if( !port) continue;
01413 
01414                 // acquire the in/out connections through the current port
01415                 POSITION cpos = p_inOrOut? port->GetInConns().GetHeadPosition(): port->GetOutConns().GetHeadPosition();
01416                 while(cpos) 
01417                 {
01418                         // one connection
01419                         CGuiConnection* conn = p_inOrOut? port->GetInConns().GetNext(cpos): port->GetOutConns().GetNext(cpos);
01420 
01421                         ASSERT( conn);
01422                         if( !conn) continue;
01423 
01424                         // store it
01425                         p_list.AddTail( conn);
01426                 }
01427         }
01428 }
01429 
01430 void CGuiObject::ReadAllLocations()
01431 {
01432         try {
01433                 CComPtr<IMgaMetaParts> mmParts;
01434                 CComPtr<IMgaMetaPart> mmPart;
01435                 COMTHROW(metaRole->get_Parts(&mmParts));
01436                 MGACOLL_ITERATE(IMgaMetaPart,mmParts) {
01437                         mmPart = MGACOLL_ITER;
01438                         CComPtr<IMgaMetaAspect> mmAspect;
01439                         COMTHROW(mmPart->get_ParentAspect(&mmAspect));
01440                         CComBSTR bstr;
01441                         COMTHROW(mmAspect->get_Name(&bstr));
01442                         CString aspName;
01443                         CopyTo(bstr,aspName);
01444                         CGuiMetaAspect *guiMetaAsp = GetGuiMetaParent()->FindAspect(aspName);
01445                         VERIFY(guiMetaAsp);
01446                         VERIFY(guiMetaAsp->index < numParentAspects);
01447                         int aspIndex = guiMetaAsp->index;
01448                         VERIFY(aspIndex >= 0);
01449                         CComPtr<IMgaPart> part;
01450                         COMTHROW(mgaFco->get_Part(mmAspect,&part));
01451                         CComBSTR icon;
01452                         long x;
01453                         long y;
01454 
01455                         CRect loc(0, 0, 0, 0);
01456                         CSize s = GetNativeSize(aspIndex);
01457                         ::SetSize(loc,s);
01458 
01459                         if(part->GetGmeAttrs(0, &x, &y) == S_OK) {
01460                                 ::SetLocation(loc, CPoint(x, y));
01461                                 guiAspects[aspIndex]->SetLocation(loc);
01462                         }
01463                         else { // unparsable integer pair found, use (-1, -1) like in CMgaPart::GetGmeAttrs
01464                                 ::SetLocation(loc,CPoint(-1, -1));
01465                                 guiAspects[aspIndex]->SetLocation(loc);
01466                         }
01467                 }
01468                 MGACOLL_ITERATE_END;
01469         }
01470         catch(hresult_exception &e) {
01471                 throw hresult_exception(e.hr);
01472         }
01473 }
01474 
01475 void CGuiObject::WriteLocation(int aspect)
01476 {
01477         VERIFY(IsReal());
01478         if(aspect < 0)
01479                 aspect = parentAspect;
01480         VERIFY(aspect >= 0);
01481         VERIFY(guiAspects[aspect]);
01482         try {
01483                 view->BeginTransaction();
01484                 CComPtr<IMgaPart> part;
01485                 CGuiMetaAspect *guiAsp = GetGuiMetaParent()->FindAspect(aspect);
01486                 CComPtr<IMgaMetaBase> mBase = guiAsp->mgaMeta;
01487                 CComPtr<IMgaMetaAspect> mAspect;
01488                 COMTHROW(mBase.QueryInterface(&mAspect));
01489                 COMTHROW(mgaFco->get_Part(mAspect,&part));
01490                 CRect r = guiAspects[aspect]->GetLocation();
01491                 // Save position part
01492                 CPoint pt = r.TopLeft();
01493                 COMTHROW(part->SetGmeAttrs(0, pt.x, pt.y));
01494                 // This would be too agressive: to delete any connecting connections customizations if the box is moved
01495                 // DeleteCustomizationOfInOutConnections(aspect);
01496                 view->CommitTransaction();
01497         }
01498         catch(hresult_exception &e) {
01499                 view->AbortTransaction(e.hr);
01500         }
01501 }
01502 
01503 void CGuiObject::DeleteCustomizationOfConnections(CGuiConnectionList& conns, long aspect)
01504 {
01505         POSITION pos = conns.GetHeadPosition();
01506         while(pos) {
01507                 CGuiConnection* conn = conns.GetNext(pos);
01508                 if (conn->HasPathCustomization())
01509                         if (conn->DeleteAllPathCustomizationsForAnAspect(aspect))
01510                                 conn->WriteCustomPathData(false);
01511         }
01512 }
01513 
01514 void CGuiObject::DeleteCustomizationOfInOutConnections(long aspect)
01515 {
01516         CGuiConnectionList inConns;
01517         GetRelationsInOut(inConns, true);
01518         DeleteCustomizationOfConnections(inConns, aspect);
01519         CGuiConnectionList outConns;
01520         GetRelationsInOut(outConns, false);
01521         DeleteCustomizationOfConnections(outConns, aspect);
01522 }
01523 
01524 void CGuiObject::GrayOutNeighbors()
01525 {
01526         CGuiFcoList neighbors;
01527         GetNeighbors(neighbors);
01528         GrayOutFcos(neighbors, grayedOut);
01529         ResetFlags(neighbors);
01530 }
01531 
01532 bool CGuiObject::IsInside(CPoint& pt, bool lookNearToo)
01533 {
01534         CRect loc = GetLocation();
01535         if (lookNearToo)
01536                 loc.InflateRect(3, 3);
01537         return (loc.PtInRect(pt) == TRUE);
01538 }
01539 
01540 bool CGuiObject::IsLabelInside(CPoint& pt, bool lookNearToo)
01541 {
01542         CRect loc = GetNameLocation();
01543         if (lookNearToo)
01544                 loc.InflateRect(3, 3);
01545         return (loc.PtInRect(pt) == TRUE);
01546 }
01547 
01548 CGuiPort* CGuiObject::FindPort(CPoint& pt, bool lookNearToo)
01549 {
01550         CGuiPort* found = NULL;
01551         CSize foundSize(0, 0);
01552         VERIFY(GetCurrentAspect());
01553         CGuiPortList& portList = GetCurrentAspect()->GetPortList();
01554         POSITION pos = portList.GetHeadPosition();
01555         while(pos) {
01556                 CGuiPort* port = portList.GetNext(pos);
01557                 // The last one in the list is weird one: fco is the object's fco, skip that.
01558                 // See CGuiAspect::InitPorts
01559                 if (!mgaFco.IsEqualObject(port->mgaFco))
01560                 {
01561                         CRect r = port->GetLocation() + GetLocation().TopLeft();
01562                         r.InflateRect(1, 1); // consider mouseover on red outline too
01563                         CRect rInflated = r;
01564                         rInflated.InflateRect(3, 3);
01565                         if (r.PtInRect(pt) == TRUE || (lookNearToo && rInflated.PtInRect(pt) == TRUE))
01566                         {
01567                                 CSize psize = port->GetLocation().Size();
01568                                 if (found)
01569                                 {
01570                                         if (psize.cx < foundSize.cx && psize.cy < foundSize.cy ) {
01571                                                 foundSize = psize;
01572                                                 found = port;
01573                                         }
01574                                 }
01575                                 else
01576                                 {
01577                                         foundSize = psize;
01578                                         found = port;
01579                                 }
01580                         }
01581                 }
01582         }
01583         return found;
01584 }
01585 
01586 CGuiPort* CGuiObject::FindPort(CComPtr<IMgaFCO> mgaFco)
01587 {
01588         ASSERT(GetCurrentAspect());
01589         CGuiPortList& portList = GetCurrentAspect()->GetPortList();
01590         POSITION pos = portList.GetHeadPosition();
01591         while(pos) {
01592                 CGuiPort* port = portList.GetNext(pos);
01593                 VARIANT_BOOL b;
01594                 COMTHROW(port->mgaFco->get_IsEqual(mgaFco, &b));
01595                 if (b)
01596                         return port;
01597         }
01598         return 0;
01599 }
01600 
01601 void CGuiObject::IncrementAnimRefCnt()
01602 {
01603         if (view) {
01604                 if (!(view->animRefCnt++)) {
01605                         view->timerID = view->SetTimer(GME_ANIM_EVENT_ID, GME_ANIM_INTERVAL, NULL);
01606                 }
01607         }
01608 }
01609 
01610 void CGuiObject::DecrementAnimRefCnt()
01611 {
01612         if (view) {
01613                 ASSERT(view->animRefCnt);
01614                 if (!(--view->animRefCnt)) {
01615                         if (view->timerID) {
01616                                 view->KillTimer(view->timerID);
01617                                 view->timerID = 0;
01618                         }
01619                 }
01620         }
01621 }
01622 
01623 
01625 // Static methods of CGuiObject
01627 
01628 void CGuiObject::GetExtent(CGuiFcoList& objectList, CRect& rect)
01629 {
01630         CGuiObject* obj;
01631         CRect cur1, cur2;
01632         POSITION pos = objectList.GetHeadPosition();
01633         rect = CRect(0, 0, 10, 10);
01634         while (pos) {
01635                 CGuiFco* fco = objectList.GetNext(pos);
01636                 ASSERT(fco != NULL);
01637                 obj = fco->dynamic_cast_CGuiObject();
01638                 if(obj && obj->IsVisible()) {
01639                         cur2 = obj->GetLocation();
01640                         cur1 = rect;
01641                         rect.UnionRect(&cur1, &cur2);
01642                 }
01643         }
01644 }
01645 
01646 void CGuiObject::GetExtent(CGuiObjectList& objectList, CRect& rect)
01647 {
01648         CGuiObject* obj;
01649         CRect cur1, cur2;
01650         POSITION pos = objectList.GetHeadPosition();
01651         rect = CRect(0, 0, 0, 0);
01652         while(pos) {
01653                 obj = objectList.GetNext(pos);
01654                 if(obj && obj->IsVisible()) {
01655                         cur2 = obj->GetLocation();
01656                         cur1 = rect;
01657                         rect.UnionRect(&cur1, &cur2);
01658                 }
01659         }
01660 }
01661 
01662 void CGuiObject::MoveObjects(CGuiFcoList& fcoList, CPoint& pt)
01663 {
01664         CGuiObjectList objs;
01665         POSITION pos = fcoList.GetHeadPosition();
01666         while(pos) {
01667                 CGuiFco* fco = fcoList.GetNext(pos);
01668                 ASSERT(fco != NULL);
01669                 CGuiObject* obj = fco->dynamic_cast_CGuiObject();
01670                 if (obj)
01671                         objs.AddTail(obj);
01672         }
01673         MoveObjects(objs, pt);
01674 }
01675 
01676 void CGuiObject::MoveObjects(CGuiObjectList& objList, CPoint& pt)
01677 {
01678         int left, top;
01679         FindUpperLeft(objList, left, top);
01680         CPoint diff = pt - CPoint(left, top);
01681         ShiftModels(objList, diff);
01682 }
01683 
01684 
01685 void CGuiObject::FindUpperLeft(CGuiObjectList& objs, int& left, int& top)
01686 {
01687         bool start = true;
01688         POSITION pos = objs.GetHeadPosition();
01689         CGuiObject* obj;
01690         CRect r;
01691         while(pos) {
01692                 obj = objs.GetNext(pos);
01693                 if(obj->IsVisible()) {
01694                         r = obj->GetLocation();
01695                         if(start) {
01696                                 left = r.left;
01697                                 top = r.top;
01698                                 start = false;
01699                         }
01700                         else {
01701                                 if(r.left < left)
01702                                         left = r.left;
01703                                 if(r.top < top)
01704                                         top = r.top;
01705                         }
01706                 }
01707         }
01708 }
01709 
01710 void CGuiObject::ShiftModels(CGuiObjectList& objList, CPoint& shiftBy)
01711 {
01712         CGMEEventLogger::LogGMEEvent(_T("CGuiObject::ShiftModels "));
01713         GMEEVENTLOG_GUIOBJS(objList);
01714 
01715         CGuiObject* first_obj = objList.IsEmpty() ? 0 : objList.GetHead();
01716         if( first_obj && first_obj->GetView() && first_obj->GetView() != modelGrid.GetSource())
01717         {
01718                 // if the view where the object was moved and the view of the grid 
01719                 // do not correspond, we must clear & update the grid.
01720                 // possible because if a port is moved inside a model, then the model
01721                 // is redrawn as well, and modelGrid is a global variable.
01722                 // clearing only the grid would be too dangerous, would allow any movement
01723                 // because other objects will disappear from the radar
01724                 // but a Clear with a FillModelGrid will do the correct update
01725                 modelGrid.Clear();
01726                 first_obj->GetView()->FillModelGrid();
01727         }
01728 
01729         POSITION pos = objList.GetHeadPosition();
01730         while(pos) {
01731                 CGuiObject* obj = objList.GetNext(pos);
01732                 modelGrid.Reset(obj);
01733         }
01734         pos = objList.GetHeadPosition();
01735         while(pos) {
01736                 CGuiObject* obj = objList.GetNext(pos);
01737                 VERIFY(obj->IsVisible());
01738                 CRect rect = obj->GetLocation();
01739                 rect.MoveToXY(rect.left + shiftBy.x, rect.top + shiftBy.y);
01740                 if(!modelGrid.GetClosestAvailable(obj, rect)) {
01741                         //AfxMessageBox(_T("Too Many Models! Internal Program Error!"),MB_OK | MB_ICONSTOP);
01742                         //return;
01743                 }
01744                 obj->SetLocation(rect);
01745                 modelGrid.Set(obj);
01746         }
01747 }
01748 
01749 void CGuiObject::ResizeObject(const CRect& newLocation/*, bool doMga*/)
01750 {
01751         CGMEEventLogger::LogGMEEvent(_T("CGuiObject::ResizeObject\n"));
01752 
01753         VERIFY(IsVisible());
01754         SetLocation((CRect)newLocation, -1, false/*doMga, true*/);
01755         // Note: there's no need to update modelgrid now, because after finishing the resize operation
01756         //               there will be a full GMEView::Reset induced by the transaction commit
01757 }
01758 
01759 bool CGuiObject::NudgeObjects(CGuiObjectList& modelList, int right, int down)
01760 {
01761         CGMEEventLogger::LogGMEEvent(_T("CGuiObject::NudgeObjects "));
01762         GMEEVENTLOG_GUIOBJS(modelList);
01763         ASSERT(right == 0 || down == 0); // cannot nudge diagonally for now
01764 
01765         CGuiObject* first_obj = modelList.IsEmpty() ? 0 : modelList.GetHead();
01766         if( first_obj && first_obj->GetView() && first_obj->GetView() != modelGrid.GetSource())
01767         {
01768                 // if the view where the object was nudged and the view of the grid 
01769                 // do not correspond, we must clear & update the grid
01770                 // possible because if a port is moved inside a model, then the model
01771                 // is redrawn as well, and modelGrid is a global variable.
01772                 // clearing only the grid would be too dangerous, would allow nudging always
01773                 // because other objects will not seem to sit in their places
01774                 // but a Clear with a FillModelGrid will do the correct update
01775                 modelGrid.Clear();
01776                 first_obj->GetView()->FillModelGrid();
01777         }
01778 
01779         POSITION pos = modelList.GetHeadPosition();
01780         while(pos) {
01781                 CGuiObject* model = modelList.GetNext(pos);
01782                 VERIFY(model->IsVisible());
01783                 modelGrid.Reset(model);
01784         }
01785         bool canDo = true;
01786         pos = modelList.GetHeadPosition();
01787         while(pos) {
01788                 CGuiObject* model = modelList.GetNext(pos);
01789                 if(!modelGrid.CanNudge(model, right, down)) {
01790                         canDo = false;
01791                         break;
01792                 }
01793         }
01794         if(canDo) {
01795                 POSITION pos = modelList.GetHeadPosition();
01796                 while(pos) {
01797                         CGuiObject *model = modelList.GetNext(pos);
01798                         CRect loc = model->GetLocation();
01799                         loc.OffsetRect(CPoint(right * GME_GRID_SIZE, down * GME_GRID_SIZE));
01800                         model->SetLocation(loc);
01801                         ASSERT(modelGrid.IsAvailable(model));
01802                         modelGrid.Set(model);
01803                 }
01804         }
01805         else {
01806                 POSITION pos = modelList.GetHeadPosition();
01807                 while(pos) {
01808                         CGuiObject* model = modelList.GetNext(pos);
01809                         modelGrid.Set(model);
01810                 }
01811         }
01812         return canDo;
01813 }
01814 
01815 void CGuiObject::GetRectList(CGuiObjectList& objList, CRectList& rects)
01816 {
01817         POSITION pos = objList.GetHeadPosition();
01818         while(pos) {
01819                 CRect* rect = new CRect(objList.GetNext(pos)->GetLocation());
01820                 rects.AddTail(rect);
01821         }
01822 }
01823 
01824 bool CGuiObject::IsResizable(void)
01825 {
01826         VERIFY(parentAspect >= 0);
01827         VERIFY(GetCurrentAspect());
01828 
01829         try {
01830                 feature_code fc = 0;
01831                 CGuiAspect* aspect = GetCurrentAspect();
01832                 if (aspect->GetNewDecorator())
01833                         COMTHROW(GetCurrentAspect()->GetNewDecorator()->GetFeatures(&fc));
01834                 else
01835                         COMTHROW(GetCurrentAspect()->GetDecorator()->GetFeatures(&fc));
01836                 return ((fc & F_RESIZABLE) != 0);
01837         }
01838         catch (hresult_exception &) {
01839                 AfxMessageBox(_T("Error in CGuiObject [method IsResizable()]"));
01840         }
01841 
01842         return false;
01843 }
01844 
01845 
01847 // Virtual methods of CGuiObject
01849 void CGuiObject::Draw(HDC pDC, Gdiplus::Graphics* gdip)
01850 {
01851         VERIFY(parentAspect >= 0);
01852         VERIFY(GetCurrentAspect());
01853 
01854         try {
01855                 CGuiAspect* aspect = GetCurrentAspect();
01856                 if (aspect->GetNewDecorator())
01857                         COMTHROW(GetCurrentAspect()->GetNewDecorator()->DrawEx((ULONG)pDC, (ULONGLONG)gdip));
01858                 else
01859                         COMTHROW(GetCurrentAspect()->GetDecorator()->Draw((ULONG)pDC));
01860         }
01861         catch (hresult_exception &e) {
01862                 CComQIPtr<ISupportErrorInfo> errorInfo = GetCurrentAspect()->GetDecorator();
01863                 _bstr_t error;
01864                 if (errorInfo) {
01865                         GetErrorInfo(error.GetAddress());
01866                 } else {
01867                         GetErrorInfo(e.hr, error.GetAddress());
01868                 }
01869                 // FIXME: KMS: won't Draw() be called after the MessageBox is dismissed?
01870                 AfxMessageBox(CString(_T("Error in decorator [method Draw()]: ")) + static_cast<const TCHAR*>(error));
01871         }
01872 
01873 // #define _ARDEBUG
01874 #ifdef _ARDEBUG
01875         CPen arPen(PS_DOT, 1, 0x000000ff);
01876         CPen *oldPen = pDC->SelectObject(&arPen);
01877         pDC->SelectStockObject(HOLLOW_BRUSH);
01878         //pDC->Rectangle(GetCurrentAspect()->GetLocation());
01879         //pDC->Rectangle(GetCurrentAspect()->GetNameLocation());
01880         if (GetRouterBox()) {
01881                 pDC->Rectangle(GetRouterBox()->GetRect());
01882         }
01883         if (GetRouterNameBox()) {
01884                 pDC->Rectangle(GetRouterNameBox()->GetRect());
01885         }
01886         pDC->SelectObject(oldPen);
01887 #endif
01888 
01889 }
01890 
01891 void CGuiObject::GrayOut(bool set)
01892 {
01893         CGuiFco::GrayOut(set);
01894 
01895         for (int i = 0; i< guiAspects.GetSize(); i++) {
01896                 if (IsVisible(i)) {
01897                         COMTHROW(guiAspects[i]->GetDecorator()->SetActive(set ? VARIANT_FALSE : VARIANT_TRUE));
01898                 }
01899         }
01900 }
01901 
01902 
01903 
01904 CGuiMetaAspect *CGuiObject::GetKindAspect(CComPtr<IMgaMetaPart> metaPart)
01905 {
01906         // Kindaspect is the same as parentaspect in regular objects
01907         CComBSTR bstr;
01908         CComPtr<IMgaMetaAspect> pAspect;
01909         COMTHROW(metaPart->get_ParentAspect(&pAspect));
01910         COMTHROW(pAspect->get_Name(&bstr));
01911         CString aspName;
01912         CopyTo(bstr, aspName);
01913         return GetGuiMetaParent()->FindAspect(aspName);
01914 }
01915 
01917 
01919 // Non-virtual methods of CGuiCompound
01921 
01923 // Static methods of CGuiCompound
01925 
01927 // Virtual methods of CGuiCompound
01929 
01930 
01932 
01934 // Non-virtual methods of CGuiModel
01936 CGuiModel::CGuiModel(CComPtr<IMgaFCO>& pt, CComPtr<IMgaMetaRole>& role,CGMEView* vw, int numAsp) : CGuiCompound(pt, role, vw, numAsp)
01937 {
01938         if (IsReal()) {
01939                 VARIANT_BOOL inst;
01940                 COMTHROW(pt->get_IsInstance(&inst));
01941                 isType = (inst == VARIANT_FALSE);
01942         }
01943 }
01944 
01946 // Static methods of CGuiModel
01948 
01950 // Virtual methods of CGuiModel
01952 CGuiMetaAttributeList* CGuiModel::GetMetaAttributes()
01953 {
01954         return &(GetCurrentAspect()->guiMeta->attrs);
01955 }
01956 
01957 CGuiMetaAspect* CGuiModel::GetKindAspect(CComPtr<IMgaMetaPart> metaPart)
01958 {
01959         CGuiMetaModel* guiMetaModel = dynamic_cast<CGuiMetaModel*>(guiMeta);
01960         VERIFY(guiMetaModel);
01961         CGuiMetaAspect* metaAspect = NULL;
01962         CComBSTR bstr;
01963         COMTHROW(metaPart->get_KindAspect(&bstr));
01964         CString kindAspect;
01965         CopyTo(bstr, kindAspect);
01966         if (kindAspect.IsEmpty()) {
01967                 CComBSTR bstr;
01968                 CComPtr<IMgaMetaAspect> pAspect;
01969                 COMTHROW(metaPart->get_ParentAspect(&pAspect));
01970                 COMTHROW(pAspect->get_Name(&bstr));
01971                 CopyTo(bstr, kindAspect);
01972                 metaAspect = guiMetaModel->FindAspect(kindAspect);
01973                 if(!metaAspect) {
01974                         metaAspect = guiMetaModel->GetFirstAspect();
01975                         /*
01976                         CComBSTR bstr;
01977                         COMTHROW(metaRole->get_Name(&bstr));
01978                         CString roleName;
01979                         CopyTo(bstr,roleName);
01980                         AfxMessageBox(_T("Missing aspect mapping specification for model ") + name + _T(" aspect ") + kindAspect +
01981                                         _T(" role ") + roleName + _T("!\nFirst aspect ") + metaAspect->name + _T(" is used!"));
01982                         */
01983                 }
01984         }
01985         else {
01986                 metaAspect = guiMetaModel->FindAspect(kindAspect);
01987         }
01988         return metaAspect;
01989 }
01991 
01993 // Non-virtual methods of CReference
01995 
01996 CReference::CReference(CComPtr<IMgaFCO> mgaRefd, CComPtr<IMgaFCO> mgaTermRefd) : mgaReferee(mgaRefd), mgaTerminalReferee(mgaTermRefd)
01997 {
01998         mgaReferee = mgaRefd;
01999         mgaTerminalReferee = mgaTermRefd;
02000         if(!IsNull()) {
02001                 {
02002                         CComBSTR bstr;
02003                         COMTHROW(mgaRefd->get_Name(&bstr));
02004                         CopyTo(bstr,targetName);
02005                 }
02006                 {
02007                         CComPtr<IMgaMetaFCO> meta;
02008                         COMTHROW(mgaRefd->get_Meta(&meta));
02009                         CComBSTR bstr;
02010                         COMTHROW(meta->get_DisplayedName(&bstr));
02011                         CopyTo(bstr, targetKindDisplayedName);
02012                 }
02013         }
02014 }
02015 
02016 CString CReference::GetInfoText(CString &name)
02017 {
02018         CString txt;
02019         if(IsNull())
02020                 txt = name + L" \u2192 null ";
02021         else
02022                 txt.Format(L"%s \u2192 %s (%s) ", name, targetName, targetKindDisplayedName);
02023         return CString(txt);
02024 }
02026 // Static methods of CReference
02028 
02030 // Virtual methods of CReference
02032 
02034 
02036 // Non-virtual methods of CGuiReference
02039 // Static methods of CGuiReference
02042 // Virtual methods of CGuiReference
02044 
02045 
02048 // Non-virtual methods of CGuiCompoundReference
02050 
02052 // Static methods of CGuiCompoundReference
02054 
02056 // Virtual methods of CGuiCompoundReference
02058 
02059 CGuiMetaAttributeList* CGuiCompoundReference::GetMetaAttributes()
02060 {
02061         return &guiMeta->attrs;
02062 }
02063 
02064 CGuiMetaAspect* CGuiCompoundReference::GetKindAspect(CComPtr<IMgaMetaPart> metaPart)
02065 {
02066         CComPtr<IMgaMetaFCO> metaFcoForAM;
02067         COMTHROW(GetTerminalReferee()->get_Meta(&metaFcoForAM));
02068         metaref_type metaRef;
02069         COMTHROW(metaFcoForAM->get_MetaRef(&metaRef));
02070         CGuiMetaModel* guiMetaModel = CGuiMetaProject::theInstance->GetGuiMetaModel(metaRef);
02071         VERIFY(guiMetaModel);
02072 
02073         CGuiMetaAspect* metaAspect = NULL;
02074         CComBSTR bstr;
02075         COMTHROW(metaPart->get_KindAspect(&bstr));
02076         CString kindAspect;
02077         CopyTo(bstr, kindAspect);
02078         if (kindAspect.IsEmpty()) {
02079                 CComBSTR bstr;
02080                 CComPtr<IMgaMetaAspect> pAspect;
02081                 COMTHROW(metaPart->get_ParentAspect(&pAspect));
02082                 COMTHROW(pAspect->get_Name(&bstr));
02083                 CopyTo(bstr, kindAspect);
02084                 metaAspect = guiMetaModel->FindAspect(kindAspect);
02085                 if(!metaAspect) {
02086                         metaAspect = guiMetaModel->GetFirstAspect();
02087                         /*
02088                         CComBSTR bstr;
02089                         COMTHROW(metaRole->get_Name(&bstr));
02090                         CString roleName;
02091                         CopyTo(bstr,roleName);
02092                         AfxMessageBox(_T("Missing aspect mapping specification for model ") + name + _T(" aspect ") + kindAspect +
02093                                         _T(" role ") + roleName + _T("!\nFirst aspect ") + metaAspect->name + _T(" is used!"));
02094                         */
02095                 }
02096         }
02097         else {
02098                 metaAspect = guiMetaModel->FindAspect(kindAspect);
02099         }
02100         return metaAspect;
02101 }
02102 
02103 
02105 
02107 // Non-virtual methods of CGuiSet
02109 
02110 void CGuiSet::Init(CGuiFcoList& objs, CGuiConnectionList& conns)
02111 {
02112         if (!IsReal()) {
02113                 return;
02114         }
02115         CComPtr<IMgaSet> mgaSet;
02116         COMTHROW(mgaFco.QueryInterface(&mgaSet));
02117 
02118         CComPtr<IMgaFCOs> fcos;
02119         COMTHROW(mgaSet->get_Members(&fcos));
02120         MGACOLL_ITERATE(IMgaFCO,fcos) {
02121                 CComPtr<IMgaFCO> member;
02122                 member = MGACOLL_ITER;
02123                 CGuiFco* obj =  CGuiFco::FindObject(member, objs);
02124                 if(!obj)
02125                         obj =  CGuiFco::FindConnection(member, conns);
02126                 VERIFY(obj);
02127                 members.AddTail(obj);
02128         }
02129         MGACOLL_ITERATE_END;
02130 }
02131 
02132 bool CGuiSet::CheckMember(CGuiFco* fco)
02133 {
02134         CComPtr<IMgaMetaSet> metaSet;
02135         COMTHROW(metaFco.QueryInterface(&metaSet));
02136 
02137         metaref_type mr = fco->GetRoleMetaRef();
02138         CString path;
02139         path.Format(_T("%d"), mr);
02140         CComBSTR bstr;
02141         CopyTo(path, bstr);
02142 
02143         VARIANT_BOOL ok = VARIANT_FALSE;
02144         COMTHROW(metaSet->CheckPath(bstr, &ok));
02145 
02146         return (ok != VARIANT_FALSE);
02147 }
02148 
02149 bool CGuiSet::ToggleMember(CGuiFco* member)
02150 {
02151         VERIFY(mgaFco);
02152         CComPtr<IMgaSet> mgaSet;
02153         COMTHROW(mgaFco.QueryInterface(&mgaSet));
02154         POSITION pos = members.Find(member);
02155         if(pos) {
02156                 COMTHROW(mgaSet->RemoveMember(member->mgaFco));
02157         }
02158         else {
02159                 COMTHROW(mgaSet->AddMember(member->mgaFco));
02160         }
02161         return pos == 0;
02162 }
02163 
02164 
02166 // Static methods of CGuiSet
02168 
02170 // Virtual methods of CGuiSet
02172 
02174 
02175 CGuiConnectionLabel::CGuiConnectionLabel():
02176         alignment(TA_BASELINE | TA_CENTER),
02177         primary(false)
02178 {
02179 }
02180 
02181 CGuiConnectionLabel::~CGuiConnectionLabel()
02182 {
02183 }
02184 
02185 void CGuiConnectionLabel::SetLabel(const CString& l)
02186 {
02187         label = l;
02188 }
02189 
02190 void CGuiConnectionLabel::SetPrimary(bool prim)
02191 {
02192         primary = prim;
02193 }
02194 
02195 void CGuiConnectionLabel::SetLocation(const CPoint& endPoint, const CPoint& nextPoint, const CRect& box)
02196 {
02197         if (label.IsEmpty())
02198                 return;
02199 
02200         int diffx = 3;
02201         int diffy = 3;
02202         BOOL f_center = box.IsRectNull();
02203 
02204         loc = endPoint;
02205         CPoint center = box.CenterPoint();
02206 
02207         bool skew = (endPoint.x != nextPoint.x && endPoint.y != nextPoint.y);
02208         double alpha = 0.0;
02209         bool moreVerticalThanHorizontal = true;
02210         if (skew) {
02211                 alpha = atan2(-((double)nextPoint.y - endPoint.y), (double)nextPoint.x - endPoint.x);
02212                 moreVerticalThanHorizontal = (alpha >= -3 * M_PI_4 && alpha < -M_PI_4) || (alpha < 3 * M_PI_4 && alpha >= M_PI_4);
02213         }
02214         RoutingDirection lineDir = Dir_None;
02215         if (!f_center)
02216                 lineDir = PointOnSide(endPoint, box);
02217 
02218         if (f_center)
02219         {
02220                 if (endPoint.x == nextPoint.x || skew && moreVerticalThanHorizontal)    // vertical line
02221                 {
02222                         alignment = TA_BASELINE | (primary ? TA_RIGHT : TA_LEFT);
02223                         loc.x += primary ? -diffx : diffx;
02224                 }
02225                 else if (endPoint.y == nextPoint.y || skew && !moreVerticalThanHorizontal)      // horizontal line
02226                 {
02227                         alignment = TA_CENTER | (primary ? TA_BOTTOM : TA_TOP);
02228                 }
02229                 else
02230                 {
02231                         ASSERT(false);
02232                 }
02233         }
02234         else
02235         {
02236                 switch(lineDir) {
02237                         case Dir_Top:   // up
02238                                 {
02239                                         loc.y -= diffy;
02240                                         loc.x += primary ? -diffx : diffx;
02241                                         alignment = TA_BOTTOM | (primary ? TA_RIGHT : TA_LEFT);
02242                                 }
02243                                 break;
02244                         case Dir_Bottom:        // down
02245                                 {
02246                                         loc.y += diffy;
02247                                         loc.x += primary ? -diffx : diffx;
02248                                         alignment = TA_TOP | (primary ? TA_RIGHT : TA_LEFT);
02249                                 }
02250                                 break;
02251                         case Dir_Left:          // left
02252                                 {
02253                                         loc.x -= diffx;
02254                                         alignment = TA_RIGHT | (primary ? TA_BOTTOM : TA_TOP);
02255                                 }
02256                                 break;
02257                         default:
02258                                 ASSERT(false);
02259                         case Dir_Skew:  // TODO?
02260                         case Dir_Right:         // right
02261                                 {
02262                                         loc.x += diffx;
02263                                         alignment = TA_LEFT | (primary ? TA_BOTTOM : TA_TOP);
02264                                 }
02265                                 break;
02266                 }
02267         }
02268 }
02269 
02270 void CGuiConnectionLabel::Draw(Gdiplus::Graphics* gdip, COLORREF color, CGuiConnection* conn)
02271 {
02272         if (label.IsEmpty())
02273                 return;
02274 
02275         label.Replace(_T("%name%"), conn->name);
02276         label.Replace(_T("%kind%"), conn->kindDisplayedName);
02277         label.Replace(_T("%role%"), conn->roleDisplayedName);
02278 
02279         CGuiMetaAttributeList *metaAttrs = conn->GetMetaAttributes();
02280         POSITION pos = metaAttrs->GetHeadPosition();
02281         while (pos) {
02282                 CGuiMetaAttribute *metaAttr = metaAttrs->GetNext(pos);
02283                 CString attrName;
02284                 attrName += _T("%");
02285                 attrName += metaAttr->name;
02286                 attrName += _T("%");
02287                 label.Replace(attrName, conn->attributeCache[metaAttr->name]);
02288         }
02289 
02290         if (label.IsEmpty())
02291                 return;
02292         graphics.DrawGdipText(gdip, label, loc, graphics.GetGdipFont(GME_CONNLABEL_FONT), color, alignment);
02293 }
02294 
02295 CPoint CGuiConnectionLabel::GetLocation(void) const
02296 {
02297         return loc;
02298 }
02299 
02300 int CGuiConnectionLabel::GetAlignment(void) const
02301 {
02302         return alignment;
02303 }
02304 
02305 CString CGuiConnectionLabel::GetLabel(void) const
02306 {
02307         return label;
02308 }
02309 
02311 
02312 CGuiConnectionLabelSet::CGuiConnectionLabelSet()
02313 {
02314         labels[GME_CONN_SRC_LABEL1].SetPrimary(false);
02315         labels[GME_CONN_SRC_LABEL2].SetPrimary(true);
02316         labels[GME_CONN_DST_LABEL1].SetPrimary(false);
02317         labels[GME_CONN_DST_LABEL2].SetPrimary(true);
02318         labels[GME_CONN_MAIN_LABEL].SetPrimary(true);
02319 }
02320 
02321 CGuiConnectionLabelSet::~CGuiConnectionLabelSet()
02322 {
02323 }
02324 
02325 void CGuiConnectionLabelSet::SetLabel(int index, const CString& label)
02326 {
02327         if (index < 0 || index >= GME_CONN_LABEL_NUM)
02328                 return;
02329         labels[index].SetLabel(label);
02330 }
02331 
02332 void CGuiConnectionLabelSet::SetLocation(int index, const CPoint& endPoint, const CPoint& nextPoint, const CRect& box)
02333 {
02334         if (index < 0 || index >= GME_CONN_LABEL_NUM)
02335                 return;
02336         labels[index].SetLocation(endPoint, nextPoint, box);
02337 }
02338 
02339 void CGuiConnectionLabelSet::Draw(Gdiplus::Graphics* gdip, COLORREF color, CGuiConnection* conn)
02340 {
02341         for(int i = 0; i < GME_CONN_LABEL_NUM; i++)
02342                 labels[i].Draw(gdip, color, conn);
02343 }
02344 
02345 CPoint CGuiConnectionLabelSet::GetLocation(int index) const
02346 {
02347         CPoint pt(-1, -1);
02348         if (index >= 0 && index < GME_CONN_LABEL_NUM)
02349                 pt = labels[index].GetLocation();
02350         return pt;
02351 }
02352 
02353 int CGuiConnectionLabelSet::GetAlignment(int index) const
02354 {
02355         int alignment = 0;
02356         if (index >= 0 && index < GME_CONN_LABEL_NUM)
02357                 alignment = labels[index].GetAlignment();
02358         return alignment;
02359 }
02360 
02361 CString CGuiConnectionLabelSet::GetLabel(int index) const
02362 {
02363         CString label;
02364         if (index >= 0 && index < GME_CONN_LABEL_NUM)
02365                 label = labels[index].GetLabel();
02366         return label;
02367 }
02368 
02369 
02371 
02373 // Non-virtual methods of CGuiConnection
02375 
02376 CGuiConnection::CGuiConnection(CComPtr<IMgaFCO>& pt, CComPtr<IMgaMetaRole>& role, CGMEView* vw, int numAsp, bool resolve):
02377         CGuiFco(pt, role, vw, numAsp),
02378         src                                             (NULL),
02379         srcPort                                 (NULL),
02380         dst                                             (NULL),
02381         dstPort                                 (NULL),
02382         hovered                                 (false),
02383         selected                                (false),
02384         connRegAutoRouteNotSet  (true),
02385         isAutoRouted                    (theApp.useAutoRouting)
02386 {
02387         routerPath = NULL;
02388 
02389         if (resolve)
02390                 Resolve();
02391 
02392         {
02393                 CString pref;
02394                 GetPreference(pref, CONN_LINE_TYPE_PREF);
02395                 lineType = (pref == _T("dash")) ? GME_LINE_DASH : GME_LINE_SOLID;
02396         }
02397         {
02398                 CString pref;
02399                 GetPreference(pref, CONN_SRC_END_STYLE_PREF);
02400                 if ( pref == _T("arrow") )
02401                         srcStyle = GME_ARROW_END;
02402                 else if ( pref == _T("diamond") )
02403                         srcStyle = GME_DIAMOND_END;
02404                 else if ( pref == _T("empty diamond") )
02405                         srcStyle = GME_EMPTYDIAMOND_END;
02406                 else if ( pref == _T("apex") )
02407                         srcStyle = GME_APEX_END;
02408                 else if ( pref == _T("empty apex") )
02409                         srcStyle = GME_EMPTYAPEX_END;
02410                 else if ( pref == _T("bullet") )
02411                         srcStyle = GME_BULLET_END;
02412                 else if ( pref == _T("empty bullet") )
02413                         srcStyle = GME_EMPTYBULLET_END;
02414                 else if ( pref == _T("left half arrow") )
02415                         srcStyle = GME_HALFARROWLEFT_END;
02416                 else if ( pref == _T("right half arrow") )
02417                         srcStyle = GME_HALFARROWRIGHT_END;
02418                 else
02419                         srcStyle = GME_BUTT_END;
02420         }
02421         {
02422                 CString pref;
02423                 GetPreference(pref, CONN_DST_END_STYLE_PREF);
02424                 if ( pref == _T("arrow") )
02425                         dstStyle = GME_ARROW_END;
02426                 else if ( pref == _T("diamond") )
02427                         dstStyle = GME_DIAMOND_END;
02428                 else if ( pref == _T("empty diamond") )
02429                         dstStyle = GME_EMPTYDIAMOND_END;
02430                 else if ( pref == _T("apex") )
02431                         dstStyle = GME_APEX_END;
02432                 else if ( pref == _T("empty apex") )
02433                         dstStyle = GME_EMPTYAPEX_END;
02434                 else if ( pref == _T("bullet") )
02435                         dstStyle = GME_BULLET_END;
02436                 else if ( pref == _T("empty bullet") )
02437                         dstStyle = GME_EMPTYBULLET_END;
02438                 else if ( pref == _T("left half arrow") )
02439                         dstStyle = GME_HALFARROWLEFT_END;
02440                 else if ( pref == _T("right half arrow") )
02441                         dstStyle = GME_HALFARROWRIGHT_END;
02442                 else
02443                         dstStyle = GME_BUTT_END;
02444         }
02445 
02446         {
02447                 ReadARPreferences();
02448         }
02449         {
02450                 CString pref;
02451 
02452                 GetPreference(pref,CONN_LABEL_FORMATSTR_PREF);
02453                 labelset.SetLabel(GME_CONN_MAIN_LABEL, pref);
02454                 GetPreference(pref,CONN_SRC_LABEL1_PREF);
02455                 labelset.SetLabel(GME_CONN_SRC_LABEL1, pref);
02456                 GetPreference(pref,CONN_SRC_LABEL2_PREF);
02457                 labelset.SetLabel(GME_CONN_SRC_LABEL2, pref);
02458                 GetPreference(pref,CONN_DST_LABEL1_PREF);
02459                 labelset.SetLabel(GME_CONN_DST_LABEL1, pref);
02460                 GetPreference(pref,CONN_DST_LABEL2_PREF);
02461                 labelset.SetLabel(GME_CONN_DST_LABEL2, pref);
02462         }
02463         if (!GetColorPreference(color, COLOR_PREF)) {
02464                 color = GME_BLACK_COLOR;
02465         }
02466         if (!GetColorPreference(nameColor, NAME_COLOR_PREF)) {
02467                 nameColor = GME_BLACK_COLOR;
02468         }
02469         ReadCustomPathData();
02470         SetAutoRouted(ReadAutoRouteState());
02471         RefreshAttributeCache();
02472 }
02473 
02474 void CGuiConnection::GiveConnectionEndErroMessage(const TCHAR* mainMsg, const TCHAR* srcOrDst, const CGuiPort* otherPort) const
02475 {
02476         if (!view->ShouldSupressConnectionCheckAlert()) {
02477                 CString msgEx;
02478                 msgEx.Append(_T("Connection properties:\n"));
02479                 msgEx.Append(_T("\nName: "));
02480                 msgEx.Append(name);
02481                 msgEx.Append(_T("\nKind Name: "));
02482                 msgEx.Append(kindDisplayedName);
02483                 msgEx.Append(_T("\nRole Name: "));
02484                 msgEx.Append(roleDisplayedName);
02485                 msgEx.Append(_T("\nID: "));
02486                 msgEx.Append(id);
02487                 msgEx.Append(_T("\nDirection: "));
02488                 msgEx.Append(srcOrDst);
02489                 msgEx.Append(_T("\nOther endpoint properties:"));
02490                 if (otherPort) {
02491                         msgEx.Append(_T("\n\tName: "));
02492                         msgEx.Append(otherPort->name);
02493                         msgEx.Append(_T("\n\tID: "));
02494                         msgEx.Append(otherPort->id);
02495                 } else {
02496                         msgEx.Append(_T("\n\tOther Endpoint is also null."));
02497                 }
02498                 msgEx.Append(_T("\nMissing endpoints sometimes can be generated by UDM based interpreters."));
02499                 msgEx.Append(_T("\nCancel button supress further connection error messages like this."));
02500                 int retVal = view->MessageBox(msgEx, mainMsg, MB_OKCANCEL | MB_ICONERROR);
02501                 if (retVal == IDCANCEL)
02502                         view->SupressConnectionCheckAlert();
02503         }
02504 }
02505 
02506 void CGuiConnection::Resolve()
02507 {
02508         try {
02509                 view->BeginTransaction(TRANSACTION_READ_ONLY);
02510                 CComPtr<IMgaSimpleConnection> conn;
02511                 mgaFco.QueryInterface(&conn);
02512                 VERIFY(conn);
02513 
02514                 // Compute visibility
02515                 visible = std::unique_ptr<bool[]>(new bool[numParentAspects]);
02516                 memset(visible.get(), 0, numParentAspects * sizeof(bool));
02517                 CComPtr<IMgaMetaParts> mmParts;
02518                 COMTHROW(metaRole->get_Parts(&mmParts));
02519                 MGACOLL_ITERATE(IMgaMetaPart,mmParts) {
02520                         CComPtr<IMgaMetaPart> mmPart;
02521                         mmPart = MGACOLL_ITER;
02522                         CComPtr<IMgaMetaAspect> mmAspect;
02523                         COMTHROW(mmPart->get_ParentAspect(&mmAspect));
02524                         CComBSTR bstr;
02525                         COMTHROW(mmAspect->get_Name(&bstr));
02526                         CString aspName;
02527                         CopyTo(bstr,aspName);
02528                         CGuiMetaAspect *guiMetaAsp = view->guiMeta->FindAspect(aspName);
02529                         VERIFY(guiMetaAsp);
02530                         VERIFY(guiMetaAsp->index < numParentAspects);
02531                         visible[guiMetaAsp->index] = true;
02532                 }
02533                 MGACOLL_ITERATE_END;
02534                 
02535                 srcPort = NULL;
02536                 dstPort = NULL;
02537                 if(visible[parentAspect]) {
02538                         CComPtr<IMgaFCO> mgaSrc;
02539 
02540                         // Lookup first conn. reference first
02541                         CComPtr<IMgaFCOs> mgaSrcRefs;
02542                         bool src_err = false;
02543                         HRESULT src_hr = S_OK;
02544                         {
02545                                 try {
02546                                         src_hr = conn->get_SrcReferences(&mgaSrcRefs);
02547                                 }
02548                                 catch(hresult_exception &e)
02549                                 {
02550                                         ASSERT(FAILED(e.hr));
02551                                         SetErrorInfo(e.hr);
02552                                         src_hr = e.hr;
02553                                 }
02554                         }
02555                         if (SUCCEEDED(src_hr) || mgaSrcRefs) {
02556                                 long nSrcRef = 0;
02557                                 COMTHROW(mgaSrcRefs->get_Count(&nSrcRef));
02558                                 if (nSrcRef > 0) {
02559                                         COMTHROW(mgaSrcRefs->get_Item(1, &mgaSrc));
02560                                 }
02561                                 else {
02562                                         COMTHROW(conn->get_Src(&mgaSrc));
02563                                 }
02564 
02565                                 POSITION pos = view->children.GetHeadPosition();
02566                                 while (pos) {
02567                                         CGuiFco* fco = view->children.GetNext(pos);
02568                                         ASSERT(fco != NULL);
02569                                         CGuiObject* srcObj = fco->dynamic_cast_CGuiObject();
02570                                         if (srcObj && srcObj->IsVisible()) {
02571                                                 srcPort = srcObj->FindPort(mgaSrc);
02572                                                 if (srcPort) {
02573                                                         CGuiCompoundReference* modelRefObj = srcObj->dynamic_cast_CGuiCompoundReference();
02574                                                         if (modelRefObj) {
02575                                                                 CComPtr<IMgaFCO> mgaSrcPort;
02576                                                                 COMTHROW(conn->get_Src(&mgaSrcPort));
02577                                                                 CGuiPort *srcFPort = srcObj->FindPort(mgaSrcPort);
02578                                                                 srcPort = srcFPort ? srcFPort : srcPort;
02579                                                                 if ((srcPort->IsRealPort()) && (!nSrcRef) ) {
02580                                                                         continue;
02581                                                                 }
02582                                                         }
02583                                                         src = srcPort->parent->GetParent();
02584                                                         VERIFY(src);
02585                                                         break;
02586                                                 }
02587                                         }
02588                                 }
02589                                 if (!srcPort) {
02590                                         visible[parentAspect] = false;
02591                                 }
02592                         } else {
02593                                 src_err = true;
02594                         }
02595 
02596                         CComPtr<IMgaFCO> mgaDst;
02597 
02598                         // Lookup first conn. reference first
02599                         HRESULT dst_hr = S_OK;
02600                         CComPtr<IMgaFCOs> mgaDstRefs;
02601                         bool dst_err = false;
02602                         {
02603                                 try {
02604                                         dst_hr = conn->get_DstReferences(&mgaDstRefs);
02605                                 }
02606                                 catch(hresult_exception &e)
02607                                 {
02608                                         ASSERT(FAILED(e.hr));
02609                                         SetErrorInfo(e.hr);
02610                                         dst_hr = e.hr;
02611                                 }
02612                         }
02613                         if (SUCCEEDED(dst_hr) && mgaDstRefs) {
02614                                 long nDstRef = 0;
02615                                 COMTHROW(mgaDstRefs->get_Count(&nDstRef));
02616                                 if (nDstRef > 0) {
02617                                         COMTHROW(mgaDstRefs->get_Item(1, &mgaDst));
02618                                 }
02619                                 else {
02620                                         COMTHROW(conn->get_Dst(&mgaDst));
02621                                 }
02622 
02623                                 POSITION pos = view->children.GetHeadPosition();
02624                                 while (pos) {
02625                                         CGuiFco* fco = view->children.GetNext(pos);
02626                                         ASSERT(fco != NULL);
02627                                         CGuiObject* dstObj = fco->dynamic_cast_CGuiObject();
02628                                         if (dstObj && dstObj->IsVisible()) {
02629                                                 dstPort = dstObj->FindPort(mgaDst);
02630                                                 if (dstPort) {
02631                                                         CGuiCompoundReference* modelRefObj = dstObj->dynamic_cast_CGuiCompoundReference();
02632                                                         if (modelRefObj) {
02633                                                                 CComPtr<IMgaFCO> mgaDstPort;
02634                                                                 COMTHROW(conn->get_Dst(&mgaDstPort));
02635                                                                 CGuiPort *dstFPort = dstObj->FindPort(mgaDstPort);
02636                                                                 dstPort = dstFPort ? dstFPort : dstPort;
02637                                                                 if ((dstPort->IsRealPort()) && (!nDstRef) ) {
02638                                                                         continue;
02639                                                                 }
02640                                                         }
02641                                                         dst = dstPort->parent->GetParent();
02642                                                         VERIFY(dst);
02643                                                         break;
02644                                                 }
02645                                         }
02646                                 }
02647                                 if (!dstPort) {
02648                                         visible[parentAspect] = false;
02649                                 }
02650                         } else {
02651                                 dst_err = true;
02652                         }
02653                         if (src_err || dst_err) {
02654                                 if (src_err) {
02655                                         GiveConnectionEndErroMessage(_T("Source endpoint error"), _T("src"), dstPort);
02656                                 } else if (dst_err) {
02657                                         GiveConnectionEndErroMessage(_T("Destination endpoint error"), _T("dst"), srcPort);
02658                                 }
02659                         } else
02660 
02661                         if (visible[parentAspect]) {
02662                                 if( !srcPort->outConns.Find( this)) // WAS: outConns.AddTail(this); and as a result as aspects have cycled the collection got bigger and bigger
02663                                         srcPort->outConns.AddTail(this);// NOW: added only if ptr was not already stored in outConns
02664                                 
02665                                 if( !dstPort->inConns.Find( this)) // WAS: inConns.AddTail(this);
02666                                         dstPort->inConns.AddTail(this);// NOW: added only if ptr was not already stored in inConns
02667                         }
02668 
02669                 }
02670                 view->CommitTransaction();
02671         }
02672         catch (hresult_exception e) {
02673                 view->AbortTransaction(e.hr);
02674         }
02675 }
02676 
02677 void CGuiConnection::Draw(HDC pDC, Gdiplus::Graphics* gdip)
02678 {
02679         if(!IsVisible())
02680                 return;
02681         if (!src || !dst)
02682                 return;
02683         VERIFY(src->IsVisible());
02684         VERIFY(dst->IsVisible());
02685 
02686         CPointList points;
02687         GetPointList(points);
02688 
02689         if (points.GetSize() <= 0) {
02690                 ASSERT(false);
02691                 return;
02692         }
02693 
02694         std::vector<long> customizedEdgeIndexes;
02695         if (selected && IsAutoRouted())
02696                 customizedEdgeIndexes = GetRelevantCustomizedEdgeIndexes();
02697         int width = selected ? 3 : hovered ? 5 : 1;
02698         if (selected && view->m_zoomVal < ZOOM_NO)
02699         {
02700                 // selection was hard to see at <100% zoom. Magic numbers determined by experimentation
02701                 width = (int)((float)((ZOOM_NO - 25) / max(10, view->m_zoomVal) + 0.2) * width + 0.5f);
02702         }
02703         graphics.DrawConnection(gdip, points, customizedEdgeIndexes, grayedOut ? GME_GRAYED_OUT_COLOR : color,
02704                                                         lineType, srcStyle, dstStyle, view->m_zoomVal > ZOOM_NO, !IsAutoRouted() && selected,
02705                                                         width);
02706 
02707         if (points.GetSize() < 2) {
02708                 ASSERT(false);
02709                 return;
02710         }
02711 
02712         POSITION pos = points.GetHeadPosition();
02713         CPoint start = points.GetNext(pos);
02714         CPoint start2 = points.GetNext(pos);
02715         pos = points.GetTailPosition();
02716         CPoint end = points.GetPrev(pos);
02717         CPoint end2 = points.GetPrev(pos);
02718 
02719         // Get the center position of the whole connection
02720 
02721         int segments = points.GetCount();
02722         pos = points.FindIndex((int)(segments/2)-1);
02723         CPoint middle = points.GetNext(pos);
02724         CPoint middle2 = points.GetNext(pos);
02725         CRect tmpRect(middle, middle2);
02726         middle = tmpRect.CenterPoint();
02727 
02728         const CRect srcRect = src->GetLocation();
02729         const CRect dstRect = dst->GetLocation();
02730 
02731         CRect box;
02732         box = src->GetLocation();
02733         if (srcPort != NULL && srcPort->IsRealPort())
02734                 box = srcPort->GetLocation() + box.TopLeft();
02735         labelset.SetLocation(0, start, start2, box);
02736         labelset.SetLocation(1, start, start2, box);
02737         box = dst->GetLocation();
02738         if (dstPort != NULL && dstPort->IsRealPort())
02739                 box = dstPort->GetLocation() + box.TopLeft();
02740         labelset.SetLocation(2, end, end2, box);
02741         labelset.SetLocation(3, end, end2, box);
02742         box = CRect(0, 0, 0, 0);
02743         labelset.SetLocation(GME_CONN_MAIN_LABEL, middle, middle2, box);
02744 
02745 
02746         labelset.Draw(gdip, (grayedOut ? GME_GRAYED_OUT_COLOR : nameColor), this);
02747 }
02748 
02749 void CGuiConnection::RemoveFromRouter(CAutoRouter &router)
02750 {
02751         router.DeleteConnection(this);
02752 }
02753 
02754 void CGuiConnection::GrayOutEndPoints()
02755 {
02756         src->GrayOut(grayedOut);
02757         dst->GrayOut(grayedOut);
02758 }
02759 
02760 void CGuiConnection::RefreshAttributeCache()
02761 {
02762         attributeCache.RemoveAll();
02763 
02764         CGuiMetaAttributeList* guiMetaAttrs = GetMetaAttributes();
02765         POSITION pos = guiMetaAttrs->GetHeadPosition();
02766 
02767         while (pos) {
02768                 CGuiMetaAttribute* guiMetaAttr = guiMetaAttrs->GetNext(pos);
02769                 CComPtr<IMgaAttribute> attr;
02770                 CComPtr<IMgaMetaAttribute> metaAttr;
02771                 attval_enum     tp;
02772                 COMTHROW(guiMetaAttr->mgaMeta.QueryInterface(&metaAttr));
02773                 COMTHROW(metaAttr->get_ValueType(&tp));
02774                 COMTHROW(mgaFco->get_Attribute(metaAttr, &attr));
02775                 CComVariant     attrValue;
02776                 COMTHROW(attr->get_Value(&attrValue));
02777 
02778                 CString aval;
02779                 CString aname = guiMetaAttr->name;
02780 
02781                 if (tp == ATTVAL_BOOLEAN) {
02782                         VERIFY(attrValue.vt == VT_BOOL);
02783                         aval = attrValue.boolVal ? _T("True") : _T("False");
02784                 }
02785                 else if (tp == ATTVAL_REFERENCE) {
02786                         aval = _T("Reference attr. label not supported");       // Sorry, maybe later
02787                 }
02788                 else if (tp == _attval_enum) {
02789                         VERIFY(attrValue.vt == VT_BSTR);
02790                         CString attrValueStr(attrValue.bstrVal);
02791                         /* CGuiMenuCtrl *guiMenuCtrl = dynamic_cast<CGuiMenuCtrl *>(guiMetaAttr->depCtrl);
02792                         if (guiMenuCtrl) {
02793                                 aval = attrValue.bstrVal;
02794                                 int idx = guiMenuCtrl->FindItemByValue(aval);
02795                                 if (idx != -1)
02796                                         aval = (guiMenuCtrl->items[idx]).label;
02797                                 else
02798                                         aval = _T("N/A");
02799                         }
02800                         else {
02801                                 aval = _T("N/A");
02802                         } */
02803                         aval = _T("N/A");
02804                         CComPtr<IMgaMetaEnumItems> metaEnumItems;
02805                         COMTHROW(metaAttr->get_EnumItems(&metaEnumItems));
02806 
02807                         MGACOLL_ITERATE(IMgaMetaEnumItem,metaEnumItems)
02808                         {
02809                                 CComBSTR bstrItemLabel;
02810                                 CComBSTR bstrItemValue;
02811                                 COMTHROW(MGACOLL_ITER->get_DisplayedName(&bstrItemLabel));
02812                                 COMTHROW(MGACOLL_ITER->get_Value(&bstrItemValue));
02813 
02814                                 CString strItemValue(bstrItemValue);
02815                                 if (strItemValue == attrValueStr) {
02816                                         aval = bstrItemLabel;
02817                                 }
02818                         }
02819                         MGACOLL_ITERATE_END;
02820 
02821                 }
02822                 else {
02823                         if (attrValue.vt != VT_BSTR)
02824                                 attrValue.ChangeType(VT_BSTR);
02825                         aval = attrValue.bstrVal;
02826                 }
02827                 attributeCache[aname] = aval;
02828         }
02829 }
02830 
02831 void CGuiConnection::ReadARPreferences()
02832 {
02833         CString val;
02834         if (GetPreference(val, AUTOROUTER_PREF)) {
02835                 autorouterPrefs[GME_START_NORTH]        = (val.Find(_T("N")) != -1);
02836                 autorouterPrefs[GME_START_EAST]         = (val.Find(_T("E")) != -1);
02837                 autorouterPrefs[GME_START_SOUTH]        = (val.Find(_T("S")) != -1);
02838                 autorouterPrefs[GME_START_WEST]         = (val.Find(_T("W")) != -1);
02839                 autorouterPrefs[GME_END_NORTH]          = (val.Find(_T("n")) != -1);
02840                 autorouterPrefs[GME_END_EAST]           = (val.Find(_T("e")) != -1);
02841                 autorouterPrefs[GME_END_SOUTH]          = (val.Find(_T("s")) != -1);
02842                 autorouterPrefs[GME_END_WEST]           = (val.Find(_T("w")) != -1);
02843         } else {
02844                 autorouterPrefs[GME_START_NORTH]        = false;
02845                 autorouterPrefs[GME_START_EAST]         = false;
02846                 autorouterPrefs[GME_START_SOUTH]        = false;
02847                 autorouterPrefs[GME_START_WEST]         = false;
02848                 autorouterPrefs[GME_END_NORTH]          = false;
02849                 autorouterPrefs[GME_END_EAST]           = false;
02850                 autorouterPrefs[GME_END_SOUTH]          = false;
02851                 autorouterPrefs[GME_END_WEST]           = false;
02852         }
02853 }
02854 
02855 void CGuiConnection::GetPointList(CPointList& points) const
02856 {
02857         if (routerPath != NULL)
02858         {
02859                 CPointListPath& pointList = routerPath->GetPointList();
02860                 POSITION pos = pointList.GetHeadPosition();
02861                 while( pos != NULL )
02862                 {
02863                         points.AddTail(pointList.GetNext(pos));
02864                 }
02865         }
02866 
02867         if (!routerPath || points.GetSize() <= 0)
02868         {
02869                 if (srcPort != NULL) {
02870                         CPoint start = srcPort->GetLocation().CenterPoint() + src->GetLocation().TopLeft();
02871                         points.AddHead(start);
02872                 }
02873                 if (dstPort != NULL) {
02874                         CPoint end = dstPort->GetLocation().CenterPoint() + dst->GetLocation().TopLeft();
02875                         points.AddTail(end);
02876                 }
02877         }
02878 }
02879 
02880 int CGuiConnection::GetEdgeCount(void) const
02881 {
02882         CPointList points;
02883         GetPointList(points);
02884         return points.GetSize() - 1;
02885 }
02886 
02887 CRect CGuiConnection::GetBounds(void) const
02888 {
02889         CPointList points;
02890         GetPointList(points);
02891 
02892         POSITION pos = points.GetHeadPosition();
02893         long xmin = LONG_MAX;
02894         long xmax = LONG_MIN;
02895         long ymin = LONG_MAX;
02896         long ymax = LONG_MIN;
02897         CRect bounds;
02898         bounds.SetRectEmpty();
02899         if (pos) {
02900                 while (pos) {
02901                         CPoint& pt = points.GetNext(pos);
02902                         if (pt.x > xmax)
02903                                 xmax = pt.x;
02904                         if (pt.x < xmin)
02905                                 xmin = pt.x;
02906                         if (pt.y > ymax)
02907                                 ymax = pt.y;
02908                         if (pt.y < ymin)
02909                                 ymin = pt.y;
02910                 }
02911                 bounds = CRect(xmin, ymin, xmax, ymax);
02912         }
02913 
02914         return bounds;
02915 }
02916 
02917 CPoint CGuiConnection::GetCenter(void) const
02918 {
02919         CRect bounds = GetBounds();
02920         return bounds.CenterPoint();
02921 }
02922 
02923 bool CGuiConnection::AdjustCoordLimits(CPointList& points, int edgeIndex, bool isPathEnd, bool xOrY, POSITION pos,
02924                                                                            int ptCoord, int lastlastCoord, long& coordMinLimit, long& coordMaxLimit) const
02925 {
02926         if (!isPathEnd) {
02927                 // Internal edge
02928                 CPoint nextPt = points.GetNext(pos);
02929                 int nextPtCoord = xOrY ? nextPt.x : nextPt.y;
02930                 if (ptCoord < nextPtCoord && ptCoord < lastlastCoord)
02931                         coordMinLimit = LONG_MIN;
02932                 else
02933                         coordMinLimit = min(nextPtCoord, lastlastCoord);
02934                 if (ptCoord > nextPtCoord && ptCoord > lastlastCoord)
02935                         coordMaxLimit = LONG_MAX;
02936                 else
02937                         coordMaxLimit = max(nextPtCoord, lastlastCoord);
02938         } else {
02939                 // Inspect entities at the end to calculate limits
02940                 CRect portRect;
02941                 portRect.SetRectEmpty();
02942                 if (edgeIndex == 0) {
02943                         if (srcPort != NULL && srcPort->IsRealPort()) {
02944                                 return true;
02945                         } else if (src != NULL) {
02946                                 portRect = src->GetLocation();
02947                         }
02948                 } else {
02949                         if (dstPort != NULL && dstPort->IsRealPort()) {
02950                                 return true;
02951                         } else if (dst != NULL) {
02952                                 portRect = dst->GetLocation();
02953                         }
02954                 }
02955 
02956                 if (!portRect.IsRectEmpty()) {
02957                         if (xOrY) {
02958                                 coordMinLimit = portRect.left;
02959                                 coordMaxLimit = portRect.right;
02960                         } else {
02961                                 coordMinLimit = portRect.top;
02962                                 coordMaxLimit = portRect.bottom;
02963                         }
02964                 } else {
02965                         ASSERT(false);
02966                         return true;
02967                 }
02968         }
02969 
02970         return false;
02971 }
02972 
02973 int CGuiConnection::GetEdgeIndex(const CPoint& point, CPoint& startPoint, CPoint& endPoint, CPoint& thirdPoint,
02974                                                                  ConnectionPartMoveType& connectionMoveMethod, bool& horizontalOrVerticalEdge,
02975                                                                  bool& isPartFixed, long& xMinLimit, long& xMaxLimit, long& yMinLimit, long& yMaxLimit,
02976                                                                  bool checkPointOnEdge) const
02977 {
02978         CPointList points;
02979         GetPointList(points);
02980 
02981         int numEdges = points.GetSize() - 1;
02982         if (numEdges == -1 || routerPath == NULL)
02983                 return -1;
02984         CPoint last = emptyPoint;
02985         CPoint lastlast = emptyPoint;
02986         POSITION pos = points.GetHeadPosition();
02987         int i = 0;
02988         CAutoRouterGraph* ag = routerPath->GetOwner();
02989         ASSERT(ag != NULL);
02990         if (pos) {
02991                 CPoint pt = points.GetNext(pos);
02992                 last = pt;
02993                 while (pos) {
02994                         pt = points.GetNext(pos);
02995                         if (IsAutoRouted()) {
02996                                 bool moveAction = false;
02997                                 if (last.x == pt.x) {   // vertical edge, horizontal move
02998                                         if (abs(pt.x - point.x) <= 3 &&
02999                                                 (point.y >= min(last.y, pt.y) - 3 ||
03000                                                  point.y <= max(last.y, pt.y) + 3))
03001                                         {
03002                                                 connectionMoveMethod = HorizontalEdgeMove;
03003                                                 horizontalOrVerticalEdge = false;
03004                                                 moveAction = true;
03005                                         }
03006                                 } else if (last.y == pt.y) {    // horizontal line, vertical move
03007                                         if (abs(pt.y - point.y) <= 3 &&
03008                                                 (point.x >= min(last.x, pt.x) - 3 ||
03009                                                  point.x <= max(last.x, pt.x) + 3))
03010                                         {
03011                                                 connectionMoveMethod = VerticalEdgeMove;
03012                                                 horizontalOrVerticalEdge = true;
03013                                                 moveAction = true;
03014                                         }
03015                                 } else {
03016                                         // There mustn't be any skew edge in case of auto routed connection
03017                                         ASSERT(false);
03018                                 }
03019                                 if (i < numEdges - 1 &&         // We can't drag two connected edges at the last point!
03020                                         abs(pt.x - point.x) <= 3 &&
03021                                         abs(pt.y - point.y) <= 3)
03022                                 {
03023                                         connectionMoveMethod = AdjacentEdgeMove;
03024                                 }
03025                                 if (moveAction) {
03026                                         isPartFixed = ag->IsEdgeFixed(routerPath, last, pt);
03027 
03028                                         startPoint = last;
03029                                         endPoint = pt;
03030                                         bool isPathEnd = (i == 0 || i == numEdges - 1);
03031 
03032                                         bool isPartFixed2 = false;
03033                                         bool pointOnEdge = false;
03034                                         if (connectionMoveMethod == HorizontalEdgeMove) {
03035                                                 isPartFixed2 = AdjustCoordLimits(points, i, isPathEnd, true, pos,
03036                                                                                                                  pt.x, lastlast.x, xMinLimit, xMaxLimit);
03037                                                 if (checkPointOnEdge)
03038                                                         pointOnEdge = point.y >= min(startPoint.y, endPoint.y) - 3 && point.y <= max(startPoint.y, endPoint.y) + 3;
03039                                         } else if (connectionMoveMethod == VerticalEdgeMove) {
03040                                                 isPartFixed2 = AdjustCoordLimits(points, i, isPathEnd, false, pos,
03041                                                                                                                  pt.y, lastlast.y, yMinLimit, yMaxLimit);
03042                                                 if (checkPointOnEdge)
03043                                                         pointOnEdge = point.x >= min(startPoint.x, endPoint.x) - 3 && point.x <= max(startPoint.x, endPoint.x) + 3;
03044                                         } else  if (connectionMoveMethod == AdjacentEdgeMove) {
03045                                                 POSITION nextPos = pos;
03046                                                 CPoint nextPt = points.GetNext(nextPos);
03047                                                 thirdPoint = nextPt;
03048                                                 if (horizontalOrVerticalEdge) {
03049                                                         isPartFixed2 = AdjustCoordLimits(points, i, isPathEnd, false, pos,
03050                                                                                                                          pt.y, lastlast.y, yMinLimit, yMaxLimit);
03051                                                         if (checkPointOnEdge)
03052                                                                 pointOnEdge = point.x >= min(startPoint.x, endPoint.x) - 3 && point.x <= max(startPoint.x, endPoint.x) + 3;
03053                                                         if (isPartFixed2) {
03054                                                                 connectionMoveMethod = HorizontalEdgeMove;
03055                                                                 isPartFixed2 = false;
03056                                                         }
03057                                                         isPartFixed2 = AdjustCoordLimits(points, i + 1, i >= numEdges - 2, true, nextPos,
03058                                                                                                                          nextPt.x, last.x, xMinLimit, xMaxLimit);
03059                                                         if (checkPointOnEdge)
03060                                                                 pointOnEdge = pointOnEdge && (point.y >= min(endPoint.y, nextPt.y) - 3 && point.y <= max(endPoint.y, nextPt.y) + 3);
03061                                                         if (isPartFixed2) {
03062                                                                 if (connectionMoveMethod != HorizontalEdgeMove) {
03063                                                                         connectionMoveMethod = VerticalEdgeMove;
03064                                                                         isPartFixed2 = false;
03065                                                                 }
03066                                                         }
03067                                                 } else {
03068                                                         isPartFixed2 = AdjustCoordLimits(points, i, isPathEnd, true, pos,
03069                                                                                                                          pt.x, lastlast.x, xMinLimit, xMaxLimit);
03070                                                         if (checkPointOnEdge)
03071                                                                 pointOnEdge = point.y >= min(startPoint.y, endPoint.y) - 3 && point.y <= max(startPoint.y, endPoint.y) + 3;
03072                                                         if (isPartFixed2) {
03073                                                                 connectionMoveMethod = VerticalEdgeMove;
03074                                                                 isPartFixed2 = false;
03075                                                         }
03076                                                         isPartFixed2 = AdjustCoordLimits(points, i + 1, i >= numEdges - 2, false, nextPos,
03077                                                                                                                          nextPt.y, last.y, yMinLimit, yMaxLimit);
03078                                                         if (checkPointOnEdge)
03079                                                                 pointOnEdge = pointOnEdge && (point.x >= min(endPoint.x, nextPt.x) - 3 && point.x <= max(endPoint.x, nextPt.x) + 3);
03080                                                         if (isPartFixed2) {
03081                                                                 if (connectionMoveMethod != VerticalEdgeMove) {
03082                                                                         connectionMoveMethod = HorizontalEdgeMove;
03083                                                                         isPartFixed2 = false;
03084                                                                 }
03085                                                         }
03086                                                 }
03087                                         }
03088                                         isPartFixed |= isPartFixed2;
03089 
03090                                         if (!checkPointOnEdge || pointOnEdge)
03091                                                 return i;
03092                                 }
03093                         } else {
03094                                 if (abs(pt.x - point.x) <= 3 && abs(pt.y - point.y) <= 3) {
03095                                         startPoint = last;
03096                                         CPoint next = points.GetNext(pos);
03097                                         endPoint = next;
03098 
03099                                         connectionMoveMethod = ModifyExistingCustomPoint;
03100                                         isPartFixed = false;
03101                                         return i;
03102                                 } else {
03103                                         if (IsOnEdge(last, pt, point))
03104                                         {
03105                                                 startPoint = last;
03106                                                 endPoint = pt;
03107 
03108                                                 connectionMoveMethod = InsertNewCustomPoint;
03109                                                 isPartFixed = false;
03110                                                 return i;
03111                                         }
03112                                 }
03113                         }
03114 
03115                         i++;
03116                         lastlast = last;
03117                         last = pt;
03118                 }
03119         }
03120 
03121         return -1;
03122 }
03123 
03124 int CGuiConnection::IsPathAt(const CPoint& point, ConnectionPartMoveType& connectionMoveMethod,
03125                                                          bool& horizontalOrVerticalEdge, bool& isPartFixed) const
03126 {
03127         CPoint customizeConnectionEdgeStartPoint;
03128         CPoint customizeConnectionEdgeEndPoint;
03129         CPoint customizeConnectionEdgeThirdPoint;
03130         long customizeConnectionEdgeXMinLimit;
03131         long customizeConnectionEdgeXMaxLimit;
03132         long customizeConnectionEdgeYMinLimit;
03133         long customizeConnectionEdgeYMaxLimit;
03134 
03135         return GetEdgeIndex(point, customizeConnectionEdgeStartPoint, customizeConnectionEdgeEndPoint, customizeConnectionEdgeThirdPoint,
03136                                                 connectionMoveMethod, horizontalOrVerticalEdge,
03137                                                 isPartFixed, customizeConnectionEdgeXMinLimit, customizeConnectionEdgeXMaxLimit,
03138                                                 customizeConnectionEdgeYMinLimit, customizeConnectionEdgeYMaxLimit);
03139 }
03140 
03141 long CGuiConnection::IsPointOnSectionAndDeletable(long edgeIndex, const CPoint& point)
03142 {
03143         CPointList points;
03144         GetPointList(points);
03145 
03146         CPoint last;
03147         CPoint lastlast;
03148         POSITION pos = points.GetHeadPosition();
03149         int i = 0;
03150         if (pos) {
03151                 CPoint pt = points.GetNext(pos);
03152                 last = pt;
03153                 while (pos) {
03154                         pt = points.GetNext(pos);
03155 
03156                         if (i == edgeIndex) {
03157                                 if (pos) {
03158                                         CPoint next = points.GetNext(pos);
03159 
03160                                         if (IsOnEdge(last, next, point, 5)) {
03161                                                 return i;
03162                                         }
03163                                 }
03164                                 return -1;
03165                         }
03166 
03167                         i++;
03168                         lastlast = last;
03169                         last = pt;
03170                 }
03171         }
03172 
03173         return -1;
03174 }
03175 
03176 std::vector<long> CGuiConnection::GetRelevantCustomizedEdgeIndexes(void)
03177 {
03178         int edgeCount = GetEdgeCount();
03179         long asp = view->currentAspect->index;
03180         std::vector<long> customizedEdgeIndexes;
03181         std::vector<CustomPathData>::iterator ii = customPathData.begin();
03182         while (ii != customPathData.end() && edgeCount > 0) {
03183                 if ((*ii).GetAspect() == asp || asp == -1) {
03184                         if (IsAutoRouted() && (*ii).GetType() == SimpleEdgeDisplacement && (*ii).GetEdgeCount() == edgeCount ||
03185                            !IsAutoRouted() && (*ii).GetType() != SimpleEdgeDisplacement)
03186                         {
03187                                 customizedEdgeIndexes.push_back((*ii).GetEdgeIndex());
03188                         }
03189                 }
03190                 ++ii;
03191         }
03192         return customizedEdgeIndexes;
03193 }
03194 
03195 void CGuiConnection::FillOutCustomPathData(CustomPathData& pathData, PathCustomizationType custType, long asp,
03196                                                                                    int newPosX, int newPosY, int edgeIndex, int edgeCount, bool horizontalOrVerticalEdge)
03197 {
03198         pathData.SetVersion                                     (CONNECTIONCUSTOMIZATIONDATAVERSION);
03199         pathData.SetAspect                                      (asp);
03200         pathData.SetEdgeIndex                           (edgeIndex);
03201         pathData.SetEdgeCount                           (edgeCount < 0 ? GetEdgeCount() : edgeCount);
03202         pathData.SetType                                        (custType);
03203         pathData.SetHorizontalOrVertical        (horizontalOrVerticalEdge);
03204         if (custType == SimpleEdgeDisplacement) {
03205                 pathData.SetX                                   (!horizontalOrVerticalEdge ? newPosX : 0);
03206                 pathData.SetY                                   (horizontalOrVerticalEdge ? newPosY : 0);
03207         } else {
03208                 pathData.SetX                                   (newPosX);
03209                 pathData.SetY                                   (newPosY);
03210         }
03211 }
03212 
03213 std::vector<CustomPathData> CGuiConnection::GetCurrentPathCustomizations(void)
03214 {
03215         std::vector<CustomPathData> cd;
03216         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03217                 if ((*ii).GetAspect() == parentAspect)
03218                         cd.push_back(*ii);
03219         }
03220         return cd;
03221 }
03222 
03223 bool CGuiConnection::HasPathCustomization(void) const
03224 {
03225         return customPathData.size() > 0;
03226 }
03227 
03228 bool CGuiConnection::HasPathCustomizationForCurrentAspect(int edgeIndex) const
03229 {
03230         return HasPathCustomizationForAspect(view->currentAspect->index, edgeIndex);
03231 }
03232 
03233 bool CGuiConnection::HasPathCustomizationForAspect(long asp, int edgeIndex) const
03234 {
03235         return HasPathCustomizationForTypeAndAspect(asp, Invalid, edgeIndex);
03236 }
03237 
03238 bool CGuiConnection::HasPathCustomizationForTypeAndCurrentAspect(PathCustomizationType custType, int edgeIndex) const
03239 {
03240         return HasPathCustomizationForTypeAndAspect(view->currentAspect->index, custType, edgeIndex);
03241 }
03242 
03243 bool CGuiConnection::HasPathCustomizationForTypeAndAspect(long asp, PathCustomizationType custType, int edgeIndex) const
03244 {
03245         for (std::vector<CustomPathData>::const_iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03246                 if ((*ii).GetAspect() == asp &&
03247                         ((*ii).GetEdgeIndex() == edgeIndex || edgeIndex == -1) &&
03248                         ((*ii).GetType() == custType || custType == Invalid))
03249                 {
03250                         return true;
03251                 }
03252         }
03253         return false;
03254 }
03255 
03256 void CGuiConnection::ReadCustomPathData(void)
03257 {
03258         customPathData.clear();
03259         CString pref;
03260         if (GetPreference(pref, CUSTOMCONNECTIONDATA)) {
03261                 if (pref != EMPTYCONNECTIONCUSTOMIZATIONDATAMAGIC) {    // -1 is a magic number for deleted data
03262                         CString subStr;
03263                         int curPos = 0;
03264                         subStr = pref.Tokenize(_T(";"), curPos);
03265                         while (subStr != _T("")) {
03266                                 CustomPathData pathData;
03267                                 if (pathData.Deserialize(subStr))
03268                                         customPathData.push_back(pathData);
03269                                 subStr = pref.Tokenize(_T(";"), curPos);
03270                         }
03271                 }
03272         }
03273 }
03274 
03275 void CGuiConnection::WriteCustomPathData(bool handleTransaction)
03276 {
03277         CString valStr;
03278         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03279                 CString edgeStr;
03280                 (*ii).Serialize(edgeStr);
03281                 if (valStr != _T(""))
03282                         valStr.Append(_T(";"));
03283                 valStr.Append(edgeStr);
03284         }
03285         VERIFY(mgaFco);
03286         CComBSTR pathBstr = CUSTOMCONNECTIONDATA;
03287         CComBSTR bstrVal;
03288         if (valStr == _T(""))
03289                 bstrVal = EMPTYCONNECTIONCUSTOMIZATIONDATAMAGIC;
03290         else
03291                 CopyTo(valStr, bstrVal);
03292 
03293         if (handleTransaction)
03294                 view->BeginTransaction();
03295 
03296         if (valStr == _T("")) {
03297                 CComPtr<IMgaRegNode> ccpMgaRegNode;
03298                 COMTHROW(mgaFco->get_RegistryNode(pathBstr, &ccpMgaRegNode));
03299                 COMTHROW(ccpMgaRegNode->RemoveTree());
03300         } else {
03301                 COMTHROW(mgaFco->put_RegistryValue(pathBstr, bstrVal));
03302         }
03303 
03304         if (handleTransaction)
03305                 view->CommitTransaction();
03306 }
03307 
03308 void CGuiConnection::InsertCustomPathData(const CustomPathData& pathData)
03309 {
03310         // Note:
03311         //      We assume that element are in ascending order by edgeIndexes
03312         //      Types and aspects can be mixed up, but edgeIndexes should be in order within an aspect and type
03313 
03314         // Update indexes
03315         std::vector<CustomPathData>::iterator jj;       // insertion point
03316         bool found = false;
03317         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03318                 ASSERT((*ii).GetVersion() == pathData.GetVersion());
03319                 if ((*ii).GetAspect() == pathData.GetAspect() &&
03320                         (*ii).GetType() == pathData.GetType() &&
03321                         (!IsAutoRouted() || (*ii).GetEdgeCount() == pathData.GetEdgeCount()) &&
03322                         (*ii).GetEdgeIndex() >= pathData.GetEdgeIndex())
03323                 {
03324                         if (!found)
03325                                 jj = ii;
03326                         found = true;
03327                         if (pathData.GetType() == CustomPointCustomization)
03328                                 (*ii).SetEdgeIndex((*ii).GetEdgeIndex() + 1);
03329                         else if (pathData.GetType() == SimpleEdgeDisplacement)
03330                                 break;
03331                         // TODO: other cases
03332                 }
03333         }
03334         if (found)
03335                 // Insert
03336                 customPathData.insert(jj, pathData);
03337         else
03338                 // If we didn't find elements with bigger or equal edgeIndexes, then we should insert it as last one (ascending order)
03339                 customPathData.push_back(pathData);
03340 }
03341 
03342 void CGuiConnection::UpdateCustomPathData(const CustomPathData& pathData)
03343 {
03344         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03345                 ASSERT((*ii).GetVersion() == pathData.GetVersion());
03346                 if ((*ii).GetAspect() == pathData.GetAspect() &&
03347                         (*ii).GetType() == pathData.GetType() &&
03348                         (!IsAutoRouted() || (*ii).GetEdgeCount() == pathData.GetEdgeCount()) &&
03349                         (*ii).GetEdgeIndex() == pathData.GetEdgeIndex())
03350                 {
03351                         (*ii) = pathData;
03352                         return;
03353                 }
03354         }
03355 
03356         // not found => insert it, preserving order
03357         InsertCustomPathData(pathData);
03358 }
03359 
03360 void CGuiConnection::DeletePathCustomization(const CustomPathData& pathData)
03361 {
03362         long fullCustomEdgeCounter = 0;
03363         bool found = false;
03364         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03365                 ASSERT((*ii).GetVersion() == pathData.GetVersion());
03366                 if ((*ii).GetAspect() == pathData.GetAspect() &&
03367                         (*ii).GetType() == pathData.GetType())
03368                 {
03369                         if (pathData.GetType() == SimpleEdgeDisplacement) {
03370                                 if ((*ii).GetEdgeIndex() == pathData.GetEdgeIndex() &&
03371                                         (*ii).GetEdgeCount() == pathData.GetEdgeCount())
03372                                 {
03373                                         ASSERT((*ii).IsHorizontalOrVertical() == pathData.IsHorizontalOrVertical());
03374                                         ii = customPathData.erase(ii);
03375                                         found = true;
03376                                         return;
03377                                 }
03378                         } else if (pathData.GetType() == CustomPointCustomization) {
03379                                 // in case of CustomPointCustomization delete by array index and not edgeIndex
03380                                 if (fullCustomEdgeCounter == pathData.GetEdgeIndex()) {
03381                                         ii = customPathData.erase(ii);
03382                                         found = true;
03383                                         break;
03384                                 }
03385                                 fullCustomEdgeCounter++;
03386                         } else {
03387                                 // TODO: other checks for other types
03388                         }
03389                 }
03390         }
03391         // update indexes in case of full customization
03392         if (pathData.GetType() == CustomPointCustomization) {
03393                 for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03394                         ASSERT((*ii).GetVersion() == pathData.GetVersion());
03395                         if ((*ii).GetAspect() == pathData.GetAspect() &&
03396                                 (*ii).GetType() == pathData.GetType())
03397                         {
03398                                 ASSERT((*ii).GetEdgeIndex() != pathData.GetEdgeIndex());        // because we just deleted it
03399                                 if ((*ii).GetEdgeIndex() > pathData.GetEdgeIndex()) {
03400                                         (*ii).SetEdgeIndex((*ii).GetEdgeIndex() - 1);
03401                                 }
03402                         }
03403                 }
03404         }
03405         // not found
03406         ASSERT(found);
03407 }
03408 
03409 bool CGuiConnection::DeleteAllPathCustomizationsForAnAspect(long asp)
03410 {
03411         bool wereThereAnyDeletion = false;
03412         std::vector<CustomPathData>::iterator ii = customPathData.begin();
03413         while (ii != customPathData.end()) {
03414                 if ((*ii).GetAspect() == asp &&
03415                         (IsAutoRouted() && (*ii).GetType() == SimpleEdgeDisplacement ||
03416                         !IsAutoRouted() && (*ii).GetType() != SimpleEdgeDisplacement))
03417                 {
03418                         wereThereAnyDeletion = true;
03419                         ii = customPathData.erase(ii);
03420                 } else {
03421                         ++ii;
03422                 }
03423         }
03424         return wereThereAnyDeletion;
03425 }
03426 
03427 bool CGuiConnection::DeleteAllPathCustomizationsForCurrentAspect(void)
03428 {
03429         return DeleteAllPathCustomizationsForAnAspect(view->currentAspect->index);
03430 }
03431 
03432 void CGuiConnection::DeleteAllPathCustomizationsForAllAspects(void)
03433 {
03434         customPathData.clear();
03435 }
03436 
03437 void CGuiConnection::RemoveDeletedPathCustomizations(const std::vector<CustomPathData>& customPathDat)
03438 {
03439         std::vector<CustomPathData>::const_iterator ii = customPathDat.begin();
03440         while (ii != customPathDat.end()) {
03441                 std::vector<CustomPathData>::iterator jj = customPathData.begin();
03442                 while (jj != customPathData.end()) {
03443                         if ((*ii).GetAspect() == (*jj).GetAspect() &&
03444                                 (*ii).GetEdgeIndex() == (*jj).GetEdgeIndex() &&
03445                                 (*ii).GetType() == (*jj).GetType() &&
03446                                 ((*ii).GetType() == CustomPointCustomization || (*ii).GetEdgeCount() == (*jj).GetEdgeCount()))
03447                         {
03448                                 jj = customPathData.erase(jj);
03449                         } else {
03450                                 ++jj;
03451                         }
03452                 }
03453                 ++ii;
03454         }
03455 }
03456 
03457 void CGuiConnection::SnapCoordIfApplicable(CustomPathData* coordToSet, const CPoint& last, const CPoint& pt)
03458 {
03459         double radEps = 4.0 / 360.0 * 2 * M_PI;
03460         RoutingDirection dir = GetDir(last - pt);
03461         if (dir == Dir_Skew) {
03462                 bool modify = false;
03463                 RoutingDirection dirToGo = GetSkewDir(last - pt);
03464                 if ((dirToGo == Dir_Left || dirToGo == Dir_Right) && last.y != pt.y) {
03465                         if (abs(last.y - pt.y) <= 3) {
03466                                 modify = true;
03467                         } else if (last.x != pt.x) {
03468                                 double alpha = atan2(-((double)pt.y - last.y), (double)pt.x - last.x);
03469                                 TRACE(_T("Horizontal alpha %lf %lf\n"), alpha / M_PI * 180.0, alpha);
03470                                 if (abs(alpha + M_PI) < radEps || abs(alpha) < radEps || abs(alpha - M_PI) < radEps)
03471                                         modify = true;
03472                         }
03473                         if (modify)
03474                                 coordToSet->SetY(last.y);
03475                 } else if (last.x != pt.x) {    // dirToGo == Dir_Top || dirToGo == Dir_Bottom (also can be Dir_Skew but this would be error and no_dir in case of singularity)
03476                         if (abs(last.x - pt.x) <= 3) {
03477                                 modify = true;
03478                         } else if (last.y != pt.y) {
03479                                 double alpha = atan2((double)pt.x - last.x, -((double)pt.y - last.y));
03480                                 TRACE(_T("Vertical alpha %lf %lf\n"), alpha / M_PI * 180.0, alpha);
03481                                 if (abs(alpha + M_PI) < radEps || abs(alpha) < radEps || abs(alpha - M_PI) < radEps)
03482                                         modify = true;
03483                         }
03484                         if (modify)
03485                                 coordToSet->SetX(last.x);
03486                 }
03487         }
03488 }
03489 
03490 bool CGuiConnection::VerticalAndHorizontalSnappingOfConnectionLineSegments(long asp, int edgeIndex)
03491 {
03492         if (IsAutoRouted() && customPathData.size() < 1)
03493                 return false;
03494 
03495         CPointList points;
03496         GetPointList(points);
03497 
03498         int i = 0;
03499         CustomPathData* lastData = NULL;
03500         for (std::vector<CustomPathData>::iterator ii = customPathData.begin(); ii != customPathData.end(); ++ii) {
03501                 ASSERT((*ii).GetVersion() == CONNECTIONCUSTOMIZATIONDATAVERSION);
03502                 if ((*ii).GetAspect() == asp) {
03503                         if ((*ii).GetType() == CustomPointCustomization) {
03504                                 CPoint pt((*ii).GetX(), (*ii).GetY());
03505                                 CPoint last;
03506                                 if (lastData != NULL) {
03507                                         last = CPoint(lastData->GetX(), lastData->GetY());
03508                                 } else {
03509                                         last = points.GetHead();
03510                                 }
03511                                 if (edgeIndex == -1 || i == edgeIndex || i == edgeIndex + 1)    // Apply snapping only to the point neighbour edges
03512                                         SnapCoordIfApplicable(&(*ii), last, pt);
03513                                 lastData = &(*ii);
03514                                 i++;
03515                         }
03516                 }
03517         }
03518         // see the very last connection line segment
03519         if (lastData != NULL && (edgeIndex == -1 || i == edgeIndex || i == edgeIndex + 1)) {
03520                 CPoint pt(lastData->GetX(), lastData->GetY());
03521                 CPoint last = points.GetTail();
03522                 SnapCoordIfApplicable(lastData, last, pt);
03523         }
03524 
03525         return false;
03526 }
03527 
03528 bool CGuiConnection::IsAutoRouted(void) const
03529 {
03530         if (view->needsConnConversion && connRegAutoRouteNotSet)
03531                 return true;
03532 
03533         return isAutoRouted;
03534 }
03535 
03536 void CGuiConnection::SetAutoRouted(bool autoRouteState)
03537 {
03538         isAutoRouted = autoRouteState;
03539 }
03540 
03541 bool CGuiConnection::NeedsRouterPathConversion(bool expectedAutoRouterState)
03542 {
03543         TRACE(_T("NeedsRouterPathConversion %d %d %d\n"), connRegAutoRouteNotSet, isAutoRouted,
03544                         !HasPathCustomizationForTypeAndCurrentAspect(CustomPointCustomization));
03545         return (connRegAutoRouteNotSet && isAutoRouted == expectedAutoRouterState &&
03546                         !HasPathCustomizationForTypeAndCurrentAspect(CustomPointCustomization));
03547 }
03548 
03549 void CGuiConnection::ConvertAutoRoutedPathToCustom(long asp, bool handleTransaction, bool expectedAutoRouterState)
03550 {
03551         if (NeedsRouterPathConversion(expectedAutoRouterState)) {
03552                 CPointList points;
03553                 GetPointList(points);
03554                 int numPoints = points.GetSize();
03555 
03556                 bool wasThereDataToWrite = false;
03557                 if (numPoints > 2) {
03558                         POSITION pos = points.GetHeadPosition();
03559                         int i = 0;
03560                         while (pos) {
03561                                 CPoint pt = points.GetNext(pos);
03562                                 if (i > 0 && i < numPoints - 1) {       // do not include the start and end point
03563                                         CustomPathData pathData;
03564                                         FillOutCustomPathData(pathData, CustomPointCustomization, asp, pt.x, pt.y, i - 1, numPoints - 1, true);
03565                                         wasThereDataToWrite = true;
03566                                         UpdateCustomPathData(pathData);
03567                                 }
03568                                 i++;
03569                         }
03570                 }
03571 
03572                 if (wasThereDataToWrite)
03573                         WriteCustomPathData(handleTransaction);
03574         }
03575 }
03576 
03577 bool CGuiConnection::ReadAutoRouteState(void)
03578 {
03579         CString autoRoutingStateStr;
03580 
03581         // The parent model's setting overrides the global (theApp.useAutoRouting) settings
03582         bool connRegAutoRoute = view->isModelAutoRouted;
03583         // The connection setting overrides the global or model settings
03584         if (GetPreference(autoRoutingStateStr, CONNECTIONAUTOROUTING)) {
03585                 if (autoRoutingStateStr == _T("false"))
03586                         connRegAutoRoute = false;
03587                 else
03588                         connRegAutoRoute = true;
03589                 connRegAutoRouteNotSet = false;
03590         } else {
03591                 connRegAutoRouteNotSet = true;
03592         }
03593         return connRegAutoRoute;
03594 }
03595 
03596 void CGuiConnection::WriteAutoRouteState(bool handleTransaction)
03597 {
03598         VERIFY(mgaFco);
03599         CComBSTR pathBstr = CONNECTIONAUTOROUTING;
03600         CString valStr = isAutoRouted ? _T("true") : _T("false");
03601         CComBSTR bstrVal;
03602         CopyTo(valStr, bstrVal);
03603         if (handleTransaction)
03604                 view->BeginTransaction();
03605         COMTHROW(mgaFco->put_RegistryValue(pathBstr, bstrVal));
03606         if (handleTransaction)
03607                 view->CommitTransaction();
03608 }
03609 
03610 CGuiConnectionLabelSet& CGuiConnection::GetLabelSet(void)
03611 {
03612         return labelset;
03613 }
03614 
03616 // Static methods of CGuiConnection
03618 
03620 // Virtual methods of CGuiConnection
03622 
03623 
03624