NCBI C++ ToolKit
project_tree_panel.cpp
Go to the documentation of this file.
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
Modified on Wed May 23 13:12:57 2012 by modify_doxy.py rev. 337098