00001
00002
00003
00004 #include "stdafx.h"
00005 #include "inplaceedit.h"
00006 #include "inplacelist.h"
00007 #include "NameSpecTbl.h"
00008 #include "NameSpecDlg.h"
00009 extern NameSpecDlg * dlg;
00010
00011 #ifdef _DEBUG
00012 #define new DEBUG_NEW
00013 #undef THIS_FILE
00014 static char THIS_FILE[] = __FILE__;
00015 #endif
00016
00017 #define OFFSET_FIRST 2
00018 #define OFFSET_OTHER 6
00019
00021
00022
00023 NameSpecTbl::NameSpecTbl()
00024 {
00025 }
00026
00027 NameSpecTbl::~NameSpecTbl()
00028 {
00029 }
00030
00031
00032 BEGIN_MESSAGE_MAP(NameSpecTbl, CListCtrl)
00033
00034 ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
00035 ON_WM_HSCROLL()
00036 ON_WM_VSCROLL()
00037 ON_WM_LBUTTONDOWN()
00038 ON_WM_CREATE()
00039
00040 END_MESSAGE_MAP()
00041
00043
00044
00045 BOOL NameSpecTbl::PreCreateWindow( CREATESTRUCT &cs)
00046 {
00047 cs.style |= WS_TABSTOP|LVS_REPORT|LVS_SINGLESEL|LVS_NOSORTHEADER|LVS_OWNERDRAWFIXED;
00048
00049 return CListCtrl::PreCreateWindow( cs);
00050 }
00051
00052 void NameSpecTbl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
00053 {
00054 LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
00055
00056
00057 LV_ITEM *plvItem = &pDispInfo->item;
00058
00059 if (plvItem->pszText != NULL)
00060 {
00061 SetItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
00062 }
00063
00064 *pResult = TRUE;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int NameSpecTbl::HitTestEx(CPoint &point, int *col) const
00076 {
00077 int colnum = 0;
00078 int row = HitTest( point, NULL );
00079
00080 if( col ) *col = 0;
00081
00082
00083 if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
00084 return row;
00085
00086
00087 row = GetTopIndex();
00088 int bottom = row + GetCountPerPage();
00089 if( bottom > GetItemCount() )
00090 bottom = GetItemCount();
00091
00092
00093 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00094 int nColumnCount = pHeader->GetItemCount();
00095
00096
00097 for( ;row <=bottom;row++)
00098 {
00099
00100 CRect rect;
00101 GetItemRect( row, &rect, LVIR_BOUNDS );
00102 if( rect.PtInRect(point) )
00103 {
00104
00105 for( colnum = 0; colnum < nColumnCount; colnum++ )
00106 {
00107 int colwidth = GetColumnWidth(colnum);
00108 if( point.x >= rect.left
00109 && point.x <= (rect.left + colwidth ) )
00110 {
00111 if( col ) *col = colnum;
00112 return row;
00113 }
00114 rect.left += colwidth;
00115 }
00116 }
00117 }
00118 return -1;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 CComboBox* NameSpecTbl::ShowInPlaceList( int nItem, int nCol,
00130 CStringList &lstItems, int nSel )
00131 {
00132
00133
00134
00135 if( !EnsureVisible( nItem, TRUE ) ) return NULL;
00136
00137
00138 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00139 int nColumnCount = pHeader->GetItemCount();
00140 if( nCol >= nColumnCount || GetColumnWidth(nCol) < 10 )
00141 return NULL;
00142
00143
00144 int offset = 0;
00145 for( int i = 0; i < nCol; i++ )
00146 offset += GetColumnWidth( i );
00147
00148 CRect rect;
00149 GetItemRect( nItem, &rect, LVIR_BOUNDS );
00150
00151
00152 CRect rcClient;
00153 GetClientRect( &rcClient );
00154 if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
00155 {
00156 CSize size;
00157 size.cx = offset + rect.left;
00158 size.cy = 0;
00159 Scroll( size );
00160 rect.left -= size.cx;
00161 }
00162
00163 rect.left += offset+ 1*OFFSET_FIRST;
00164 rect.right = rect.left + GetColumnWidth( nCol );
00165 int height = rect.bottom-rect.top;
00166 rect.bottom += (lstItems.GetCount()+1)*height;
00167 if( rect.right > rcClient.right) rect.right = rcClient.right;
00168
00169 DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE
00170 |CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL;
00171 if( rect.bottom > rcClient.bottom + 4*height)
00172 {
00173 rect.bottom = rcClient.bottom + 4*height;
00174 dwStyle |= WS_VSCROLL;
00175 }
00176
00177 CComboBox *pList = new CInPlaceList(nItem, nCol, &lstItems, nSel);
00178 pList->Create( dwStyle, rect, this, IDC_IPEDIT );
00179 pList->SetItemHeight( -1, height-1);
00180 pList->SetHorizontalExtent( GetColumnWidth( nCol ));
00181 pList->ShowDropDown();
00182
00183
00184 return pList;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193 CEdit* NameSpecTbl::EditSubLabel( int nItem, int nCol )
00194 {
00195
00196
00197
00198 if( !EnsureVisible( nItem, TRUE ) ) return NULL;
00199
00200
00201 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
00202 int nColumnCount = pHeader->GetItemCount();
00203 if( nCol >= nColumnCount || GetColumnWidth(nCol) < 5 )
00204 return NULL;
00205
00206
00207 int offset = 0;
00208 for( int i = 0; i < nCol; i++ )
00209 offset += GetColumnWidth( i );
00210
00211 CRect rect;
00212 GetItemRect( nItem, &rect, LVIR_BOUNDS );
00213
00214
00215 CRect rcClient;
00216 GetClientRect( &rcClient );
00217 if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
00218 {
00219 CSize size;
00220 size.cx = offset + rect.left;
00221 size.cy = 0;
00222 Scroll( size );
00223 rect.left -= size.cx;
00224 }
00225
00226
00227 LV_COLUMN lvcol;
00228 lvcol.mask = LVCF_FMT;
00229 GetColumn( nCol, &lvcol );
00230 DWORD dwStyle ;
00231 if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
00232 dwStyle = ES_LEFT;
00233 else if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
00234 dwStyle = ES_RIGHT;
00235 else dwStyle = ES_CENTER;
00236
00237 rect.left += offset+4;
00238 rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
00239 if( rect.right > rcClient.right) rect.right = rcClient.right;
00240
00241 dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL;
00242 CEdit *pEdit = new CInPlaceEdit(nItem, nCol, GetItemText( nItem, nCol ));
00243 pEdit->Create( dwStyle, rect, this, IDC_IPEDIT );
00244
00245
00246 return pEdit;
00247 }
00248
00249 void NameSpecTbl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00250 {
00251
00252 if( GetFocus() != this ) SetFocus();
00253 CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
00254 }
00255
00256
00257
00258 void NameSpecTbl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00259 {
00260
00261 if( GetFocus() != this ) SetFocus();
00262 CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
00263 }
00264
00265
00266 void NameSpecTbl::OnLButtonDown(UINT nFlags, CPoint point)
00267 {
00268 int index;
00269 CListCtrl::OnLButtonDown(nFlags, point);
00270
00271 int colnum;
00272 if( ( index = HitTestEx( point, &colnum )) != -1 )
00273 {
00274 UINT flag = LVIS_FOCUSED;
00275 if( (GetItemState( index, flag ) & flag) == flag )
00276 {
00277
00278
00279 if(colnum==0)
00280 {
00281 char buff[128];
00282 LVITEM item;
00283 item.mask = LVIF_TEXT;
00284 item.iItem = index;
00285 item.iSubItem = 0;
00286 item.pszText = buff;
00287 item.cchTextMax = 127;
00288 if (GetItem(&item) && CString(item.pszText) != "N/A") {
00289 CStringList lstItems;
00290 int rowID = GetItemData( index);
00291 dlg->GetNames( rowID, CString(item.pszText), lstItems);
00292 ShowInPlaceList( index, colnum, lstItems, 0 );
00293 }
00294 }
00295 else if(colnum==1)
00296 {
00297 char buff[128];
00298 LVITEM item;
00299 item.mask = LVIF_TEXT;
00300 item.iItem = index;
00301 item.iSubItem = 1;
00302 item.pszText = buff;
00303 item.cchTextMax = 127;
00304 if (GetItem(&item) && CString(item.pszText) != "N/A") {
00305 CStringList lstItems;
00306 int rowID = GetItemData( index);
00307 dlg->GetDispNames( rowID, CString(item.pszText), lstItems);
00308 ShowInPlaceList( index, colnum, lstItems, 0 );
00309 }
00310 }
00311 }
00312 else
00313 SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
00314 LVIS_SELECTED | LVIS_FOCUSED);
00315 }
00316 }
00317
00318
00319
00320 void NameSpecTbl::AddRow(int rowID, CString& name, CString& disp_name, CString& kind)
00321 {
00322 LV_ITEM lvItem;
00323 lvItem.mask = LVIF_TEXT;
00324 lvItem.iItem = GetItemCount();
00325 lvItem.iSubItem = 0;
00326 lvItem.pszText = name.GetBuffer( name.GetLength());
00327 int index = InsertItem(&lvItem);
00328
00329 lvItem.iSubItem = 1;
00330 lvItem.pszText = disp_name.GetBuffer( disp_name.GetLength());
00331 SetItem(&lvItem);
00332
00333 lvItem.iSubItem = 2;
00334 lvItem.pszText = kind.GetBuffer( kind.GetLength());
00335 SetItem(&lvItem);
00336
00337 SetItemData(index, rowID);
00338 }
00339
00340 int NameSpecTbl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00341 {
00342 if (CListCtrl::OnCreate(lpCreateStruct) == -1)
00343 return -1;
00344
00345 int col1size = 3*GetStringWidth("TipicalLongTipicalLongName")/2;
00346 int col2size = 3*GetStringWidth("KindName")/2;
00347
00348 InsertColumn(0, _T("Name"), LVCFMT_LEFT, col1size, -1);
00349 InsertColumn(1, _T("Displayed Name"), LVCFMT_LEFT, col1size, -1);
00350 InsertColumn(2, _T("Kind"), LVCFMT_LEFT, col2size, -1);
00351
00352 return 0;
00353 }
00354
00355 bool NameSpecTbl::GetRow(int rowID, CString& name, CString& disp_name, CString& kind)
00356 {
00357 LVFINDINFO lvFind;
00358 lvFind.flags = LVFI_PARAM;
00359 lvFind.lParam = rowID;
00360 int idx = FindItem(&lvFind);
00361
00362 if (idx == -1)
00363 return false;
00364
00365
00366 LV_ITEM lvItem;
00367 lvItem.mask = LVIF_TEXT;
00368 lvItem.iItem = idx;
00369 lvItem.pszText = name.GetBuffer(255);
00370 lvItem.cchTextMax = 254;
00371 lvItem.iSubItem = 0;
00372 GetItem(&lvItem);
00373
00374
00375 lvItem.iSubItem = 1;
00376 lvItem.pszText = disp_name.GetBuffer(255);
00377 lvItem.cchTextMax = 254;
00378 GetItem(&lvItem);
00379
00380 lvItem.iSubItem = 2;
00381 lvItem.pszText = kind.GetBuffer(255);
00382 lvItem.cchTextMax = 254;
00383 GetItem(&lvItem);
00384
00385 return true;
00386 }
00387
00388 void NameSpecTbl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
00389 {
00390 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
00391 CRect rcItem(lpDrawItemStruct->rcItem);
00392 int nItem = lpDrawItemStruct->itemID;
00393 BOOL bFocus = (GetFocus() == this);
00394 COLORREF clrTextSave, clrBkSave;
00395 static _TCHAR szBuff[MAX_PATH];
00396 LPCTSTR pszText;
00397
00398
00399
00400 LV_ITEM lvi;
00401 lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
00402 lvi.iItem = nItem;
00403 lvi.iSubItem = 0;
00404 lvi.pszText = szBuff;
00405 lvi.cchTextMax = sizeof(szBuff);
00406 lvi.stateMask = 0xFFFF;
00407 GetItem(&lvi);
00408
00409 BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
00410 bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);
00411
00412
00413
00414 CRect rcAllLabels;
00415 GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
00416
00417 CRect rcLabel;
00418 GetItemRect(nItem, rcLabel, LVIR_LABEL);
00419
00420 rcAllLabels.left = rcLabel.left;
00421
00422 if (bSelected)
00423 {
00424
00425 clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
00426 clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
00427
00428 pDC->FillRect(rcAllLabels, &CBrush( ::GetSysColor(COLOR_HIGHLIGHT)));
00429 }
00430 else
00431 pDC->FillRect(rcAllLabels, &CBrush( ::GetSysColor(COLOR_WINDOW)));
00432
00433
00434
00435 GetItemRect(nItem, rcItem, LVIR_LABEL);
00436
00437 pszText = MakeShortString(pDC, szBuff, rcItem.right-rcItem.left, 2*OFFSET_FIRST);
00438
00439 rcLabel = rcItem;
00440 rcLabel.left += OFFSET_FIRST;
00441 rcLabel.right -= OFFSET_FIRST;
00442
00443 pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
00444
00445
00446 CRect rc = rcItem;
00447
00448 rc.left = rc.right - ::GetSystemMetrics(SM_CXHSCROLL);
00449
00450
00451
00452
00453 if( rc.left > OFFSET_FIRST + 1)
00454 pDC->DrawFrameControl(rc, DFC_SCROLL, DFCS_SCROLLDOWN);
00455
00456
00457
00458 LV_COLUMN lvc;
00459 lvc.mask = LVCF_FMT | LVCF_WIDTH;
00460
00461 for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
00462 {
00463 rcItem.left = rcItem.right;
00464 rcItem.right += lvc.cx;
00465
00466 int nRetLen = GetItemText(nItem, nColumn,
00467 szBuff, sizeof(szBuff));
00468 if (nColumn != 1 && nRetLen == 0)
00469 continue;
00470
00471 pszText = MakeShortString(pDC, szBuff,
00472 rcItem.right - rcItem.left, 2*OFFSET_OTHER);
00473
00474 UINT nJustify = DT_LEFT;
00475
00476 if(pszText == szBuff)
00477 {
00478 switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
00479 {
00480 case LVCFMT_RIGHT:
00481 nJustify = DT_RIGHT;
00482 break;
00483 case LVCFMT_CENTER:
00484 nJustify = DT_CENTER;
00485 break;
00486 default:
00487 break;
00488 }
00489 }
00490
00491 rcLabel = rcItem;
00492 rcLabel.left += OFFSET_OTHER;
00493
00494
00495 pDC->DrawText(pszText, -1, rcLabel,
00496 nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
00497
00498
00499 CRect r2 = rcLabel;
00500 r2.left = r2.right - ::GetSystemMetrics(SM_CXHSCROLL);
00501 if( nColumn == 1 && r2.left > OFFSET_FIRST + 1)
00502 pDC->DrawFrameControl(r2, DFC_SCROLL, DFCS_SCROLLDOWN);
00503 }
00504
00505
00506
00507 if (lvi.state & LVIS_FOCUSED && bFocus) pDC->DrawFocusRect(rcAllLabels);
00508
00509
00510
00511
00512 if (bSelected)
00513 {
00514 pDC->SetTextColor(clrTextSave);
00515 pDC->SetBkColor(clrBkSave);
00516 }
00517 }
00518
00519 LPCTSTR NameSpecTbl::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
00520 {
00521 static const _TCHAR szEmpty[] = _T("");
00522 static const _TCHAR szThreeDots[] = _T("...");
00523
00524 int nStringLen = lstrlen(lpszLong);
00525
00526 if(nStringLen == 0 ||
00527 (pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen)
00528 {
00529 return(lpszLong);
00530 }
00531
00532 static _TCHAR szShort[MAX_PATH];
00533
00534 lstrcpy(szShort,lpszLong);
00535 int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
00536
00537 if( nOffset + nAddLen > nColumnLen) return szEmpty;
00538
00539
00540 for(int i = nStringLen-1; i > 0; i--)
00541 {
00542 szShort[i] = 0;
00543 if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen)
00544 <= nColumnLen)
00545 {
00546 break;
00547 }
00548 }
00549
00550 lstrcat(szShort, szThreeDots);
00551 return(szShort);
00552 }