/* * Copyright 2004 Perforce Software. All rights reserved. * * Developed by Data Shades Ltd. */ #include "OpenDepotDialog.h" #include "TraceUtils.h" // Store orginal wndproc of list view static WNDPROC origListViewProc; static void GetItemInfo( HWND fileList, int idx, UniStrDict **dict = NULL, TCHAR *buff = NULL, BOOL *selected = NULL ) { LVITEM item; item.iItem = idx; item.iSubItem = 0; item.mask = 0; if ( buff != NULL ) { item.mask |= LVIF_TEXT; item.pszText = buff; item.cchTextMax = MAX_PATH; } if ( dict != NULL ) { item.mask |= LVIF_PARAM; } if ( selected != NULL ) { item.mask |= LVIF_STATE; item.stateMask = LVIS_SELECTED; } ListView_GetItem( fileList, &item ); if ( dict != NULL ) { *dict = (UniStrDict *)item.lParam; } if ( selected != NULL ) { *selected = item.state & LVIS_SELECTED; } } OpenDepotDialog::OpenDepotDialog( PluginOperations *ops, PerforceOptions *options, StrBufArray *filetypes ) : Dialog( ops, IDD_OPEN_DEPOT_DIALOG, DialogWndProc ) { ops->SetFileDir(); con = new PerforceConnection( ops ); ops->RestoreOldDir(); this->options = options; this->filetypes = filetypes; // Set initial sort orders nameOrder = 1; haveOrder = -1; headOrder = -1; typeOrder = -1; } OpenDepotDialog::~OpenDepotDialog() { delete con; ImageList_Destroy( lookInImages ); } LRESULT APIENTRY OpenDepotDialog::ListViewEnterHandler( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if ( uMsg == WM_GETDLGCODE ) { LPMSG lpmsg; if ( ( lpmsg = (LPMSG)lParam ) != NULL ) { // Intercept return key when item selected is a folder. if ( lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_RETURN ) { HWND dialog = GetParent( hwnd ); HWND fileList = GetDlgItem( dialog, IDC_DEPOT_LIST ); if ( ListView_GetSelectedCount( fileList ) > 0 ) { int idx = ListView_GetNextItem( fileList, -1, LVNI_SELECTED ); UniStrDict *dict; GetItemInfo( fileList, idx, &dict ); if ( IsFolder( dict ) ) { return DLGC_WANTALLKEYS; } } } } } else if ( uMsg == WM_KEYDOWN && wParam == VK_RETURN ) { // Process return key when selected item is a folder HWND dialog = GetParent( hwnd ); HWND fileList = GetDlgItem( dialog, IDC_DEPOT_LIST ); if ( ListView_GetSelectedCount( fileList ) > 0 ) { int idx = ListView_GetNextItem( fileList, -1, LVNI_SELECTED ); TCHAR path[MAX_PATH]; UniStrDict *dict; GetItemInfo( fileList, idx, &dict, path ); // If item is a folder then open it if ( IsFolder( dict ) ) { EnterFolder( dialog, path ); return 0; } } } return CallWindowProc( origListViewProc, hwnd, uMsg, wParam, lParam ); } void OpenDepotDialog::EnterFolder( HWND hWnd, TCHAR *path ) { HWND fileList = GetDlgItem( hWnd, IDC_DEPOT_LIST ); HWND lookIn = GetDlgItem( hWnd, IDC_LOOK_IN_COMBO ); HWND fileTypes = GetDlgItem( hWnd, IDC_FILE_TYPE_COMBO ); OpenDepotDialog *dialog = ( OpenDepotDialog * )DialogObject( hWnd ); dialog->OpenDir( lookIn, path ); // Refresh files view try { dialog->ShowCurrFolder( fileList, fileTypes ); } catch (std::exception e) { dialog->SetError( hWnd, &e ); } } void OpenDepotDialog::InitFileTypes( HWND combo ) { COMBOBOXEXITEM item; item.mask = CBEIF_TEXT; if ( filetypes != NULL && filetypes->Count() > 0 ) { for ( int i = 0; i<filetypes->Count(); i++ ) { item.iItem = i; item.pszText = filetypes->Get( i ); SendMessage( combo, CBEM_INSERTITEM, 0, ( LPARAM )&item ); } int curr = options->GetOptionValue( PERFORCE_OPEN_FILE_TYPE ); if ( curr < filetypes->Count() ) { SendMessage( combo, CB_SETCURSEL, (WPARAM)curr, 0 ); } else { SendMessage( combo, CB_SETCURSEL, (WPARAM)0, 0 ); } } else { item.iItem = 0; item.pszText = _T("All Files (*.*)"); SendMessage( combo, CBEM_INSERTITEM, 0, ( LPARAM )&item ); SendMessage( combo, CB_SETCURSEL, (WPARAM)0, 0 ); } } int OpenDepotDialog::WildCmp( TCHAR *wild, TCHAR *string ) { TCHAR *cp, *mp; while ( ( *string ) && ( *wild != '*' ) ) { if ( _tcsnicmp( wild, string, 1 ) != 0 && ( *wild != '?' ) ) { return 0; } wild = _tcsinc( wild ); string = _tcsinc( string ); } while ( *string ) { if ( *wild == '*' ) { wild = _tcsinc( wild ); if ( !*wild ) { return 1; } mp = wild; cp = _tcsinc( string ); } else if ( _tcsnicmp( wild, string, 1 ) == 0 || ( * wild == '?' ) ) { wild = _tcsinc( wild ); string = _tcsinc( string ); } else { wild = mp; string = cp; cp = _tcsinc( cp ); } } while ( *wild == '*' ) { wild = _tcsinc( wild ); } return !*wild; } /* * Original ASCII version of WildCmp * int OpenDepotDialog::WildCmp( char *wild, char *string ) { char *cp, *mp; while ( ( *string ) && ( *wild != '*' ) ) { if ( !CharICmp( *wild, *string ) && ( *wild != '?' ) ) { return 0; } wild++; string++; } while ( *string ) { if ( *wild == '*' ) { if ( !*++wild ) { return 1; } mp = wild; cp = string+1; } else if ( CharICmp( *wild, *string ) || ( *wild == '?' ) ) { wild++; string++; } else { wild = mp; string = cp++; } } while (*wild == '*') { wild++; } return !*wild; } */ bool OpenDepotDialog::MatchFileType( HWND combo, TCHAR *filename ) { TCHAR buff[MAX_TYPE_SIZE]; COMBOBOXEXITEM info; info.mask = CBEIF_TEXT; info.iItem = SendMessage( combo, CB_GETCURSEL, 0, 0 ); info.pszText = buff; info.cchTextMax = sizeof( buff ); SendMessage( combo, CBEM_GETITEM, 0, (LPARAM)&info ); // Extract name extension TCHAR *extn = _tcsrchr( filename, '.' ); if ( extn != NULL ) { extn++; } TCHAR *curr = buff; UniStrBuf wildext; while ( curr = _tcschr( curr, '.' ) ) { curr++; TCHAR *end = curr; // Extract extension while ( *end && *end != ';' && *end != ')' ) { end++; } wildext.Set( curr, ( end - curr ) * sizeof( TCHAR ) ); // Check for files that do not have an extension if ( extn == NULL ) { // files with no extension only match against *.* if ( _tcscmp( wildext.Text(), _T("*") ) == 0 ) { return true; } } else { if ( WildCmp( wildext.Text(), extn ) ) { return true; } } } return false; } void OpenDepotDialog::AddLookInItem( HWND combo, int pos, TCHAR *text, int indent ) { COMBOBOXEXITEM item; item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE; item.iItem = pos; item.pszText = text; item.iIndent = indent; item.iImage = 0; item.iSelectedImage = 1; SendMessage( combo, CBEM_INSERTITEM, 0, ( LPARAM )&item ); } void OpenDepotDialog::SetupLookInImageLists( HWND combo ) { // Image list gets destroyed in destructor lookInImages = ImageList_Create( 21, 13, ILC_COLOR24 | ILC_MASK, 3, 1 ); COLORREF mask = RGB( 0, 255, 255 ); HBITMAP bitmap = ( HBITMAP )LoadImage( Instance(), MAKEINTRESOURCE( IDB_FOLDER_CLOSED ), IMAGE_BITMAP, 0, 0, 0 ); ImageList_AddMasked( lookInImages, bitmap, mask ); DeleteObject( bitmap ); // ImageList_Add copies object bitmap = ( HBITMAP )LoadImage( Instance(), MAKEINTRESOURCE( IDB_FOLDER_OPEN ), IMAGE_BITMAP, 0, 0, 0 ); ImageList_AddMasked( lookInImages, bitmap, mask ); DeleteObject( bitmap ); // ImageList_Add copies object bitmap = ( HBITMAP )LoadImage( Instance(), MAKEINTRESOURCE( IDB_DEPOT ), IMAGE_BITMAP, 0, 0, 0 ); ImageList_AddMasked( lookInImages, bitmap, mask ); DeleteObject( bitmap ); // ImageList_Add copies object SendMessage( combo, CBEM_SETIMAGELIST, 0, ( LPARAM )lookInImages ); } void OpenDepotDialog::SetupReportColumns( HWND list ) { LV_COLUMN col; // Filename column col.mask = LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.cx = 200; col.iSubItem = 0; col.pszText = _T("Name"); ListView_InsertColumn( list, 0, &col ); // Have revision column col.mask = LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; col.fmt = LVCFMT_RIGHT; col.cx = 110; col.iSubItem = 1; col.pszText = _T("Have Revision"); ListView_InsertColumn( list, 1, &col ); // Head revision column col.mask = LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; col.fmt = LVCFMT_RIGHT; col.cx = 110; col.iSubItem = 2; col.pszText = _T("Head Revision"); ListView_InsertColumn( list, 2, &col ); // File type column col.mask = LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.cx = 60; col.iSubItem = 3; col.pszText = _T("Type"); ListView_InsertColumn( list, 3, &col ); } void OpenDepotDialog::SelectLookInFolder( HWND combo, int selected ) { int count = SendMessage( combo, CB_GETCOUNT, 0, 0 ); int last = selected; TCHAR path[MAX_PATH]; // Get text and indent of selected item COMBOBOXEXITEM info; info.mask = CBEIF_INDENT | CBEIF_TEXT; info.iItem = selected; info.pszText = path; info.cchTextMax = MAX_PATH; SendMessage( combo, CBEM_GETITEM, 0, ( LPARAM )&info ); // Selected item is a Depot if ( info.iIndent == 0 ) { info.mask = CBEIF_INDENT; // Remove all non depot entries for ( int i=count-1; i >= 0; i-- ) { info.iItem = i; SendMessage( combo, CBEM_GETITEM, 0, ( LPARAM )&info ); if ( info.iIndent > 0 ) { SendMessage( combo, CBEM_DELETEITEM, i, 0 ); } } SetCurrDepot( path ); } // Selected item is a folder else { info.mask = CBEIF_INDENT; // Get last item we need to delete. // This will be the last folder before the next depot or end of list for ( int i=selected + 1; i<count; i++ ) { info.iItem = i; SendMessage( combo, CBEM_GETITEM, 0, ( LPARAM )&info ); // This item is a depot so break if ( info.iIndent == 0 ) { break; } last = i; } // Remove all items between last and curr selected. for ( int i=last; i != selected; i-- ) { SendMessage( combo, CBEM_DELETEITEM, i, 0 ); PopFolder(); } } SendMessage( combo, CB_SETCURSEL, ( WPARAM )selected, 0); } void OpenDepotDialog::Tooltips( LPNMTBGETINFOTIP tooltipEvent ) { switch ( tooltipEvent->iItem ) { case IDM_LARGEICON: _tcscpy( tooltipEvent->pszText, _T( "Large Icons" ) ); break; case IDM_SMALLICON: _tcscpy( tooltipEvent->pszText, _T("Small Icons") ); break; case IDM_LISTVIEW: _tcscpy( tooltipEvent->pszText, _T("List") ); break; case IDM_REPORTVIEW: _tcscpy( tooltipEvent->pszText, _T("Details") ); break; case IDM_PARENTFOLDER: _tcscpy( tooltipEvent->pszText, _T("Up One Level") ); break; } } void OpenDepotDialog::CreateToolbar( HWND dialog, HWND combo ) { static TBBUTTON buttons1[] = { {VIEW_PARENTFOLDER, IDM_PARENTFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, }; static TBBUTTON buttons2[] = { {VIEW_LARGEICONS, IDM_LARGEICON, TBSTATE_ENABLED | TBSTATE_CHECKED, BTNS_BUTTON | BTNS_CHECKGROUP, {0}, 0, 0}, {VIEW_SMALLICONS, IDM_SMALLICON, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_CHECKGROUP, {0}, 0, 0}, {VIEW_LIST, IDM_LISTVIEW, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_CHECKGROUP, {0}, 0, 0}, {VIEW_DETAILS, IDM_REPORTVIEW, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_CHECKGROUP, {0}, 0, 0}, }; static TBADDBITMAP bitmaps = {HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR}; toolbar1 = CreateWindowEx( 0, TOOLBARCLASSNAME, (TCHAR *) NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | WS_TABSTOP, 0, 0, 0, 0, dialog, ( HMENU )IDC_FOLDER_TOOLBAR, Instance(), NULL ); toolbar2 = CreateWindowEx( 0, TOOLBARCLASSNAME, (TCHAR *) NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | WS_TABSTOP, 0, 0, 0, 0, dialog, ( HMENU )IDC_LIST_TOOLBAR, Instance(), NULL ); // Set tab order HWND lookIn = GetDlgItem( dialog, IDC_LOOK_IN_COMBO ); SetWindowPos( toolbar1, lookIn, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); SetWindowPos( toolbar2, toolbar1, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); // Set version of TBBUTTON structure SendMessage( toolbar1, TB_BUTTONSTRUCTSIZE, ( WPARAM )sizeof( TBBUTTON ), 0 ); SendMessage( toolbar2, TB_BUTTONSTRUCTSIZE, ( WPARAM )sizeof( TBBUTTON ), 0 ); // Set toolbar images SendMessage( toolbar1, TB_ADDBITMAP, 0, (LPARAM)&bitmaps ); SendMessage( toolbar2, TB_ADDBITMAP, 0, (LPARAM)&bitmaps ); int nbuttons1 = sizeof( buttons1 )/sizeof( TBBUTTON ); int nbuttons2 = sizeof( buttons2 )/sizeof( TBBUTTON ); // Set toolbar buttons SendMessage( toolbar1, TB_ADDBUTTONS, (WPARAM) nbuttons1, (LPARAM) &buttons1 ); SendMessage( toolbar2, TB_ADDBUTTONS, (WPARAM) nbuttons2, (LPARAM) &buttons2 ); // Set toolbar size SendMessage( toolbar1, TB_AUTOSIZE, (WPARAM) 0, (LPARAM) 0 ); SendMessage( toolbar2, TB_AUTOSIZE, (WPARAM) 0, (LPARAM) 0 ); // Move toolbars to right of combo RECT comboRect; GetControlPos( dialog, combo, &comboRect ); // The TB_AUTOSIZE does not seem to set toolbar width and height // so need to set explicitly MoveWindow( toolbar1, comboRect.right + 10, comboRect.top, TB_BUTTON_WIDTH * nbuttons1, TB_BUTTON_HEIGHT, FALSE ); MoveWindow( toolbar2, comboRect.right + 40, comboRect.top, TB_BUTTON_WIDTH * nbuttons2, TB_BUTTON_HEIGHT, FALSE ); ShowWindow( toolbar1, SW_SHOW ); ShowWindow( toolbar2, SW_SHOW ); } BOOL CALLBACK OpenDepotDialog::DialogWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { DWORD dwStyle; HWND fileList = GetDlgItem( hWnd, IDC_DEPOT_LIST ); HWND lookIn = GetDlgItem( hWnd, IDC_LOOK_IN_COMBO ); HWND openFile = GetDlgItem( hWnd, IDC_OPEN_FILE_EDIT ); HWND fileTypes = GetDlgItem( hWnd, IDC_FILE_TYPE_COMBO ); HWND fileNameLabel = GetDlgItem( hWnd, IDC_FILE_NAME_LABEL ); HWND fileTypeLabel = GetDlgItem( hWnd, IDC_FILE_TYPE_LABEL ); HWND okButton = GetDlgItem( hWnd, IDOK ); HWND cancelButton = GetDlgItem( hWnd, IDCANCEL ); switch(uMsg) { case WM_INITDIALOG: { OpenDepotDialog *dialog = ( OpenDepotDialog * )lParam; dialog->SaveDialogObject( hWnd, dialog ); SetupReportColumns( fileList ); SetListViewImageLists( fileList ); dialog->SetupLookInImageLists( lookIn ); dialog->CreateToolbar( hWnd, lookIn ); dialog->InitFileTypes( fileTypes ); dialog->InitCaption( hWnd ); origListViewProc = (WNDPROC)SetWindowLong( fileList, GWL_WNDPROC, (LONG)ListViewEnterHandler ); try { dialog->InitCurrDir( lookIn ); dialog->ShowCurrFolder( fileList, fileTypes ); } catch ( std::exception e ) { dialog->SetError( hWnd, &e ); } SaveInitialSizes( hWnd ); SetResizeFlags( fileList, RESIZE_HEIGHT | RESIZE_WIDTH ); SetResizeFlags( openFile, RESIZE_TOP | RESIZE_WIDTH ); SetResizeFlags( fileTypes, RESIZE_TOP | RESIZE_WIDTH ); SetResizeFlags( fileNameLabel, RESIZE_TOP ); SetResizeFlags( fileTypeLabel, RESIZE_TOP ); SetResizeFlags( lookIn, RESIZE_WIDTH ); SetResizeFlags( dialog->toolbar1, RESIZE_LEFT ); SetResizeFlags( dialog->toolbar2, RESIZE_LEFT ); SetResizeFlags( okButton, RESIZE_TOP | RESIZE_LEFT ); SetResizeFlags( cancelButton, RESIZE_TOP | RESIZE_LEFT ); // Restore size of dialog int width = dialog->options->GetOptionValue( PERFORCE_OPEN_WIDTH ); int height = dialog->options->GetOptionValue( PERFORCE_OPEN_HEIGHT ); if ( width > 0 && height > 0 ) { MoveWindow( hWnd, 0, 0, width, height, TRUE ); RECT rect; GetClientRect( hWnd, &rect ); Resize( hWnd, MAKELONG( rect.right, rect.bottom ) ); } Centre( hWnd ); long button; long style = dialog->options->GetOptionValue( PERFORCE_OPEN_VIEW_TYPE ); switch ( style ) { case LVS_ICON: button = IDM_LARGEICON; break; case LVS_SMALLICON: button = IDM_SMALLICON; break; case LVS_LIST: button = IDM_LISTVIEW; break; case LVS_REPORT: button = IDM_REPORTVIEW; break; } SendMessage( dialog->toolbar2, (UINT) TB_CHECKBUTTON, (WPARAM)button, (LPARAM)TRUE ); DWORD dwStyle = GetWindowLong( fileList, GWL_STYLE ); SetWindowLong( fileList, GWL_STYLE, ( dwStyle & ~LVS_TYPEMASK ) | style ); return true; break; } case WM_GETMINMAXINFO: SetMinimumSize( hWnd, (LPMINMAXINFO) lParam ); return true; break; case WM_SIZE: { Resize( hWnd, lParam ); return true; break; } case WM_PAINT: { OpenDepotDialog *dialog = ( OpenDepotDialog * )DialogObject( hWnd ); dialog->PaintSizeGrip( hWnd ); break; } case WM_NCHITTEST: { return HitTestSizeGrip( hWnd, lParam ); } case WM_NOTIFY: { LPNMHDR listEvent = ( LPNMHDR ) lParam; OpenDepotDialog *dialog = ( OpenDepotDialog * )DialogObject( hWnd ); if ( (int)wParam == IDC_DEPOT_LIST ) { if ( listEvent->code == NM_DBLCLK ) { LPNMITEMACTIVATE clickEvent = ( LPNMITEMACTIVATE ) lParam; // Make sure click is on an item if ( clickEvent->iItem >= 0 ) { TCHAR path[MAX_PATH]; UniStrDict *dict; GetItemInfo( listEvent->hwndFrom, clickEvent->iItem, &dict, path ); // If item is a folder and it was double clicked if ( IsFolder( dict ) ) { EnterFolder( hWnd, path ); } // double click item is file else { EndDialog( hWnd, TRUE ); } } return true; } else if ( listEvent->code == LVN_ITEMCHANGED ) { LPNMLISTVIEW changedEvent = ( LPNMLISTVIEW ) lParam; if ( changedEvent->iItem >= 0 ) { TCHAR path[MAX_PATH]; UniStrDict *dict; BOOL selected; GetItemInfo( listEvent->hwndFrom, changedEvent->iItem, &dict, path, &selected ); if ( selected && !IsFolder( dict ) ) { dialog->SetSelectedFile( path ); SetDlgItemText( hWnd, IDC_OPEN_FILE_EDIT, path ); } } } // Column header click else if ( listEvent->code == LVN_COLUMNCLICK ) { LPNMLISTVIEW item = ( LPNMLISTVIEW ) lParam; dialog->sortCol = item->iSubItem; // Get column for sort and change order switch ( dialog->sortCol ) { case 0: dialog->nameOrder *= -1; dialog->sortOrder = dialog->nameOrder; break; case 1: dialog->haveOrder *= -1; dialog->sortOrder = dialog->haveOrder; break; case 2: dialog->headOrder *= -1; dialog->sortOrder = dialog->headOrder; break; case 3: dialog->typeOrder *= -1; dialog->sortOrder = dialog->typeOrder; break; } ListView_SortItems( fileList, Compare, (LPARAM) dialog ); } } // Toolbar tooltips else if ( ( (int)wParam == IDC_LIST_TOOLBAR || (int)wParam == IDC_FOLDER_TOOLBAR ) && listEvent->code == TBN_GETINFOTIP ) { dialog->Tooltips( (LPNMTBGETINFOTIP) lParam ); return true; } } break; case WM_COMMAND: OpenDepotDialog *dialog = ( OpenDepotDialog * )DialogObject( hWnd ); switch ( LOWORD( wParam ) ) { case IDC_OPEN_FILE_EDIT: // Handle manual edit of filename field if ( HIWORD( wParam ) == EN_KILLFOCUS ) { TCHAR path[MAX_PATH]; GetDlgItemText( hWnd, IDC_OPEN_FILE_EDIT, path, MAX_PATH ); dialog->SetSelectedFile( path ); return true; } break; case IDC_LOOK_IN_COMBO: // Selected a folder from the Look In combo if ( HIWORD( wParam ) == CBN_SELCHANGE ) { dialog->SelectLookInFolder( lookIn, SendMessage( lookIn, CB_GETCURSEL, 0, 0 ) ); try { dialog->ShowCurrFolder( fileList, fileTypes ); } catch ( std::exception e ) { dialog->SetError( hWnd, &e ); } return true; } break; case IDC_FILE_TYPE_COMBO: // Changed the file type if ( HIWORD( wParam ) == CBN_SELCHANGE ) { try { dialog->ShowCurrFolder( fileList, fileTypes, false ); } catch ( std::exception e ) { dialog->SetError( hWnd, &e ); } return true; } break; case IDM_PARENTFOLDER: // Go up a level dialog->SelectLookInFolder( lookIn, SendMessage( lookIn, CB_GETCURSEL, 0, 0 ) - 1); try { dialog->ShowCurrFolder( fileList, fileTypes ); } catch ( std::exception e ) { dialog->SetError( hWnd, &e ); } return true; case IDM_LARGEICON: dwStyle = GetWindowLong( fileList, GWL_STYLE ); SetWindowLong( fileList, GWL_STYLE, ( dwStyle & ~LVS_TYPEMASK ) | LVS_ICON ); return true; case IDM_SMALLICON: dwStyle = GetWindowLong( fileList, GWL_STYLE ); SetWindowLong( fileList, GWL_STYLE, ( dwStyle & ~LVS_TYPEMASK ) | LVS_SMALLICON ); return true; case IDM_LISTVIEW: dwStyle = GetWindowLong( fileList, GWL_STYLE ); SetWindowLong( fileList, GWL_STYLE, ( dwStyle & ~LVS_TYPEMASK ) | LVS_LIST ); return true; case IDM_REPORTVIEW: dwStyle = GetWindowLong( fileList, GWL_STYLE ); SetWindowLong( fileList, GWL_STYLE, ( dwStyle & ~LVS_TYPEMASK ) | LVS_REPORT ); return true; case IDOK: TCHAR path[MAX_PATH]; // Only allow OK if have selected a file GetDlgItemText( hWnd, IDC_OPEN_FILE_EDIT, path, MAX_PATH ); if ( _tcslen( path ) > 0 ) { dialog->SaveSettings( hWnd ); FinishDialog( hWnd, TRUE ); } return true; case IDCANCEL: dialog->SaveSettings( hWnd ); FinishDialog( hWnd, FALSE ); return true; } } return false; } void OpenDepotDialog::SaveSettings( HWND hWnd ) { HWND fileList = GetDlgItem( hWnd, IDC_DEPOT_LIST ); HWND fileTypes = GetDlgItem( hWnd, IDC_FILE_TYPE_COMBO ); // Save view type DWORD dwStyle = GetWindowLong( fileList, GWL_STYLE ); dwStyle &= LVS_TYPEMASK; options->SetOptionValue( PERFORCE_OPEN_VIEW_TYPE, dwStyle ); // Save current directory options->SetOptionString( PERFORCE_OPEN_DIR, currDir.Text() ); // Save file type options->SetOptionValue( PERFORCE_OPEN_FILE_TYPE, SendMessage( fileTypes, CB_GETCURSEL, 0, 0 ) ); // Save size of dialog RECT rect; GetWindowRect( hWnd, &rect ); options->SetOptionValue( PERFORCE_OPEN_WIDTH, rect.right - rect.left ); options->SetOptionValue( PERFORCE_OPEN_HEIGHT, rect.bottom - rect.top ); } void OpenDepotDialog::SelectDepot( HWND combo, long idx ) { SendMessage( combo, CB_SETCURSEL, (WPARAM)idx, 0 ); TCHAR buff[MAX_PATH]; SendMessage( combo, CB_GETLBTEXT, (WPARAM)idx, (LPARAM)buff ); SetCurrDepot( buff ); } void OpenDepotDialog::SetCurrDepot( TCHAR *name ) { currDir.Set( _T("//") ); currDir.Append( name ); } void OpenDepotDialog::InitCurrDir( HWND combo ) { // Go and get all the depots PerforceCommand cmd( _T("depots") ); PerforceResults results; con->Exec( &cmd, &results ); // p4 depots returns nothing unless you have actually gone and // created a depot if ( results.Count() == 0 ) { AddLookInItem( combo, -1, _T("depot"), 0 ); } else if ( results.Count() > 0 ) { UniStrBuf depot; for ( int i=0; i<results.Count(); i++ ) { UniStrDict *dict = ( UniStrDict * )results.Get( i ); StrPtr *depotInfo = ( StrPtr * )dict->GetVar( "msg" ); if ( depotInfo != NULL ) { TCHAR *start = _tcschr( (TCHAR *)depotInfo->Text(), ' ' ); start = _tcsinc( start ); TCHAR *end = _tcschr( start, ' ' ); depot.Set( start, (end - start) * sizeof(TCHAR) ); AddLookInItem( combo, -1, depot.Text(), 0 ); } } } UniStrBuf currentDir; bool validDir = false; if ( options->GetOptionString( PERFORCE_OPEN_DIR, ¤tDir ) ) { // Check the saved directory still exists PerforceCommand dirsCmd( _T("dirs"), _T("-C"), currentDir.Text() ); // Errors will get thrown con->Exec( &dirsCmd, &results ); if ( results.Count() > 0 ) { TCHAR *start = currentDir.Text(); start = _tcsinc( start ); start = _tcsinc( start ); TCHAR *end; UniStrBuf buff; // Extract name of depot end = _tcschr( start, '/' ); if ( end ) { buff.Set( start, (end - start) * sizeof( TCHAR ) ); } else { buff.Set( start ); } long idx = SendMessage( combo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)buff.Text() ); if ( idx != CB_ERR ) { // Select the depot SelectDepot( combo, idx ); // Go and select each directory in the path if ( end = _tcschr( start, '/'), end != NULL ) { start = _tcsinc( end ); while ( end = _tcschr( start, '/' ), end != NULL ) { buff.Set( start, (end - start) * sizeof( TCHAR ) ); OpenDir( combo, buff.Text() ); start = _tcsinc( end ); } OpenDir( combo, start ); } validDir = true; } } } if ( !validDir ) { // Select first depot SelectDepot( combo, 0 ); } } void OpenDepotDialog::OpenDir( HWND combo, TCHAR *dir ) { // Get Indentation of currently selected folder int selected = SendMessage( combo, CB_GETCURSEL, 0, 0 ); COMBOBOXEXITEM info; info.mask = CBEIF_INDENT; info.iItem = selected; SendMessage(combo, CBEM_GETITEM, 0, (LPARAM)&info); // Add selected folder to Look In Combo AddLookInItem( combo, selected + 1, dir, info.iIndent + 1 ); // Make new folder the current selection SendMessage(combo, CB_SETCURSEL, (WPARAM)selected + 1, 0); PushFolder( dir ); } void OpenDepotDialog::PushFolder( TCHAR *folder ) { currDir.Append( _T("/") ); currDir.Append( folder ); } void OpenDepotDialog::PopFolder() { int len = _tcsrchr( currDir.Text(), '/' ) - currDir.Text(); currDir.Set( currDir.Text(), len * sizeof(TCHAR) ); } void OpenDepotDialog::InsertFolder( HWND list, int pos, UniStrDict *dict ) { StrPtr *name = ( StrPtr * )dict->GetVar( "dir" ); LV_ITEM item; item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iSubItem = 0; item.iItem = pos; item.iImage = FolderIcon(); item.pszText = ExtractFilename( name ); item.lParam = (LPARAM)dict; ListView_InsertItem( list, &item ); } void OpenDepotDialog::InsertFile( HWND list, int pos, UniStrDict *dict ) { StrPtr *name = ( StrPtr * )dict->GetVar( "depotFile" ); StrPtr *have = (StrPtr *)dict->GetVar( "haveRev" ); StrPtr *head = (StrPtr *)dict->GetVar( "headRev" ); StrPtr *type = (StrPtr *)dict->GetVar( "headType" ); LV_ITEM item; item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iSubItem = 0; item.iItem = pos; item.iImage = FileIcon( name ); item.pszText = ExtractFilename( name ); item.lParam = (LPARAM)dict; ListView_InsertItem(list, &item ); item.mask = LVIF_TEXT; item.iSubItem = 1; if (have) { item.pszText = (TCHAR *)have->Text(); } else { item.pszText = _T("0"); } ListView_SetItem( list, &item ); item.iSubItem = 2; item.pszText = (TCHAR *)head->Text(); ListView_SetItem( list, &item ); item.iSubItem = 3; item.pszText = (TCHAR *)type->Text(); ListView_SetItem( list, &item ); } void OpenDepotDialog::ShowCurrFolder( HWND list, HWND fileTypes, bool refresh ) { ListView_DeleteAllItems(list); UniStrBuf buff; buff.Set( currDir.Text() ); buff.Append( _T("/*") ); int pos = 0; // Get all the folders if ( refresh ) { PerforceCommand foldersCmd( _T("dirs"), _T("-C"), buff.Text() ); con->Exec( &foldersCmd, &dirResults ); } // If there are no folders in the directory then we just // get a message saying: // //depot/foo/bar/* - no such file(s). for ( int i=0; i<dirResults.Count(); i++ ) { UniStrDict *dict = ( UniStrDict * )dirResults.Get( i ); if ( dict->GetVar( "dir" ) != NULL ) { InsertFolder( list, pos++, dict ); } } try { // Get all files if ( refresh ) { PerforceCommand filesCmd( _T("fstat"), buff.Text() ); con->Exec( &filesCmd, &fileResults ); } for ( int i=0; i<fileResults.Count(); i++ ) { UniStrDict *dict = ( UniStrDict * )fileResults.Get( i ); StrPtr *name = ( StrPtr * )dict->GetVar( "depotFile" ); if ( name != NULL ) { StrPtr *headAction = ( StrPtr * )dict->GetVar( "headAction" ); // Don't include deleted files (or newly added files when headAction == NULL) // or files not mapped to client if ( headAction && _tcscmp( (TCHAR *)headAction->Text(), _T("delete") ) != 0 && dict->GetVar("clientFile") != NULL ) { // Check filename matches current type filter if ( MatchFileType( fileTypes, (TCHAR *)( ( StrPtr * )dict->GetVar( "depotFile" ) )->Text() ) ) { InsertFile( list, pos++, dict ); } } } } } catch ( std::exception e ) { // Ignore errors of the form: // //depot/* - protected namespace - access denied. // This can happen when doing an fstat on a directory for which the user // does not have permissions if ( strstr( e.what(), "protected namespace" ) == NULL ) { throw e; } } // Update state of Up Level button SendMessage( toolbar1, ( UINT ) TB_ENABLEBUTTON, ( WPARAM ) IDM_PARENTFOLDER, ( LPARAM ) MAKELONG( !InRootFolder(), 0 ) ); if ( ListView_GetItemCount( list ) > 0 ) { ListView_SetItemState( list, 0, LVIS_FOCUSED, LVIS_FOCUSED ); } } bool OpenDepotDialog::InRootFolder() { TCHAR *start = currDir.Text(); start = _tcsinc( start ); start = _tcsinc( start ); if ( _tcschr( start, '/' ) != NULL ) { return false; } else { return true; } } void OpenDepotDialog::SetSelectedFile( TCHAR *name ) { selectedFile = currDir; selectedFile.Append( _T("/") ); selectedFile.Append( name ); } StrPtr *OpenDepotDialog::SelectedFile() { // Sync file PerforceCommand syncCmd( _T("sync"), selectedFile.Text() ); PerforceResults results; con->Exec( &syncCmd, &results ); TRACE1(_T("p4dialog sync results:"), results.GetText()); // Get and return the client path PerforceCommand statCmd( _T("fstat"), selectedFile.Text() ); con->Exec( &statCmd, &results ); if ( results.Count() > 0 ) { UniStrDict *dict = ( UniStrDict * )results.Get( 0 ); StrPtr *clientFile = ( StrPtr * )dict->GetVar( "clientFile" ); if ( clientFile != NULL ) { selectedFile.Set( (TCHAR *)clientFile->Text() ); return &selectedFile; } } return NULL; } bool OpenDepotDialog::IsFolder( UniStrDict *dict ) { if ( dict->GetVar( "dir" ) ) { return true; } else { return false; } } int CALLBACK OpenDepotDialog::Compare( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) { OpenDepotDialog *dialog = (OpenDepotDialog *)lParamSort; UniStrDict *dict1 = (UniStrDict *)lParam1; UniStrDict *dict2 = (UniStrDict *)lParam2; bool strval; char *name; switch ( dialog->sortCol ) { case 0: strval = true; name = "depotFile"; break; case 1: strval = false; name = "haveRev"; break; case 2: strval = false; name = "headRev"; break; case 3: strval = true; name = "headType"; break; } TCHAR *val1, *val2; UniStrBuf buf1, buf2; if ( dialog->sortCol == 0 ) { if ( IsFolder( dict1 ) ) { // Group folders last buf1.Set( _T("ZZZZ") ); buf1.Append( ExtractFilename( ( StrPtr * )dict1->GetVar( "dir" ) ) ); val1 = buf1.Text(); } else { val1 = ExtractFilename( ( StrPtr * )dict1->GetVar( "depotFile" ) ); } if ( IsFolder( dict2 ) ) { // Group folders last buf2.Set( _T("ZZZZ") ); buf2.Append( ExtractFilename( ( StrPtr * )dict2->GetVar( "dir" ) ) ); val2 = buf2.Text(); } else { val2 = ExtractFilename( ( StrPtr * )dict2->GetVar( "depotFile" ) ); } } else { val1 = IsFolder( dict1 ) ? _T("") : (TCHAR *)dict1->GetVar( name )->Text(); val2 = IsFolder( dict2 ) ? _T("") : (TCHAR *)dict2->GetVar( name )->Text(); } int result; if ( strval ) { result = _tcsicmp( val1, val2 ); } else { long num1 = _tcstol( val1, NULL, 10 ); long num2 = _tcstol( val2, NULL, 10 ); if ( num1 < num2 ) { result = -1; } else if ( num2 < num1 ) { result = 1; } else { result = 0; } } return result * dialog->sortOrder; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 10843 | Robert Cowham |
Initial version of P4OFC source code. See README.txt (and LICENSE.txt and doc\P4OFC-Design.docx) |