00001
00002
00003
00004 #include "stdafx.h"
00005 #include "inplaceedit.h"
00006 #include "inplacelist.h"
00007 #include "table.h"
00008 #include "SelConf.h"
00009
00010 #ifdef _DEBUG
00011 #define new DEBUG_NEW
00012 #undef THIS_FILE
00013 static char THIS_FILE[] = __FILE__;
00014 #endif
00015
00016 #define OFFSET_FIRST 2 // offsets for first and other columns in owner draw methods
00017 #define OFFSET_OTHER 6
00018
00019 #define EXT_COLNUM 2 // column of 'Extended?'
00020 #define RSP_COLNUM 3 // column of 'Capture as' or 'Responsible'
00021
00023
00024
00025 CTable::CTable()
00026 : m_parent(0)
00027 , m_cxClient(0)
00028 {
00029 }
00030
00031 CTable::~CTable()
00032 {
00033 }
00034
00035 BOOL CTable::PreCreateWindow(CREATESTRUCT &cs)
00036 {
00037 cs.style |= LVS_OWNERDRAWFIXED;
00038 return CListCtrl::PreCreateWindow( cs);
00039 }
00040
00041
00042 BEGIN_MESSAGE_MAP(CTable, CListCtrl)
00043
00044 ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
00045 ON_WM_HSCROLL()
00046 ON_WM_VSCROLL()
00047 ON_WM_LBUTTONDOWN()
00048 ON_WM_CREATE()
00049 ON_WM_SIZE()
00050 ON_WM_PAINT()
00051 ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnSort)
00052
00053 END_MESSAGE_MAP()
00054
00056
00057
00058 void CTable::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
00059 {
00060 LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
00061
00062
00063 LV_ITEM *plvItem = &pDispInfo->item;
00064
00065 if (plvItem->pszText != NULL)
00066 {
00067
00068 LV_ITEM old_lvItem;
00069 old_lvItem.mask = LVIF_TEXT;
00070 old_lvItem.iItem = plvItem->iItem;
00071
00072 CString prev_str;
00073 old_lvItem.iSubItem = plvItem->iSubItem;
00074 old_lvItem.pszText = prev_str.GetBuffer(255);
00075 old_lvItem.cchTextMax = 255;
00076 GetItem(&old_lvItem);
00077
00078
00079 if( prev_str == plvItem->pszText) { *pResult = TRUE; return; }
00080
00081
00082 BOOL res = SetItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
00083
00084
00085 if( res && plvItem->iSubItem == EXT_COLNUM)
00086 {
00087 bool bYes = strcmp( plvItem->pszText, "yes") == 0;
00088 const char* repValArray[] = { "self", "none"};
00089 const char* repVal = repValArray[bYes?0:1];
00090
00091
00092 SetItemText(plvItem->iItem, RSP_COLNUM, repVal);
00093
00094
00095 std::vector< int > res;
00096 m_parent->getDescsAncs( !bYes, GetItemData( plvItem->iItem), res);
00097
00098
00099 for( unsigned int desc_i = 0; desc_i < res.size(); ++desc_i)
00100 {
00101 unsigned int desc_r_id = res[desc_i];
00102 for (int i=0;i < GetItemCount();i++)
00103 {
00104
00105 if ( GetItemData(i) == desc_r_id)
00106 {
00107
00108
00109
00110 SetItemText( i, EXT_COLNUM, plvItem->pszText);
00111
00112
00113 SetItemText( i, RSP_COLNUM, repVal);
00114 }
00115 }
00116 }
00117 }
00118 }
00119
00120 *pResult = TRUE;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 int CTable::HitTestEx(CPoint &point, int *col) const
00132 {
00133 int colnum = 0;
00134 int row = HitTest( point, NULL );
00135
00136 if( col ) *col = 0;
00137
00138
00139 if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
00140 return row;
00141
00142
00143 row = GetTopIndex();
00144 int bottom = row + GetCountPerPage();
00145 if( bottom > GetItemCount() )
00146 bottom = GetItemCount();
00147
00148
00149 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00150 int nColumnCount = pHeader->GetItemCount();
00151
00152
00153 for( ;row <=bottom;row++)
00154 {
00155
00156 CRect rect;
00157 GetItemRect( row, &rect, LVIR_BOUNDS );
00158 if( rect.PtInRect(point) )
00159 {
00160
00161 for( colnum = 0; colnum < nColumnCount; colnum++ )
00162 {
00163 int colwidth = GetColumnWidth(colnum);
00164 if( point.x >= rect.left
00165 && point.x <= (rect.left + colwidth ) )
00166 {
00167 if( col ) *col = colnum;
00168 return row;
00169 }
00170 rect.left += colwidth;
00171 }
00172 }
00173 }
00174 return -1;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 CComboBox* CTable::ShowInPlaceList( int nItem, int nCol,
00186 CStringList &lstItems, int nSel )
00187 {
00188
00189
00190
00191 if( !EnsureVisible( nItem, TRUE ) ) return NULL;
00192
00193
00194 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00195 int nColumnCount = pHeader->GetItemCount();
00196 if( nCol >= nColumnCount || GetColumnWidth(nCol) < 10 )
00197 return NULL;
00198
00199
00200 int offset = 0;
00201 for( int i = 0; i < nCol; i++ )
00202 offset += GetColumnWidth( i );
00203
00204 CRect rect;
00205 GetItemRect( nItem, &rect, LVIR_BOUNDS );
00206
00207
00208 CRect rcClient;
00209 GetClientRect( &rcClient );
00210 if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
00211 {
00212 CSize size;
00213 size.cx = offset + rect.left;
00214 size.cy = 0;
00215 Scroll( size );
00216 rect.left -= size.cx;
00217 }
00218
00219 rect.left += offset+4;
00220 rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
00221 int height = rect.bottom-rect.top;
00222 rect.bottom += (lstItems.GetCount()+1)*height;
00223 if( rect.right > rcClient.right) rect.right = rcClient.right;
00224
00225 DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE
00226 |CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL;
00227 CComboBox *pList = new CInPlaceList(nItem, nCol, &lstItems, nSel);
00228 pList->Create( dwStyle, rect, this, IDC_IPEDIT );
00229 pList->SetItemHeight( -1, height);
00230 pList->SetHorizontalExtent( GetColumnWidth( nCol ));
00231
00232
00233 return pList;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242 CEdit* CTable::EditSubLabel( int nItem, int nCol )
00243 {
00244
00245
00246
00247 if( !EnsureVisible( nItem, TRUE ) ) return NULL;
00248
00249
00250 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00251 int nColumnCount = pHeader->GetItemCount();
00252 if( nCol >= nColumnCount || GetColumnWidth(nCol) < 5 )
00253 return NULL;
00254
00255
00256 int offset = 0;
00257 for( int i = 0; i < nCol; i++ )
00258 offset += GetColumnWidth( i );
00259
00260 CRect rect;
00261 GetItemRect( nItem, &rect, LVIR_BOUNDS );
00262
00263
00264 CRect rcClient;
00265 GetClientRect( &rcClient );
00266 if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
00267 {
00268 CSize size;
00269 size.cx = offset + rect.left;
00270 size.cy = 0;
00271 Scroll( size );
00272 rect.left -= size.cx;
00273 }
00274
00275
00276 LV_COLUMN lvcol;
00277 lvcol.mask = LVCF_FMT;
00278 GetColumn( nCol, &lvcol );
00279 DWORD dwStyle ;
00280 if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
00281 dwStyle = ES_LEFT;
00282 else if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
00283 dwStyle = ES_RIGHT;
00284 else dwStyle = ES_CENTER;
00285
00286 rect.left += offset+4;
00287 rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
00288 if( rect.right > rcClient.right) rect.right = rcClient.right;
00289
00290 dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL;
00291 CEdit *pEdit = new CInPlaceEdit(nItem, nCol, GetItemText( nItem, nCol ));
00292 pEdit->Create( dwStyle, rect, this, IDC_IPEDIT );
00293
00294
00295 return pEdit;
00296 }
00297
00298 void CTable::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00299 {
00300
00301 if( GetFocus() != this ) SetFocus();
00302 CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
00303 }
00304
00305
00306
00307 void CTable::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00308 {
00309
00310 if( GetFocus() != this ) SetFocus();
00311 CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
00312 }
00313
00314
00315 void CTable::OnLButtonDown(UINT nFlags, CPoint point)
00316 {
00317 int index;
00318 CListCtrl::OnLButtonDown(nFlags, point);
00319
00320 int colnum;
00321 if( ( index = HitTestEx( point, &colnum )) != -1 )
00322 {
00323 UINT flag = LVIS_FOCUSED;
00324 if( (GetItemState( index, flag ) & flag) == flag )
00325 {
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 if(colnum==EXT_COLNUM)
00345 {
00346 CStringList lstItems;
00347 lstItems.AddTail("yes");
00348 lstItems.AddTail("no");
00349 ShowInPlaceList( index, colnum, lstItems, 0 );
00350 }
00351 else if(colnum==RSP_COLNUM)
00352 {
00353 DWORD_PTR rowID = GetItemData( index);
00354 CString role, repr; bool ext;
00355 if( getRow( rowID, role, ext, repr) && ext == false)
00356 {
00357 CStringList lstItems;
00358 lstItems.AddTail("none");
00359 if( m_parent->addPossibleAncestors( lstItems, rowID))
00360 ShowInPlaceList( index, colnum, lstItems, 0 );
00361 else
00362 AfxMessageBox("This class does not have a base of the same kind. For BON2 reasons can't be captured by its superclass.");
00363 }
00364 }
00365
00366 }
00367 else
00368 SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
00369 LVIS_SELECTED | LVIS_FOCUSED);
00370 }
00371 }
00372
00373 int CTable::OnCreate(LPCREATESTRUCT lpCreateStruct)
00374 {
00375 if (CListCtrl::OnCreate(lpCreateStruct) == -1)
00376 return -1;
00377
00378 int col0size = 9*GetStringWidth("TipicalLongRolenName")/4;
00379 int col1size = 4*GetStringWidth("R");
00380 int col2size = 13*GetStringWidth("Extend")/9;
00381 int col3size = 3*GetStringWidth("TypicalLongRoleName")/2;
00382
00383 InsertColumn(0, _T("Class"), LVCFMT_LEFT, col0size, -1);
00384 InsertColumn(1, _T("Stereotype"), LVCFMT_LEFT, col1size, -1);
00385 InsertColumn(EXT_COLNUM, _T("Extend"), LVCFMT_LEFT, col2size, -1);
00386 InsertColumn(RSP_COLNUM, _T("Capture as"), LVCFMT_LEFT, col3size, -1);
00387
00388 return 0;
00389 }
00390
00391 void CTable::addRow(int rowID, CString& role, char kind, int clique, bool generate, CString& repr)
00392 {
00393 LV_ITEM lvItem;
00394 lvItem.mask = LVIF_TEXT;
00395 lvItem.iItem = GetItemCount();
00396 lvItem.iSubItem = 0;
00397 lvItem.pszText = role.GetBuffer(role.GetLength());
00398 int index = InsertItem(&lvItem);
00399
00400 char b[2] = { kind, 0 };
00401 lvItem.iSubItem = 1;
00402 lvItem.pszText = b;
00403 SetItem(&lvItem);
00404
00405 lvItem.iSubItem = EXT_COLNUM;
00406 lvItem.pszText = generate ? _T("yes"): _T("no");
00407 SetItem(&lvItem);
00408
00409 lvItem.iSubItem = RSP_COLNUM;
00410 lvItem.pszText = generate ?_T("self"): repr.IsEmpty() ? _T("none") : repr;
00411 SetItem(&lvItem);
00412
00413
00414 SetItemData(index, rowID);
00415
00416 }
00417
00418 bool CTable::getRow(int rowID, CString &role, bool &generate, CString &repr)
00419 {
00420 LVFINDINFO lvFind;
00421 lvFind.flags = LVFI_PARAM;
00422 lvFind.lParam = rowID;
00423 int idx = FindItem(&lvFind);
00424
00425 if (idx == -1)
00426 return false;
00427
00428
00429 LV_ITEM lvItem;
00430 lvItem.mask = LVIF_TEXT;
00431 lvItem.iItem = idx;
00432 lvItem.pszText = role.GetBuffer(255);
00433 lvItem.cchTextMax = 255;
00434 lvItem.iSubItem = 0;
00435 GetItem(&lvItem);
00436
00437 CString tmpStr;
00438 lvItem.pszText = tmpStr.GetBuffer(10);
00439 lvItem.cchTextMax = 10;
00440 lvItem.iSubItem = EXT_COLNUM;
00441 GetItem(&lvItem);
00442 generate = (tmpStr == "yes");
00443
00444 lvItem.pszText = repr.GetBuffer(255);
00445 lvItem.cchTextMax = 255;
00446 lvItem.iSubItem = RSP_COLNUM;
00447 GetItem(&lvItem);
00448
00449 return true;
00450 }
00451
00452 void CTable::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
00453 {
00454 CListCtrl& ListCtrl = *this;
00455 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
00456 CRect rcItem(lpDrawItemStruct->rcItem);
00457 UINT uiFlags = ILD_TRANSPARENT;
00458 int nItem = lpDrawItemStruct->itemID;
00459 BOOL bFocus = (GetFocus() == this);
00460 COLORREF clrTextSave, clrBkSave;
00461 static _TCHAR szBuff[MAX_PATH];
00462 static _TCHAR szBuff2[MAX_PATH] = _T("c");
00463 LPCTSTR pszText;
00464
00465
00466
00467 LV_ITEM lvi;
00468 lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
00469 lvi.iItem = nItem;
00470 lvi.iSubItem = 0;
00471 lvi.pszText = szBuff;
00472 lvi.cchTextMax = sizeof(szBuff);
00473 lvi.stateMask = 0xFFFF;
00474 ListCtrl.GetItem(&lvi);
00475
00476 BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
00477 bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);
00478
00479
00480
00481 CRect rcAllLabels;
00482 ListCtrl.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
00483
00484 CRect rcLabel;
00485 ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
00486
00487 rcAllLabels.left = rcLabel.left;
00488 if (rcAllLabels.right<m_cxClient)
00489 rcAllLabels.right = m_cxClient;
00490
00491 if (bSelected)
00492 {
00493
00494 clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
00495 clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
00496
00497 pDC->FillRect(rcAllLabels, &CBrush( ::GetSysColor(COLOR_HIGHLIGHT)));
00498 }
00499 else
00500 pDC->FillRect(rcAllLabels, &CBrush( ::GetSysColor(COLOR_WINDOW)));
00501
00502
00503
00504 ListCtrl.GetItemRect(nItem, rcItem, LVIR_LABEL);
00505
00506 pszText = MakeShortString(pDC, szBuff, rcItem.right-rcItem.left, 2*OFFSET_FIRST);
00507
00508 rcLabel = rcItem;
00509 rcLabel.left += OFFSET_FIRST;
00510 rcLabel.right -= OFFSET_FIRST;
00511
00512 pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
00513
00514
00515
00516
00517 LV_COLUMN lvc;
00518 lvc.mask = LVCF_FMT | LVCF_WIDTH;
00519
00520 for(int nColumn = 1; ListCtrl.GetColumn(nColumn, &lvc); nColumn++)
00521 {
00522 rcItem.left = rcItem.right;
00523 rcItem.right += lvc.cx;
00524
00525 int nRetLen = ListCtrl.GetItemText(nItem, nColumn,
00526 szBuff, sizeof(szBuff));
00527 if (nRetLen == 0)
00528 continue;
00529
00530 pszText = MakeShortString(pDC, szBuff,
00531 rcItem.right - rcItem.left, 2*OFFSET_OTHER);
00532
00533 UINT nJustify = DT_LEFT;
00534
00535 if(pszText == szBuff)
00536 {
00537 switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
00538 {
00539 case LVCFMT_RIGHT:
00540 nJustify = DT_RIGHT;
00541 break;
00542 case LVCFMT_CENTER:
00543 nJustify = DT_CENTER;
00544 break;
00545 default:
00546 break;
00547 }
00548 }
00549
00550 rcLabel = rcItem;
00551 rcLabel.left += OFFSET_OTHER;
00552 rcLabel.right -= OFFSET_OTHER;
00553
00554 pDC->DrawText(pszText, -1, rcLabel,
00555 nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
00556 }
00557
00558
00559
00560
00561
00562
00563
00564 if (bSelected)
00565 {
00566 pDC->SetTextColor(clrTextSave);
00567 pDC->SetBkColor(clrBkSave);
00568 }
00569 }
00570
00571 LPCTSTR CTable::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
00572 {
00573 static const _TCHAR szThreeDots[] = _T("...");
00574
00575 int nStringLen = lstrlen(lpszLong);
00576
00577 if(nStringLen == 0 ||
00578 (pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen)
00579 {
00580 return(lpszLong);
00581 }
00582
00583 static _TCHAR szShort[MAX_PATH];
00584
00585 lstrcpy(szShort,lpszLong);
00586 int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
00587
00588 for(int i = nStringLen-1; i > 0; i--)
00589 {
00590 szShort[i] = 0;
00591 if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen)
00592 <= nColumnLen)
00593 {
00594 break;
00595 }
00596 }
00597
00598 lstrcat(szShort, szThreeDots);
00599 return(szShort);
00600 }
00601
00602 void CTable::OnSize(UINT nType, int cx, int cy)
00603 {
00604 m_cxClient = cx;
00605 CListCtrl::OnSize(nType, cx, cy);
00606 }
00607
00608 void CTable::OnPaint()
00609 {
00610
00611
00612 if ((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
00613 {
00614 CRect rcAllLabels;
00615 GetItemRect(0, rcAllLabels, LVIR_BOUNDS);
00616
00617 if(rcAllLabels.right < m_cxClient)
00618 {
00619
00620
00621 CPaintDC dc(this);
00622
00623 CRect rcClip;
00624 dc.GetClipBox(rcClip);
00625
00626 rcClip.left = min(rcAllLabels.right-1, rcClip.left);
00627 rcClip.right = m_cxClient;
00628
00629 InvalidateRect(rcClip, FALSE);
00630
00631 }
00632 }
00633
00634 CListCtrl::OnPaint();
00635 }
00636
00637 void CTable::OnSort(NMHDR* pNMHDR, LRESULT* pResult)
00638 {
00639 NMLISTVIEW* pNMLV = (NMLISTVIEW*) pNMHDR;
00640 ASSERT( pNMLV->iItem == -1);
00641 ASSERT( pNMLV->iSubItem >= 0);
00642
00643 switch( pNMLV->iSubItem) {
00644 case 0:
00645 this->SortItems( SelConf::MyNameCompare, (LPARAM) m_parent);
00646 break;
00647 case 1:
00648 this->SortItems( SelConf::MyKindCompare, (LPARAM) m_parent);
00649 break;
00650 case 2:
00651 this->SortItems( SelConf::MyExtdCompare, (LPARAM) m_parent);
00652 break;
00653 case 3:
00654 this->SortItems( SelConf::MyReprCompare, (LPARAM) m_parent);
00655 break;
00656 default:
00657 ASSERT(0);
00658 };
00659
00660
00661 SelConf::m_sortOrder *= -1;
00662 }