|
NCBI C++ ToolKit
|
00001 /* $Id: project_tree_panel.cpp 25238 2012-02-14 16:11:43Z ucko $ 00002 * =========================================================================== 00003 * 00004 * PUBLIC DOMAIN NOTICE 00005 * National Center for Biotechnology Information 00006 * 00007 * This software/database is a "United States Government Work" under the 00008 * terms of the United States Copyright Act. It was written as part of 00009 * the author's official duties as a United States Government employee and 00010 * thus cannot be copyrighted. This software/database is freely available 00011 * to the public for use. The National Library of Medicine and the U.S. 00012 * Government have not placed any restriction on its use or reproduction. 00013 * 00014 * Although all reasonable efforts have been taken to ensure the accuracy 00015 * and reliability of the software and data, the NLM and the U.S. 00016 * Government do not and cannot warrant the performance or results that 00017 * may be obtained by using this software or data. The NLM and the U.S. 00018 * Government disclaim all warranties, express or implied, including 00019 * warranties of performance, merchantability or fitness for any particular 00020 * purpose. 00021 * 00022 * Please cite the author in any work or product based on this material. 00023 * 00024 * =========================================================================== 00025 * 00026 * Authors: Andrey Yazhuk 00027 * 00028 * File Description: 00029 * 00030 */ 00031 00032 #include <ncbi_pch.hpp> 00033 00034 #include <gui/core/project_tree_panel.hpp> 00035 00036 #include <gui/core/commands.hpp> 00037 #include <gui/core/app_explorer_service.hpp> 00038 #include <gui/core/project_service.hpp> 00039 #include <gui/core/project_task.hpp> 00040 #include <gui/core/fname_validator_imp.hpp> 00041 00042 #include <gui/framework/workbench.hpp> 00043 #include <gui/framework/view_manager_service.hpp> 00044 #include <gui/framework/window_manager_service.hpp> 00045 #include <gui/framework/app_task_service.hpp> 00046 #include <gui/framework/menu_service.hpp> 00047 00048 #include <gui/widgets/wx/ui_command.hpp> 00049 #include <gui/widgets/wx/message_box.hpp> 00050 #include <gui/widgets/wx/wx_utils.hpp> 00051 00052 #include <gui/utils/extension_impl.hpp> 00053 00054 00055 #include <wx/artprov.h> 00056 #include <wx/sizer.h> 00057 #include <wx/panel.h> 00058 #include <wx/menu.h> 00059 #include <wx/wupdlock.h> 00060 #include <wx/frame.h> 00061 00062 00063 BEGIN_NCBI_SCOPE 00064 USING_SCOPE(objects); 00065 00066 /////////////////////////////////////////////////////////////////////////////// 00067 /// CExplorerItemData - tree item attachment pointing back to CExplorerItem. 00068 class CExplorerItemData : public wxTreeItemData 00069 { 00070 public: 00071 CExplorerItemData(CExplorerItem& item) 00072 : m_Item(&item) {} 00073 CExplorerItemData(const CExplorerItem& item) 00074 : m_Item(const_cast<CExplorerItem*>(&item)) {} 00075 CExplorerItemData(CExplorerItem* item) : m_Item(item) {} 00076 00077 CRef<CExplorerItem> m_Item; 00078 }; 00079 00080 /////////////////////////////////////////////////////////////////////////////// 00081 /// CProjectTreeViewDropTarget 00082 CProjectTreeViewDropTarget::CProjectTreeViewDropTarget(CProjectTreePanel* panel) 00083 : wxDropTarget(new CAppExplorerDataObject()), 00084 m_Panel(panel), 00085 m_AcceptableData(false) 00086 { 00087 } 00088 00089 00090 wxDragResult CProjectTreeViewDropTarget::OnEnter(wxCoord x, wxCoord y, wxDragResult def) 00091 { 00092 m_AcceptableData = true; 00093 return OnDragOver(x, y, def); 00094 } 00095 00096 00097 wxDragResult CProjectTreeViewDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult def) 00098 { 00099 if(m_AcceptableData) { 00100 return m_Panel->OnDragOver(x, y, def); 00101 } 00102 return wxDragNone; 00103 } 00104 00105 00106 wxDragResult CProjectTreeViewDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult def) 00107 { 00108 GetData(); 00109 CAppExplorerDataObject* data_obj = dynamic_cast<CAppExplorerDataObject*>(m_dataObject); 00110 m_Panel->OnDrop(x, y, def, *data_obj); 00111 return def; 00112 } 00113 00114 BEGIN_EVENT_TABLE(CProjectTreeCtrl, wxTreeCtrl) 00115 EVT_LEFT_UP( CProjectTreeCtrl::OnLeftDown) 00116 EVT_KEY_UP(CProjectTreeCtrl::OnKeyUp) 00117 EVT_MOTION( CProjectTreeCtrl::OnMove ) 00118 END_EVENT_TABLE() 00119 /////////////////////////////////////////////////////////////////////////////// 00120 /// CProjectTreeCtrl 00121 wxTextCtrl *CProjectTreeCtrl::EditLabel(const wxTreeItemId& item, wxClassInfo* textCtrlClass) 00122 { 00123 wxTextCtrl* t = wxTreeCtrl::EditLabel(item, textCtrlClass); 00124 00125 // In windows, when an item in the tree is selected for editing, all characters 00126 // are selected by default. This is not true on the Mac, but the EditLabel function 00127 // does return the edit control so we can use that to select the text. The 00128 // documentation however says that EditLabel returns NULL. Restrict it to 00129 // to MAC only since that is where it is needed and it is not validated on other platforms. 00130 #ifdef NCBI_OS_DARWIN 00131 if (t!=NULL) 00132 t->SelectAll(); 00133 #endif 00134 00135 return t; 00136 } 00137 00138 void CProjectTreeCtrl::OnLeftDown(wxMouseEvent& event) 00139 { 00140 CProjectTreePanel* tree_panel = dynamic_cast<CProjectTreePanel*>(GetParent()); 00141 if( tree_panel ){ 00142 wxTreeEvent tree_event; 00143 tree_panel->OnSelectionChanged( tree_event ); 00144 } 00145 00146 event.Skip(); 00147 } 00148 00149 void CProjectTreeCtrl::OnKeyUp(wxKeyEvent& event) 00150 { 00151 // Keep track of cmd(osx)/ctrl(other os) key status since it changes whether 00152 // drag and drop is a copy or a move (cmd/ctrl down=> copy) 00153 CProjectTreePanel* tree_panel = dynamic_cast<CProjectTreePanel*>(GetParent()); 00154 bool b = event.CmdDown(); 00155 tree_panel->SetCopyMode(b); 00156 event.Skip(); 00157 } 00158 00159 void CProjectTreeCtrl::OnMove(wxMouseEvent& event) 00160 { 00161 #ifdef __WXOSX_COCOA__ 00162 // Tree's built-in drag and drop does not have a 'isdragging' event so 00163 // we call the 'OnDragOver' on all mouse moves and it checks if a 00164 // drag is actually in progress. 00165 CProjectTreePanel* tree_panel = dynamic_cast<CProjectTreePanel*>(GetParent()); 00166 if( tree_panel ){ 00167 // The result is ignored (it is used by the other drag method - this method is only 00168 // for the osx/cocoa case.) 00169 wxDragResult ignore_me = wxDragMove; 00170 wxCoord x,y; 00171 event.GetPosition(&x,&y); 00172 tree_panel->OnDragOver(x, y, ignore_me); 00173 } 00174 #endif 00175 00176 event.Skip(); 00177 } 00178 00179 /////////////////////////////////////////////////////////////////////////////// 00180 /// CProjectTreePanel 00181 00182 BEGIN_EVENT_TABLE(CProjectTreePanel, wxPanel) 00183 EVT_CONTEXT_MENU(CProjectTreePanel::OnContextMenu) 00184 00185 EVT_TREE_ITEM_COLLAPSED(wxID_ANY, CProjectTreePanel::OnItemExpandedCollapsed) 00186 EVT_TREE_ITEM_EXPANDED(wxID_ANY, CProjectTreePanel::OnItemExpandedCollapsed) 00187 EVT_TREE_ITEM_ACTIVATED(wxID_ANY, CProjectTreePanel::OnItemActivated) 00188 EVT_TREE_KEY_DOWN(wxID_ANY, CProjectTreePanel::OnTreeKeyDown) 00189 EVT_TREE_BEGIN_LABEL_EDIT(wxID_ANY, CProjectTreePanel::OnBeginLabelEdit) 00190 EVT_TREE_END_LABEL_EDIT(wxID_ANY, CProjectTreePanel::OnEndLabelEdit) 00191 00192 EVT_TREE_SEL_CHANGED(wxID_ANY, CProjectTreePanel::OnSelectionChanged) 00193 00194 EVT_TREE_BEGIN_DRAG(wxID_ANY, CProjectTreePanel::OnBeginDrag) 00195 EVT_TREE_END_DRAG(wxID_ANY, CProjectTreePanel::OnEndDrag) 00196 00197 EVT_LEFT_UP( CProjectTreePanel::OnLeftDown) 00198 00199 EVT_MENU(wxID_CUT, CProjectTreePanel::OnCut) 00200 END_EVENT_TABLE() 00201 00202 00203 CProjectTreePanel::CProjectTreePanel() 00204 : m_DataObject(NULL), 00205 m_Workbench(NULL), 00206 m_ExplorerService(NULL), 00207 m_Tree(NULL), 00208 m_CopyMode(false) 00209 { 00210 Init(); 00211 } 00212 00213 00214 CProjectTreePanel::~CProjectTreePanel() 00215 { 00216 delete m_DataObject; 00217 m_DataObject = NULL; 00218 } 00219 00220 00221 void CProjectTreePanel::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size) 00222 { 00223 wxPanel::Create(parent, id, pos, size, wxBORDER_NONE); 00224 CreateControls(); 00225 } 00226 00227 00228 void CProjectTreePanel::Init() 00229 { 00230 m_ExplorerService = NULL; 00231 } 00232 00233 00234 void CProjectTreePanel::CreateControls() 00235 { 00236 wxSizer* sizer = new wxBoxSizer(wxVERTICAL); 00237 SetSizer(sizer); 00238 00239 long style = wxTR_HAS_BUTTONS | wxTR_MULTIPLE | wxTR_EDIT_LABELS 00240 | wxTR_HIDE_ROOT | wxBORDER_NONE 00241 ; 00242 #ifdef __WXGTK__ 00243 style |= wxTR_NO_LINES; 00244 #else 00245 style |= wxTR_LINES_AT_ROOT; 00246 #endif 00247 // create Tree Control 00248 m_Tree = new CProjectTreeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); 00249 sizer->Add(m_Tree, 1, wxEXPAND); 00250 00251 m_Tree->SetDropTarget(new CProjectTreeViewDropTarget(this)); 00252 } 00253 00254 00255 void CProjectTreePanel::SetWorkbench(IWorkbench* workbench) 00256 { 00257 m_Workbench = workbench; 00258 } 00259 00260 00261 void CProjectTreePanel::SetService(CAppExplorerService* service) 00262 { 00263 m_ExplorerService = service; 00264 if(m_ExplorerService) { 00265 m_Tree->SetImageList(&m_ExplorerService->GetIconsImageList()); 00266 } else { 00267 m_Tree->SetImageList(NULL); 00268 } 00269 RefreshItems(); 00270 } 00271 00272 00273 WX_DEFINE_MENU(kContextMenu) 00274 WX_MENU_SEPARATOR_L("Top Actions") 00275 WX_MENU_SEPARATOR_L("Actions") 00276 WX_MENU_SEPARATOR_L("Edit") 00277 WX_MENU_SEPARATOR_L("Properties") 00278 WX_END_MENU() 00279 00280 00281 void CProjectTreePanel::OnContextMenu(wxContextMenuEvent& event) 00282 { 00283 SetFocus(); 00284 00285 CUICommandRegistry& cmd_reg = m_Workbench->GetUICommandRegistry(); 00286 00287 TItemRefVector sel_items; 00288 GetSelectedItems(sel_items); 00289 00290 // create menu backbone 00291 wxMenu* menu = cmd_reg.CreateMenu(kContextMenu); 00292 00293 // get contributed menus 00294 vector< CIRef<IExplorerItemCmdContributor> > contributors; 00295 static string id("project_tree_view::context_menu::item_cmd_contributor"); 00296 GetExtensionAsInterface(id, contributors); 00297 00298 // Merge contributed menus into the main Menu 00299 for( size_t i = 0; i < contributors.size(); i++ ) { 00300 IExplorerItemCmdContributor& obj = *contributors[i]; 00301 IExplorerItemCmdContributor::TContribution 00302 contrib = obj.GetMenu(sel_items, *m_ExplorerService); 00303 /// update menu 00304 wxMenu* obj_menu = contrib.first; 00305 if(obj_menu) { 00306 Merge(*menu, *obj_menu); 00307 delete obj_menu; 00308 00309 /// register provided handler 00310 wxEvtHandler* handler = contrib.second; 00311 if(handler) { 00312 m_ContributedHandlers.push_back(handler); 00313 PushEventHandler(handler); 00314 } 00315 } else { 00316 _ASSERT(contrib.second == NULL); 00317 delete contrib.second; 00318 } 00319 } 00320 00321 CleanupSeparators(*menu); // Remove empty groups 00322 00323 PopupMenu(menu); 00324 00325 /// destroy the Menu 00326 delete menu; 00327 00328 /// disconnect and destroy contributed handlers 00329 for( size_t i = 0; i < m_ContributedHandlers.size(); i++ ) { 00330 wxEvtHandler* handler = PopEventHandler(); 00331 _ASSERT(handler == m_ContributedHandlers[i]); 00332 delete handler; 00333 } 00334 m_ContributedHandlers.clear(); 00335 } 00336 00337 00338 void CProjectTreePanel::RefreshItems() 00339 { 00340 //CStopWatch sw; sw.Start(); 00341 00342 wxColour cl_text = m_Tree->GetForegroundColour(); 00343 wxColour cl_back = m_Tree->GetBackgroundColour(); 00344 m_DisabledColor = GetAverage(cl_text, cl_back, 0.5); 00345 00346 wxWindowUpdateLocker locker(m_Tree); 00347 00348 // rebuild the tree 00349 m_Tree->DeleteAllItems(); 00350 00351 if(m_ExplorerService) { 00352 CRef<CExplorerItem> root = m_ExplorerService->GetRootItem(); 00353 if(root) { 00354 wxTreeItemId item_id = 00355 m_Tree->AddRoot(wxT(""), -1, -1, new CExplorerItemData(*root)); 00356 00357 x_AddChildItems(item_id, *root); 00358 } 00359 } 00360 00361 //LOG_POST(Info << "CProjectTreePanel::RefreshItems() " << int(1000 * sw.Elapsed()) << " ms"); 00362 } 00363 00364 00365 void CProjectTreePanel::x_AddChildItems(wxTreeItemId item_id, const CExplorerItem& item) 00366 { 00367 const CExplorerItem::TItemRefVector& child_items = item.GetChildItems(); 00368 00369 for( size_t i = 0; i < child_items.size(); i++ ) { 00370 const CExplorerItem& ch_item = *child_items[i]; 00371 00372 // create new tree item 00373 wxString s = ch_item.GetLabel(); 00374 int index = ch_item.GetIconIndex(wxTreeItemIcon_Normal); 00375 CExplorerItemData* data = new CExplorerItemData(ch_item); 00376 00377 wxTreeItemId ch_id = m_Tree->AppendItem(item_id, s, index, -1, data); 00378 00379 // set disabled look if needed 00380 if(ch_item.IsDisabled()) { 00381 m_Tree->SetItemTextColour(ch_id, m_DisabledColor); 00382 } 00383 00384 // set expanded icon 00385 index = ch_item.GetIconIndex(wxTreeItemIcon_Expanded); 00386 m_Tree->SetItemImage(ch_id, index, wxTreeItemIcon_Expanded); 00387 00388 // create subitems recursively 00389 x_AddChildItems(ch_id, ch_item); 00390 00391 if(ch_item.IsExpanded()) { 00392 m_Tree->Expand(ch_id); 00393 } else { 00394 m_Tree->Collapse(ch_id); 00395 } 00396 } 00397 } 00398 00399 00400 CExplorerItem* CProjectTreePanel::x_GetExplorerItem(const wxTreeItemId& id) 00401 { 00402 wxTreeItemData* data = m_Tree->GetItemData(id); 00403 CExplorerItemData* ex_data = dynamic_cast<CExplorerItemData*>(data); 00404 00405 _ASSERT(ex_data); 00406 00407 return ex_data->m_Item.GetPointer(); 00408 } 00409 00410 00411 // returns selection as a vector of pointers to CExplorerItem 00412 void CProjectTreePanel::GetSelectedItems(TItemRefVector& items) 00413 { 00414 wxArrayTreeItemIds sel_ids; 00415 m_Tree->GetSelections(sel_ids); 00416 00417 x_GetItemsFromIds(sel_ids, items); 00418 } 00419 00420 00421 void CProjectTreePanel::x_GetItemsFromIds(const wxArrayTreeItemIds& ids, 00422 TItemRefVector& items) 00423 { 00424 for( size_t i = 0; i < ids.GetCount(); i++ ) { 00425 wxTreeItemId id = ids[i]; 00426 CExplorerItem* item = x_GetExplorerItem(id); 00427 items.push_back(TItemRef(item)); 00428 } 00429 } 00430 00431 00432 CExplorerItem* CProjectTreePanel::x_GetSingleSelectedItem() 00433 { 00434 wxArrayTreeItemIds sel_ids; 00435 m_Tree->GetSelections(sel_ids); 00436 00437 if(sel_ids.size() == 1) { 00438 CExplorerItem* item = x_GetExplorerItem(sel_ids[0]); 00439 return item; 00440 } 00441 return NULL; 00442 } 00443 00444 00445 bool CProjectTreePanel::IsWorkspaceSelected() 00446 { 00447 TItemRefVector sel_items; 00448 GetSelectedItems(sel_items); 00449 00450 return m_ExplorerService->ContainsAllTypes(sel_items, CAppExplorerService::eWorkspace); 00451 } 00452 00453 00454 void CProjectTreePanel::GetSelectedProjectIds(TProjectIdVector& ids) 00455 { 00456 typedef CAppExplorerService::TProjectTreeItem TProjectTreeItem; 00457 00458 TItemRefVector sel_items; 00459 GetSelectedItems(sel_items); 00460 00461 CProjectService* prj_srv = m_Workbench->GetServiceByType<CProjectService>(); 00462 CRef<CWorkspaceConstPrx> workspace = prj_srv->GetWorkspaceConst(); 00463 00464 NON_CONST_ITERATE(TItemRefVector, it, sel_items) { 00465 CExplorerItem& item = **it; 00466 TProjectTreeItem* project_item = dynamic_cast<TProjectTreeItem*>(&item); 00467 if(project_item) { 00468 TProjectId id = project_item->GetData(); 00469 ids.push_back(id); 00470 } 00471 } 00472 } 00473 00474 00475 void CProjectTreePanel::OnItemExpandedCollapsed(wxTreeEvent& event) 00476 { 00477 wxTreeItemId id = event.GetItem(); 00478 bool open = m_Tree->IsExpanded(id); 00479 CExplorerItem* item = x_GetExplorerItem(id); 00480 item->Expand(open); 00481 00482 m_ExplorerService->OnItemExpandedCollapsed(*item); 00483 } 00484 00485 00486 void CProjectTreePanel::OnItemActivated(wxTreeEvent& event) 00487 { 00488 wxTreeItemId id = event.GetItem(); 00489 if(id.IsOk()) { 00490 CExplorerItem* item = x_GetExplorerItem(id); 00491 if(item) { 00492 m_ExplorerService->OnItemActivated(*item); 00493 } 00494 } 00495 } 00496 00497 00498 void CProjectTreePanel::OnSelectionChanged(wxTreeEvent& event) 00499 { 00500 CEvent evt(CEvent::eEvent_Message, CViewEvent::eWidgetSelectionChanged); 00501 Send(&evt, ePool_Parent); 00502 } 00503 00504 void CProjectTreePanel::OnLeftDown(wxMouseEvent& event) 00505 { 00506 event.Skip(); 00507 } 00508 00509 00510 // this functions inititates and performs the whole D&D session 00511 void CProjectTreePanel::OnBeginDrag(wxTreeEvent& event) 00512 { 00513 // get id selection and preserve it, so that we can restore it later 00514 wxArrayTreeItemIds sel_ids; 00515 m_Tree->GetSelections(sel_ids); 00516 00517 // get item selection 00518 TItemRefVector sel_items; 00519 x_GetItemsFromIds(sel_ids, sel_items); 00520 00521 bool en = m_ExplorerService->CanCutOrCopyToClipboard(sel_items); 00522 00523 if(en) { 00524 // reset D&D state 00525 m_DropItemId = wxTreeItemId(); 00526 m_DropTimerActive = false; 00527 00528 // create a wxDataObject for the selected items 00529 m_DataObject = m_ExplorerService->CreateDataObject(sel_items, true, false); 00530 00531 // For osx cocoa, we use wxTreeCtrl's built-in D&D. For others we continue to 00532 // use the original (general) drag and drop and approach. They seem 00533 // to be equivalent in behavior in this case afik) 00534 #ifdef __WXOSX_COCOA__ 00535 // Tree D&D does not take over the event loop... 00536 event.Allow(); 00537 #else 00538 wxDropSource source(*m_DataObject, this); 00539 00540 // the whole D&D session happens in this call 00541 wxDragResult res = source.DoDragDrop(wxDragCopy | wxDragMove); 00542 00543 // at this point session has ended and Drag Traget already has done all necessary work 00544 00545 if(res == wxDragError) { 00546 NcbiErrorBox("Unexpected error while performing D&D"); 00547 ERR_POST("CProjectTreePanel::OnBeginDrag() - Unexpected error while performing D&D"); 00548 } 00549 00550 // reset D&D state 00551 m_DropItemId = wxTreeItemId(); 00552 m_DropItemTimer.Stop(); 00553 m_DropTimerActive = false; 00554 delete m_DataObject; 00555 m_DataObject = NULL; 00556 #endif 00557 } 00558 } 00559 00560 // end drag for the trees built-in drag and drop (used for osx cocoa) 00561 // never called by other os's since they don't call event.Allow() when 00562 // D&D starts.) 00563 void CProjectTreePanel::OnEndDrag(wxTreeEvent& event) 00564 { 00565 int flags = 0; 00566 wxTreeItemId id = m_Tree->HitTest( event.GetPoint(), flags); 00567 00568 if( id.IsOk() ){ 00569 CExplorerItem* item = x_GetExplorerItem(id); 00570 00571 if( m_ExplorerService->CanDropTo(*item) ){ 00572 m_ExplorerService->Drop( *item, *m_DataObject->GetDataRef(), !m_CopyMode); 00573 } 00574 } 00575 00576 // reset D&D state 00577 m_DropItemId = wxTreeItemId(); 00578 m_DropItemTimer.Stop(); 00579 m_DropTimerActive = false; 00580 delete m_DataObject; 00581 m_DataObject = NULL; 00582 } 00583 00584 void CProjectTreePanel::x_SetSelections(wxArrayTreeItemIds& ids) 00585 { 00586 wxArrayTreeItemIds sel_ids; 00587 m_Tree->GetSelections(sel_ids); 00588 00589 //reset current selection 00590 for( size_t i = 0; i < sel_ids.size(); i++ ) { 00591 wxTreeItemId id = sel_ids[i]; 00592 m_Tree->SelectItem(id, false); 00593 } 00594 // set new selection 00595 for( size_t i = 0; i < ids.size(); i++ ) { 00596 wxTreeItemId id = ids[i]; 00597 m_Tree->SelectItem(id, true); 00598 } 00599 } 00600 00601 00602 wxDragResult CProjectTreePanel::OnDragOver(wxCoord x, wxCoord y, wxDragResult def) 00603 { 00604 // If null, a drag is not in progress. 00605 if (m_DataObject == NULL) 00606 return wxDragNone; 00607 00608 static const double kExpandDelay = 0.5; 00609 // get the item under the mouse pointer 00610 int flags = 0; 00611 wxTreeItemId id = m_Tree->HitTest(wxPoint(x, y), flags); 00612 00613 if(id != m_DropItemId) { 00614 // current item have changed - need to update highlight and "expand" timer 00615 00616 // stop the timer 00617 m_DropItemTimer.Stop(); 00618 m_DropTimerActive = false; 00619 00620 // change highlight 00621 if(m_DropItemId.IsOk()) { 00622 m_Tree->SetItemDropHighlight(m_DropItemId, false); 00623 } 00624 00625 m_DropItemId = id; 00626 00627 if(m_DropItemId.IsOk()) { 00628 m_Tree->SetItemDropHighlight(m_DropItemId, true); 00629 00630 // launch "expand" timer 00631 if(m_Tree->ItemHasChildren(m_DropItemId) && ! m_Tree->IsExpanded(m_DropItemId)) { 00632 // start the timer 00633 m_DropItemTimer.Restart(); 00634 m_DropTimerActive = true; 00635 } 00636 } 00637 } else if(m_DropTimerActive) { 00638 // current item has not changed and timer is active 00639 if(m_DropItemTimer.Elapsed() >= kExpandDelay) { 00640 m_Tree->Expand(m_DropItemId); 00641 00642 m_DropItemTimer.Stop(); 00643 m_DropTimerActive = false; 00644 } 00645 } 00646 00647 if(id.IsOk()) { 00648 CExplorerItem* item = x_GetExplorerItem(id); 00649 00650 if(m_ExplorerService->CanDropTo(*item)) { 00651 return def; 00652 } else { 00653 } 00654 } else { 00655 } 00656 return wxDragNone; 00657 } 00658 00659 // drag end for standard (general) drag and drop used on non-cocoa platforms 00660 wxDragResult CProjectTreePanel::OnDrop( 00661 wxCoord x, wxCoord y, wxDragResult def, CAppExplorerDataObject& data 00662 ){ 00663 if( def == wxDragCopy || def == wxDragMove ){ 00664 int flags = 0; 00665 wxTreeItemId id = m_Tree->HitTest( wxPoint(x, y), flags ); 00666 00667 if( id.IsOk() ){ 00668 CExplorerItem* item = x_GetExplorerItem(id); 00669 00670 if( m_ExplorerService->CanDropTo(*item) ){ 00671 bool move = (def == wxDragMove); 00672 00673 m_ExplorerService->Drop( *item, *data.GetDataRef(), move ); 00674 00675 return def; 00676 } 00677 } 00678 } 00679 00680 return wxDragNone; 00681 } 00682 00683 void CProjectTreePanel::OnTreeKeyDown(wxTreeEvent& event) 00684 { 00685 const wxKeyEvent& keyEvent = event.GetKeyEvent(); 00686 m_CopyMode = keyEvent.CmdDown(); 00687 00688 if (WXK_F2 != keyEvent.GetKeyCode() || keyEvent.GetModifiers() != wxMOD_NONE) { 00689 event.Skip(); 00690 return; 00691 } 00692 00693 wxArrayTreeItemIds items; 00694 if (m_Tree->GetSelections(items) != 1) 00695 return; 00696 00697 wxTreeItemId item = items[0]; 00698 if (!item.IsOk()) 00699 return; 00700 00701 (void)m_Tree->EditLabel(item); 00702 } 00703 00704 void CProjectTreePanel::OnBeginLabelEdit(wxTreeEvent& event) 00705 { 00706 wxTreeItemId item = event.GetItem(); 00707 CExplorerItem* eitem = x_GetExplorerItem(item); 00708 CAppExplorerService::EItemType itemType = m_ExplorerService->GetItemType(*eitem); 00709 00710 CProjectService* prj_srv = m_Workbench->GetServiceByType<CProjectService>(); 00711 if (itemType == CAppExplorerService::eWorkspace) { 00712 CRef<CWorkspaceConstPrx> ws = prj_srv->GetWorkspaceConst(); 00713 m_Tree->SetItemText(item, ToWxString(ws->GetName())); 00714 } 00715 else if (itemType == CAppExplorerService::eProject) { 00716 CAppExplorerService::TProjectTreeItem* prj_item = 00717 dynamic_cast<CAppExplorerService::TProjectTreeItem*>(eitem); 00718 _ASSERT(prj_item); 00719 CAppExplorerService::TProjectId id = prj_item->GetData(); 00720 CRef<CWorkspaceConstPrx> ws = prj_srv->GetWorkspaceConst(); 00721 CRef<CProjectPrx> project = ws->FindProjectById(id); 00722 00723 if (!project->IsLoaded()) { 00724 event.Veto(); 00725 } 00726 else { 00727 m_Tree->SetItemText(item, ToWxString(project->GetName())); 00728 } 00729 } 00730 else if (itemType == CAppExplorerService::eProjectItem); 00731 else 00732 event.Veto(); 00733 } 00734 00735 void CProjectTreePanel::OnEndLabelEdit(wxTreeEvent& event) 00736 { 00737 wxTreeItemId item = event.GetItem(); 00738 wxString label = event.GetLabel(); 00739 CExplorerItem* eitem = x_GetExplorerItem(item); 00740 CAppExplorerService::EItemType itemType = m_ExplorerService->GetItemType(*eitem); 00741 00742 CProjectService* prj_srv = m_Workbench->GetServiceByType<CProjectService>(); 00743 if (itemType == CAppExplorerService::eWorkspace) { 00744 CRef<CWorkspacePrx> ws = prj_srv->GetWorkspace(); 00745 if (event.IsEditCancelled()) 00746 label = ToWxString(ws->GetName()); 00747 ws->SetName(ToStdString(label)); 00748 CRef<CWorkspaceFolderPrx> ws_folder = ws->GetRootFolder(); 00749 ws_folder->SetName(ws->GetName()); 00750 } 00751 else if (itemType == CAppExplorerService::eProject) { 00752 CAppExplorerService::TProjectTreeItem* prj_item = 00753 dynamic_cast<CAppExplorerService::TProjectTreeItem*>(eitem); 00754 _ASSERT(prj_item); 00755 CAppExplorerService::TProjectId id = prj_item->GetData(); 00756 CRef<CWorkspaceConstPrx> ws = prj_srv->GetWorkspaceConst(); 00757 CRef<CProjectPrx> project = ws->FindProjectById(id); 00758 00759 if (!project->IsLoaded()) { 00760 event.Veto(); 00761 } 00762 else { 00763 if (event.IsEditCancelled()) 00764 label = ToWxString(project->GetName()); 00765 project->SetName(ToStdString(label)); 00766 } 00767 } 00768 else if (itemType == CAppExplorerService::eProjectItem) { 00769 if (event.IsEditCancelled()) 00770 return; 00771 00772 // get the Project and the Item proxies 00773 CAppExplorerService::TProjectItemTreeItem* tree_item = 00774 dynamic_cast<CAppExplorerService::TProjectItemTreeItem*>(eitem); 00775 _ASSERT(tree_item); 00776 TProjectId prj_id = m_ExplorerService->GetProjectIdByChild(*eitem); 00777 CRef<CWorkspaceConstPrx> ws = prj_srv->GetWorkspaceConst(); 00778 CRef<CProjectPrx> project = ws->FindProjectById(prj_id); 00779 CAppExplorerService::TPrjItemId item_id = tree_item->GetData(); 00780 CRef<CProjectItemPrx> pr_item = project->FindProjectItemById(item_id); 00781 string oldName = pr_item->GetName(); 00782 00783 // get the parent item and check whether it is a Folder 00784 CExplorerItem* parent_item = eitem->GetParent(); 00785 CAppExplorerService::TProjectFolderTreeItem* folder_parent_item = 00786 dynamic_cast<CAppExplorerService::TProjectFolderTreeItem*>(parent_item); 00787 _ASSERT(folder_parent_item); 00788 00789 CProjectFolderPrx::TId parent_id = folder_parent_item->GetData(); 00790 CRef<CProjectFolderPrx> pr_parent_folder = project->FindProjectFolderById(parent_id); 00791 00792 CPrjItemNameValidator validator(*pr_parent_folder, oldName); 00793 string err; 00794 if (!validator.IsValid(ToStdString(label), err)) { 00795 NcbiErrorBox(err); 00796 label = ToWxString(oldName); 00797 event.Veto(); 00798 } 00799 else 00800 pr_item->SetName(ToStdString(label)); 00801 return; 00802 } 00803 00804 event.Veto(); 00805 } 00806 00807 void CProjectTreePanel::OnCut( wxCommandEvent& event ) 00808 { 00809 event.Skip(); 00810 } 00811 00812 00813 END_NCBI_SCOPE
1.7.5.1
Modified on Wed May 23 13:12:57 2012 by modify_doxy.py rev. 337098