638
786
// Let the user edit the category
639
787
EnsureVisible(newCategoryID);
640
EditLabel(newCategoryID);
641
SetFileChanged(true);
788
EditLabel(newCategoryID);
789
SetFileChanged(true);
644
792
return newCategoryID;
646
// ----------------------------------------------------------------------------
647
bool CodeSnippetsTreeCtrl::RemoveItem(const wxTreeItemId RemoveItemId)
648
// ----------------------------------------------------------------------------
650
// Get the associated item id
651
wxTreeItemId itemId = RemoveItemId;
653
if (not itemId.IsOk()) return false;
654
if (itemId == GetRootItem() ) return false;
656
SnippetItemData* pItemData = (SnippetItemData*)(GetItemData(itemId));
657
if (not pItemData) return false;
659
bool shiftKeyIsDown = ::wxGetKeyState(WXK_SHIFT);
660
wxString itemText = GetItemText(RemoveItemId);
662
// delete unused items directly (don't ".trash" them)
663
bool canceledItem = false;
664
if ( itemText.IsSameAs(wxT("New category")) || itemText.IsSameAs(wxT("New snippet")) )
667
shiftKeyIsDown = true;
669
bool trashItem = false;
671
// if shift key is up, copy item to .trash category
672
if (not shiftKeyIsDown)
674
// put deleted items in .trash category
675
wxTreeItemId trashId = FindItemByLabel(wxT(".trash"), GetRootItem(), CodeSnippetsConfig::SCOPE_CATEGORIES);
676
if ( trashId==(void*)0 )
677
trashId = AddCategory(GetRootItem(), wxT(".trash"), false);
679
// if item is NOT already in the trash, copy item to .trash category
680
if (not ( FindItemById( itemId, trashId, pItemData->GetType()) ))
682
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( itemId);
683
CopyXmlDocToTreeNode(pDoc, trashId);
686
else // item already in .trash, delete it
690
}//if not shiftKeyIsDown
692
// when in trash already, or immediate delete requested, check for fileLink delete too
693
if ( not canceledItem ) //not "New category", not "New snippet"
694
if (trashItem || shiftKeyIsDown )
696
// if FileLink, memorize the filename
697
wxString filename = wxEmptyString;
698
if ( IsFileSnippet(itemId) )
699
filename = GetSnippetFileLink(itemId);
701
// if this was a FileLink, ask if user wants to delete file
702
if ( not filename.IsEmpty() ) {
703
int answer = messageBox( wxT("Delete physical file?\n\n")+filename,
704
wxT("Delete"),wxYES_NO );
705
if ( answer == wxYES)
706
/*int done =*/ ::wxRemoveFile(filename);
710
// Delete the original Snippet Tree Item
711
DeleteChildren(itemId);
713
SetFileChanged(true);
718
// ----------------------------------------------------------------------------
719
void CodeSnippetsTreeCtrl::SetSnippetImage(wxTreeItemId itemId)
720
// ----------------------------------------------------------------------------
722
// set the item tree image
723
if ( IsFileSnippet(itemId) )
724
SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
725
else if (IsUrlSnippet(itemId))
726
SetItemImage( itemId, TREE_IMAGE_SNIPPET_URL);
728
SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
731
// ----------------------------------------------------------------------------
732
void CodeSnippetsTreeCtrl::SaveFileModificationTime(wxDateTime savedTime)
733
// ----------------------------------------------------------------------------
735
if (savedTime != time_t(0))
736
{ m_LastXmlModifiedTime = savedTime;
739
if (::wxFileExists(GetConfig()->SettingsSnippetsXmlFullPath) )
740
{ wxFileName fname( GetConfig()->SettingsSnippetsXmlFullPath );
741
m_LastXmlModifiedTime = fname.GetModificationTime();
744
// ----------------------------------------------------------------------------
745
void CodeSnippetsTreeCtrl::OnBeginTreeItemDrag(wxTreeEvent& event)
746
// ----------------------------------------------------------------------------
748
// -----------------------
750
// -----------------------
751
CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
754
// LOGIT( wxT("ScrapList::OnTreeCtrlEvent %p"), pTree );
758
LOGIT( _T("TREE_CTRL_BEGIN_DRAG %p"), pTree );
760
// On MSW the current selection may not be the same as the current itemId
761
// If the user just clicks and drags, the two are different
762
m_pEvtTreeCtrlBeginDrag = pTree;
763
m_TreeItemId = event.GetItem();
764
// At this point we could solve the above problem with
765
// pTree->SelectItem(m_TreeItemId) ; But for now, we'll just
766
// record the actual current itemId.
767
m_MnuAssociatedItemID = m_TreeItemId;
768
m_TreeMousePosn = ::wxGetMousePosition();
769
m_TreeText = pTree->GetSnippet(m_TreeItemId);
770
if ( IsCategory(m_TreeItemId) )
771
m_TreeText = GetSnippetLabel(m_TreeItemId);
772
if (m_TreeText.IsEmpty())
773
m_pEvtTreeCtrlBeginDrag = 0;
774
//LOGIT( _T("TREE_CTRL_BEGIN_DRAG TreeText[%s]"), m_TreeText.GetData() );
777
// -----------------------------------------
778
// Do *not* event.Skip() or GTK will break
780
// -----------------------------------------
783
}//OnBeginTreeItemDrag
784
// ----------------------------------------------------------------------------
785
void CodeSnippetsTreeCtrl::OnEndTreeItemDrag(wxTreeEvent& event)
786
// ----------------------------------------------------------------------------
788
// -----------------------
790
// -----------------------
794
wxTreeCtrl* pTree = (wxTreeCtrl*)event.GetEventObject();
795
LOGIT( _T("TREE_CTRL_END_DRAG %p"), pTree );
794
// ----------------------------------------------------------------------------
795
bool CodeSnippetsTreeCtrl::RemoveItem(const wxTreeItemId RemoveItemId)
796
// ----------------------------------------------------------------------------
798
// Get the associated item id
799
wxTreeItemId itemId = RemoveItemId;
801
if (not itemId.IsOk()) return false;
802
if (itemId == GetRootItem() ) return false;
804
SnippetItemData* pItemData = (SnippetItemData*)(GetItemData(itemId));
805
if (not pItemData) return false;
807
bool shiftKeyIsDown = ::wxGetKeyState(WXK_SHIFT);
808
wxString itemText = GetItemText(RemoveItemId);
810
// delete unused items directly (don't ".trash" them)
811
bool canceledItem = false;
812
if ( itemText.IsSameAs(wxT("New category")) || itemText.IsSameAs(wxT("New snippet")) )
815
shiftKeyIsDown = true;
817
bool trashItem = false;
819
// if shift key is up, copy item to .trash category
820
if (not shiftKeyIsDown)
822
// put deleted items in .trash category
823
wxTreeItemId trashId = FindTreeItemByLabel(wxT(".trash"), GetRootItem(), CodeSnippetsConfig::SCOPE_CATEGORIES);
824
if ( trashId==(void*)0 )
825
trashId = AddCategory(GetRootItem(), wxT(".trash"), /*itemID*/0, /*editNow*/false);
827
// if item is NOT already in the trash, copy item to .trash category
828
if (not ( FindTreeItemByTreeId( itemId, trashId, pItemData->GetType()) ))
830
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( itemId);
831
CopyXmlDocToTreeNode(pDoc, trashId);
834
else // item already in .trash, delete it
838
}//if not shiftKeyIsDown
840
// when in trash already, or immediate delete requested, check for fileLink delete too
841
if ( not canceledItem ) //not "New category", not "New snippet"
842
if (trashItem || shiftKeyIsDown )
844
// if FileLink, memorize the filename
845
wxString filename = wxEmptyString;
846
if ( IsFileSnippet(itemId) )
847
filename = GetSnippetFileLink(itemId);
849
// if this was a FileLink, ask if user wants to delete file
850
if ( not filename.IsEmpty() ) {
851
int answer = GenericMessageBox( wxT("Delete physical file?\n\n")+filename,
852
wxT("Delete"),wxYES_NO );
853
if ( answer == wxYES)
854
/*int done =*/ ::wxRemoveFile(filename);
858
// Delete the original Snippet Tree Item
859
DeleteChildren(itemId);
861
SetFileChanged(true);
866
// ----------------------------------------------------------------------------
867
void CodeSnippetsTreeCtrl::SetSnippetImage(wxTreeItemId itemId)
868
// ----------------------------------------------------------------------------
870
// set the item tree image
871
if ( IsFileSnippet(itemId) )
872
SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
873
else if (IsUrlSnippet(itemId))
874
SetItemImage( itemId, TREE_IMAGE_SNIPPET_URL);
876
SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
879
// ----------------------------------------------------------------------------
880
void CodeSnippetsTreeCtrl::FetchFileModificationTime(wxDateTime savedTime)
881
// ----------------------------------------------------------------------------
883
if (savedTime != time_t(0))
884
{ m_LastXmlModifiedTime = savedTime;
887
if (::wxFileExists(GetConfig()->SettingsSnippetsXmlPath) )
888
{ wxFileName fname( GetConfig()->SettingsSnippetsXmlPath );
889
m_LastXmlModifiedTime = fname.GetModificationTime();
892
// ----------------------------------------------------------------------------
893
void CodeSnippetsTreeCtrl::OnBeginTreeItemDrag(wxTreeEvent& event)
894
// ----------------------------------------------------------------------------
896
// -----------------------
898
// -----------------------
899
CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
902
LOGIT( _T("TREE_CTRL_BEGIN_DRAG %p"), pTree );
904
// On MSW the current selection may not be the same as the current itemId
905
// If the user just clicks and drags, the two are different
906
m_pEvtTreeCtrlBeginDrag = pTree;
907
m_TreeItemId = event.GetItem();
908
// At this point we could solve the above problem with
909
// pTree->SelectItem(m_TreeItemId) ; But for now, we'll just
910
// record the actual current itemId.
911
m_MnuAssociatedItemID = m_TreeItemId;
912
m_TreeMousePosn = ::wxGetMousePosition();
913
m_TreeText = pTree->GetSnippet(m_TreeItemId);
914
if ( IsCategory(m_TreeItemId) )
915
m_TreeText = GetSnippetLabel(m_TreeItemId);
916
if (m_TreeText.IsEmpty())
917
m_pEvtTreeCtrlBeginDrag = 0;
920
// -----------------------------------------
921
// Do *not* event.Skip() or GTK will break.
923
// -----------------------------------------
926
}//OnBeginTreeItemDrag
927
// ----------------------------------------------------------------------------
928
void CodeSnippetsTreeCtrl::OnEndTreeItemDrag(wxTreeEvent& event)
929
// ----------------------------------------------------------------------------
931
// -----------------------
933
// -----------------------
937
wxTreeCtrl* pTree = (wxTreeCtrl*)event.GetEventObject();
938
LOGIT( _T("TREE_CTRL_END_DRAG %p"), pTree );
798
941
wxTreeItemId targetItem = (wxTreeItemId)event.GetItem();
799
wxTreeItemId sourceItem = m_MnuAssociatedItemID;
942
wxTreeItemId sourceItem = m_MnuAssociatedItemID;
800
943
if ( not sourceItem.IsOk() ){return;}
801
944
if ( not targetItem.IsOk() ){return;}
802
945
if (not m_pEvtTreeCtrlBeginDrag)
804
947
event.Skip(); return;
807
// veto the drag if mouse has moved out of the Tree window
808
// Note: Even if mouse is dragged out of the tree window,
809
// FindFocus() is returning the Tree window. So the
810
// following test does not work.
811
//if (pTree == wxWindow::FindFocus() )
815
// If user dragged item out of the window, it'll be dropped by the
816
// target application. So just clear the status and return.
950
// veto the drag if mouse has moved out of the Tree window
951
// Note: Even if mouse is dragged out of the tree window,
952
// FindFocus() is returning the Tree window. So the
953
// following test does not work.
954
//if (pTree == wxWindow::FindFocus() )
958
// If user dragged item out of the window, it'll be dropped by the
959
// target application. So just clear the status and return.
817
960
if (m_bMouseLeftWindow)
818
961
{ // user dragged item out of the window
819
962
m_bMouseLeftWindow = false;
824
// if source and target are snippets, create a new category and enclose both.
825
if ( IsSnippet(targetItem) )
827
if ( targetItem = ConvertSnippetToCategory(targetItem)) {;}//ok
829
// now targetItem is a category
833
// Save the source item node to an Xml Document
834
// Load it into the target item node
835
// delete the source item node
837
// create Xml document from source(dragged) tree item
838
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( sourceItem );
839
if (not pDoc) return;
841
TiXmlElement* root = pDoc->RootElement();
844
// Get the source xml element
845
TiXmlElement* firstChild = root->FirstChildElement("item");
847
{ // insert into target Tree items from source xml document
848
LoadItemsFromXmlNode( firstChild, targetItem);
851
// remove the old tree item
852
if (not m_MouseCtrlKeyDown){
853
RemoveItem( sourceItem );
856
delete pDoc; pDoc = 0;
858
// -----------------------------------------
859
// Do *not* event.Skip() or GTK will break
861
// -----------------------------------------
866
// ----------------------------------------------------------------------------
867
void CodeSnippetsTreeCtrl::OnEnterWindow(wxMouseEvent& event)
868
// ----------------------------------------------------------------------------
870
// a wxAUI window is not enabling the Tree ctrl so when leaving
871
// the disabled TreeCtrl, the scintilla editor doesnt show the cursor.
872
wxWindow* pw = (wxWindow*)event.GetEventObject();
877
// ----------------------------------------------------------------------------
878
void CodeSnippetsTreeCtrl::OnLeaveWindow(wxMouseEvent& event)
879
// ----------------------------------------------------------------------------
881
// -----------------------
883
// -----------------------
885
// User has dragged mouse out of source window.
886
// if EVT_TREE_BEGIN_DRAG is pending, create a drag source to be used
887
// in the destination window.
890
//LOGIT( _T("MOUSE EVT_LEAVE_WINDOW") );
893
// Left mouse key must be down (dragging)
894
if (not event.LeftIsDown() ) {event.Skip();return;}
895
// check if data is available
896
if ( m_TreeText.IsEmpty()) {event.Skip();return;}
897
if (not m_pEvtTreeCtrlBeginDrag) {event.Skip(); return;}
900
LOGIT( _T("LEAVE_WINDOW %p"), event.GetEventObject() );
967
// if source and target are snippets, create a new category and enclose both.
968
if ( IsSnippet(targetItem) )
970
if ( (targetItem = ConvertSnippetToCategory(targetItem)) )
973
// now targetItem is a category
977
// Save the source item node to a new Xml Document
978
// Load it into the target item node
979
// delete the source item node
981
// create Xml document from source(dragged) tree item
982
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( sourceItem );
983
if (not pDoc) return;
985
TiXmlElement* root = pDoc->RootElement();
988
// Get the source xml element
989
TiXmlElement* firstChild = root->FirstChildElement("item");
991
{ // insert into target Tree items from source xml document
992
LoadItemsFromXmlNode( firstChild, targetItem);
995
// remove the old tree item
996
if (not m_MouseCtrlKeyDown){
997
RemoveItem( sourceItem );
1000
delete pDoc; pDoc = 0;
1002
// -----------------------------------------
1003
// Do *not* event.Skip() or GTK will break.
1005
// -----------------------------------------
1009
}//OnEndTreeItemDrag
1010
// ----------------------------------------------------------------------------
1011
void CodeSnippetsTreeCtrl::OnEnterWindow(wxMouseEvent& event)
1012
// ----------------------------------------------------------------------------
1014
//*WARNING* child windows of wxAUI windows do not get common events.
1015
// unless the parent wxAUI window has/had focus.
1017
// a wxAUI window is not enabling the Tree ctrl unless the user specifically
1018
// clicks on a tree item. Its disabled otherwise, so when leaving
1019
// the disabled TreeCtrl, the CodeSnippets child Edit (scintilla editor)
1020
// gets no EVT_FOCUS_WINDOW and therefore shows no caret/cursor.
1021
// So here, we force the tree ctrl to focus so that the editor
1022
// gets a focus event also. Note also, that other common events are not
1023
// propagated when a wxAUI window is floating.
1025
#if defined(LOGGING)
1026
//LOGIT( _T("CodeSnippetsTreeCtrl::OnEnterWindow"));
1029
// If the user is editing a label, don't refocus the control
1030
if ( not GetConfig()->GetSnippetsWindow()->IsEditingLabel() )
1031
if ( GetConfig()->IsFloatingWindow())
1033
#if defined(LOGGING)
1034
//LOGIT( _T("CodeSnippetsCtrl IsFloatingWindow[%s]"), _T("TRUE"));
1036
wxWindow* pw = (wxWindow*)event.GetEventObject();
1037
// only if forground is our window, set focus
1038
if ( pw == ::wxGetActiveWindow() )
1046
// ----------------------------------------------------------------------------
1047
void CodeSnippetsTreeCtrl::OnLeaveWindow(wxMouseEvent& event)
1048
// ----------------------------------------------------------------------------
1050
// -----------------------
1052
// -----------------------
1054
// User has dragged mouse out of source window.
1055
// if EVT_TREE_BEGIN_DRAG is pending, create a drag source to be used
1056
// in the destination window.
1059
//LOGIT( _T("CodeSnippetsTreeCtrl::OnLeaveWindow") );
1062
// Left mouse key must be down (dragging)
1063
if (not event.LeftIsDown() ) {event.Skip();return;}
1064
// check if data is available
1065
if ( m_TreeText.IsEmpty()) {event.Skip();return;}
1066
if (not m_pEvtTreeCtrlBeginDrag) {event.Skip(); return;}
1069
LOGIT( _T("LEAVE_WINDOW %p"), event.GetEventObject() );
903
1072
// when user drags an item out of the window, this routine is called
904
1073
// before EVT_END_DRAG, who will clear this flag
905
1074
m_bMouseLeftWindow = true;
907
// we now have data, create both a simple text and filename drop source
908
wxTextDataObject* textData = new wxTextDataObject();
909
wxFileDataObject* fileData = new wxFileDataObject();
910
// fill text and file sources with snippet
911
wxString textStr = GetSnippet(m_MnuAssociatedItemID) ;
912
#if defined(BUILDING_PLUGIN)
913
// substitute any $(macro) text
914
Manager::Get()->GetMacrosManager()->ReplaceMacros(textStr);
915
//-LOGIT( _T("SnippetsTreeCtrl OnLeaveWindow $macros text[%s]"),textStr.c_str() );
917
wxDropSource textSource( *textData, (wxWindow*)event.GetEventObject() );
918
textData->SetText( textStr );
920
wxDropSource fileSource( *fileData, (wxWindow*)event.GetEventObject() );
921
wxString fileName = GetSnippetFileLink(m_MnuAssociatedItemID);
922
if (not ::wxFileExists(fileName) ) fileName = wxEmptyString;
923
fileData->AddFile( (fileName.Len() > 128) ? wxString(wxEmptyString) : fileName );
924
// set composite data object to contain both text and file data
925
wxDataObjectComposite *data = new wxDataObjectComposite();
926
data->Add( (wxDataObjectSimple*)textData );
927
data->Add( (wxDataObjectSimple*)fileData, true ); // set file data as preferred
928
// create the drop source containing both data types
929
wxDropSource source( *data, (wxWindow*)event.GetEventObject() );
932
LOGIT( _T("DropSource Text[%s],File[%s]"),
933
textData->GetText().GetData(),
934
fileData->GetFilenames().Item(0).GetData() );
936
// allow both copy and move
938
flags |= wxDrag_AllowMove;
940
wxDragResult result = source.DoDragDrop(flags);
941
// report the results
946
case wxDragError: pc = _T("Error!"); break;
947
case wxDragNone: pc = _T("Nothing"); break;
948
case wxDragCopy: pc = _T("Copied"); break;
949
case wxDragMove: pc = _T("Moved"); break;
950
case wxDragCancel: pc = _T("Cancelled"); break;
951
default: pc = _T("Huh?"); break;
953
LOGIT( wxT("ScrapList::OnLeftDown DoDragDrop returned[%s]"),pc.GetData() );
958
// ---WORKAROUNG --------------------------------------------------
959
// Since we dragged outside the tree control with an EVT_TREE_DRAG_BEGIN
960
// pending, WX will not send the EVT_TREE_DRAG_END from a
961
// mouse_key_up event unless the user re-clicks inside the tree control.
962
// The mouse is still captured and the tree exibits very bad behavior.
964
// To solve this, send an mouse_key_up to the tree control so it
965
// releases the mouse and receives an EVT_TREE_DRAG_END event.
967
if ( m_pEvtTreeCtrlBeginDrag )
969
//send Mouse LeftKeyUp to Tree Control window
971
//LOGIT( _T("Sending Mouse LeftKeyUp") );
974
// move mouse into the Tree control
975
wxPoint CurrentMousePosn = ::wxGetMousePosition();
977
#if defined(__WXMSW__)
978
MSW_MouseMove( m_TreeMousePosn.x, m_TreeMousePosn.y );
979
// send mouse LeftKeyUp
981
Input.type = INPUT_MOUSE;
982
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
983
::SendInput(1,&Input,sizeof(INPUT));
984
// put mouse back in pre-moved "dropped" position
985
MSW_MouseMove( CurrentMousePosn.x, CurrentMousePosn.y );
988
#if defined(__WXGTK__)
989
// move cursor to source window and send a left button up event
990
XWarpPointer (GDK_WINDOW_XDISPLAY(GDK_ROOT_PARENT()),
991
None, /* not source window -> move from anywhere */
992
GDK_WINDOW_XID(GDK_ROOT_PARENT()), /* dest window */
993
0, 0, 0, 0, /* not source window -> move from anywhere */
994
m_TreeMousePosn.x, m_TreeMousePosn.y );
995
// send LeftMouseRelease key
996
m_pEvtTreeCtrlBeginDrag->SetFocus();
997
GdkDisplay* display = gdk_display_get_default ();
999
GdkWindow* pGdkWindow = gdk_display_get_window_at_pointer( display, &xx, &yy);
1000
// LOGIT(wxT("Tree[%p][%d %d]"), m_pEvtTreeCtrlBeginDrag,m_TreeMousePosn.x, m_TreeMousePosn.y);
1001
// LOGIT(wxT("gdk [%p][%d %d]"), pWindow, xx, yy);
1003
memset(&evb, 0, sizeof(evb));
1004
evb.type = GDK_BUTTON_RELEASE;
1005
evb.window = pGdkWindow;
1008
evb.state = GDK_BUTTON1_MASK;
1010
// gdk display put event, namely mouse release
1011
gdk_display_put_event( display, (GdkEvent*)&evb);
1012
// put mouse back in pre-moved "dropped" position
1013
XWarpPointer (GDK_WINDOW_XDISPLAY(GDK_ROOT_PARENT()),
1014
None, /* not source window -> move from anywhere */
1015
GDK_WINDOW_XID(GDK_ROOT_PARENT()), /* dest window */
1016
0, 0, 0, 0, /* not source window -> move from anywhere */
1017
CurrentMousePosn.x, CurrentMousePosn.y );
1022
delete textData; //wxTextDataObject
1023
delete fileData; //wxFileDataObject
1024
m_pEvtTreeCtrlBeginDrag = 0;
1025
m_TreeText = wxEmptyString;
1030
// ----------------------------------------------------------------------------
1031
void CodeSnippetsTreeCtrl::OnMouseEvent(wxMouseEvent& event)
1032
// ----------------------------------------------------------------------------
1034
//remember event window pointer
1035
//wxObject* m_pEvtObject = event.GetEventObject();
1037
// memorize position of the mouse ctrl key as copy/delete flag
1038
m_MouseCtrlKeyDown = event.ControlDown();
1040
//LOGIT(wxT("MouseCtrlKeyDown[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
1045
// ----------------------------------------------------------------------------
1046
#if defined(__WXMSW__)
1047
void CodeSnippetsTreeCtrl::MSW_MouseMove(int x, int y )
1048
// ----------------------------------------------------------------------------
1050
// Move mouse uses a very strange coordinate system.
1051
// It uses screen positions with a range of 0 to 65535
1053
// Move the MSW mouse to absolute screen coords x,y
1054
double fScreenWidth = ::GetSystemMetrics( SM_CXSCREEN )-1;
1055
double fScreenHeight = ::GetSystemMetrics( SM_CYSCREEN )-1;
1056
double fx = x*(65535.0f/fScreenWidth);
1057
double fy = y*(65535.0f/fScreenHeight);
1059
Input.type = INPUT_MOUSE;
1060
Input.mi.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
1061
Input.mi.dx = (LONG)fx;
1062
Input.mi.dy = (LONG)fy;
1063
::SendInput(1,&Input,sizeof(INPUT));
1066
// ----------------------------------------------------------------------------
1067
wxTreeItemId CodeSnippetsTreeCtrl::ConvertSnippetToCategory(wxTreeItemId itemId)
1068
// ----------------------------------------------------------------------------
1070
// Convert Snippet to Category, then insert the old snippet
1071
wxTreeItemId badItemId = (void*)0;
1073
if ( not IsSnippet(itemId)) return badItemId;
1074
// memorize id of this snippet
1075
wxTreeItemId oldItemId = itemId;
1076
if ( not oldItemId.IsOk() ) return badItemId;
1077
// memorize parent id of this snippet
1078
wxTreeItemId itemParent = GetItemParent(oldItemId);
1080
// create Xml document from selected tree item
1081
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( oldItemId );
1082
if (not pDoc) return badItemId;
1084
// Create new Category
1085
wxTreeItemId newCategoryId = AddCategory( itemParent,
1086
GetItemText(oldItemId), false );
1088
// Insert old Snippet Item under new Category
1089
TiXmlElement* root = pDoc->RootElement();
1092
// Get the first xml element
1093
TiXmlElement* firstChild = root->FirstChildElement("item");
1095
{ // insert Tree items from xml document
1096
//-LoadSnippets(firstChild, newCategoryId);
1097
LoadItemsFromXmlNode( firstChild, newCategoryId);
1101
// remove the old tree item
1102
RemoveItem( oldItemId );
1103
delete pDoc; pDoc = 0;
1104
return newCategoryId;
1106
// ----------------------------------------------------------------------------
1107
TiXmlDocument* CodeSnippetsTreeCtrl::CopyTreeNodeToXmlDoc(wxTreeItemId TreeItemId )
1108
// ----------------------------------------------------------------------------
1110
// Copy a Tree node to an Xml Document
1112
wxTreeItemId itemId = TreeItemId;
1113
if (not itemId.IsOk() )
1115
itemId = GetSelection();
1117
if (not itemId.IsOk()) return NULL;
1119
TiXmlDocument* pDoc = new TiXmlDocument;
1120
TiXmlDeclaration header("1.0", "UTF-8", "yes");
1121
pDoc->InsertEndChild(header);
1123
TiXmlElement snippetsElement("snippets");
1124
CopySnippetsToXmlDoc(&snippetsElement, itemId);
1126
pDoc->InsertEndChild(snippetsElement);
1130
} // end of SaveSnippetsToFile
1131
// ----------------------------------------------------------------------------
1132
void CodeSnippetsTreeCtrl::CopySnippetsToXmlDoc(TiXmlNode* Node, const wxTreeItemId& itemID)
1133
// ----------------------------------------------------------------------------
1135
// Recursively copy Tree item and all its children to an Xml document node
1137
wxTreeItemIdValue cookie;
1138
//wxTreeItemId item = GetSnippetsTreeCtrl->GetFirstChild(parentID, cookie );
1139
wxTreeItemId item = itemID;
1141
// Loop through all items
1144
// Get the item's information
1145
const SnippetItemData* data = (SnippetItemData*)GetItemData(item);
1152
// Begin item element
1153
TiXmlElement element("item");
1155
// Write the item's name
1156
element.SetAttribute("name", GetItemText(item).mb_str());
1158
// Write the type of the item
1159
switch (data->GetType())
1161
case SnippetItemData::TYPE_CATEGORY:
1162
element.SetAttribute("type", "category");
1165
case SnippetItemData::TYPE_SNIPPET:
1166
element.SetAttribute("type", "snippet");
1174
if (data->GetType() == SnippetItemData::TYPE_SNIPPET)
1176
TiXmlElement snippetElement("snippet");
1177
TiXmlText snippetElementText(data->GetSnippet().mb_str());
1178
snippetElement.InsertEndChild(snippetElementText);
1179
element.InsertEndChild(snippetElement);
1181
// LOGIT( _T("Snippet[%s]"), data->GetSnippet().GetData() );
1185
// Check if this item has children
1186
if(ItemHasChildren(item))
1188
// If it has, check those too
1189
//-SaveSnippets(&element, item);
1190
SaveItemsToXmlNode(&element, item);
1193
// Insert the item we created as parent node's child
1194
//parentNode->InsertEndChild(element);
1195
Node->InsertEndChild(element);
1197
// Check the next child
1198
item = GetNextChild( itemID, cookie);
1200
}//CopySnippetsToXmlDoc
1201
// ----------------------------------------------------------------------------
1202
void CodeSnippetsTreeCtrl::CopyXmlDocToTreeNode(TiXmlDocument* pTiXmlDoc, wxTreeItemId targetItem )
1203
// ----------------------------------------------------------------------------
1205
TiXmlElement* root = pTiXmlDoc->RootElement();
1208
// Get the source xml element
1209
TiXmlElement* firstChild = root->FirstChildElement("item");
1211
{ // insert into target Tree items from source xml document
1212
LoadItemsFromXmlNode( firstChild, targetItem);
1217
// ----------------------------------------------------------------------------
1218
void CodeSnippetsTreeCtrl::EditSnippetAsFileLink()
1219
// ----------------------------------------------------------------------------
1221
// Open snippet text as a file name. Ie, the text should contain a filename.
1222
// Else just open a temp file with the snippet text as data.
1224
#if defined(LOGGING)
1225
LOGIT( _T("EditSnippetAsFileLink[%s]"),wxT("") );
1228
if (not IsSnippet() ) return;
1230
// If snippet is file, open it
1231
wxTreeItemId itemId = GetAssociatedItemID();
1232
SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
1233
wxString FileName = GetSnippetFileLink( itemId );
1234
LOGIT( _T("EditSnippetsAsFileLlink()FileName[%s]"),FileName.c_str() );
1236
if (FileName.Length() > 128)
1237
{ // if text is > 128 characters, open a temp file with snippet text as data.
1238
EditSnippetAsText();
1243
// no filename, edit text file
1244
if ( (FileName.IsEmpty())
1245
|| (not ::wxFileExists( FileName)) )
1246
{ // if, non-existent file, open snippet text as data
1247
EditSnippetAsText();
1076
// we now have data; create both a simple text and filename drop source
1077
wxTextDataObject* textData = new wxTextDataObject();
1078
wxFileDataObject* fileData = new wxFileDataObject();
1079
// fill text and file sources with snippet
1080
wxString textStr = GetSnippet(m_MnuAssociatedItemID) ;
1081
//-#if defined(BUILDING_PLUGIN)
1082
// substitute any $(macro) text
1083
static const wxString delim(_T("$%["));
1084
if( textStr.find_first_of(delim) != wxString::npos )
1085
Manager::Get()->GetMacrosManager()->ReplaceMacros(textStr);
1086
//-LOGIT( _T("SnippetsTreeCtrl OnLeaveWindow $macros text[%s]"),textStr.c_str() );
1089
wxDropSource textSource( *textData, (wxWindow*)event.GetEventObject() );
1090
textData->SetText( textStr );
1092
wxDropSource fileSource( *fileData, (wxWindow*)event.GetEventObject() );
1093
wxString fileName = GetSnippetFileLink(m_MnuAssociatedItemID);
1094
if (not ::wxFileExists(fileName) ) fileName = wxEmptyString;
1095
// If no filename, but text is URL/URI, pass it as a file (esp. for browsers)
1096
if ( fileName.IsEmpty())
1097
{ if (textStr.StartsWith(_T("http://")))
1099
if (textStr.StartsWith(_T("file://")))
1101
// Remove anything pass the first \n or \r {v1.3.92}
1102
fileName = fileName.BeforeFirst('\n');
1103
fileName = fileName.BeforeFirst('\r');
1104
textData->SetText( fileName );
1106
fileData->AddFile( (fileName.Len() > 128) ? wxString(wxEmptyString) : fileName );
1108
// set composite data object to contain both text and file data
1109
wxDataObjectComposite *data = new wxDataObjectComposite();
1110
data->Add( (wxDataObjectSimple*)textData );
1111
data->Add( (wxDataObjectSimple*)fileData, true ); // set file data as preferred
1112
// create the drop source containing both data types
1113
wxDropSource source( *data, (wxWindow*)event.GetEventObject() );
1116
LOGIT( _T("DropSource Text[%s], File[%s]"),
1117
textData->GetText().c_str(),
1118
fileData->GetFilenames().Item(0).c_str() );
1120
// allow both copy and move
1122
flags |= wxDrag_AllowMove;
1124
wxDragResult result = source.DoDragDrop(flags);
1125
// report the results
1130
case wxDragError: pc = _T("Error!"); break;
1131
case wxDragNone: pc = _T("Nothing"); break;
1132
case wxDragCopy: pc = _T("Copied"); break;
1133
case wxDragMove: pc = _T("Moved"); break;
1134
case wxDragLink: pc = _T("Linked"); break;
1135
case wxDragCancel: pc = _T("Cancelled"); break;
1136
default: pc = _T("Huh?"); break;
1138
LOGIT( wxT("OnLeaveWindow::OnLeftDown DoDragDrop returned[%s]"),pc.GetData() );
1140
wxUnusedVar(result);
1143
// ---WORKAROUNG --------------------------------------------------
1144
// Since we dragged outside the tree control with an EVT_TREE_DRAG_BEGIN
1145
// pending, WX will not send the EVT_TREE_DRAG_END from a
1146
// mouse_key_up event unless the user re-clicks inside the tree control.
1147
// The mouse is still captured and the tree exibits very bad behavior.
1149
// To solve this, send a mouse_key_up to the tree control so it
1150
// releases the mouse and receives an EVT_TREE_DRAG_END event.
1152
if ( m_pEvtTreeCtrlBeginDrag )
1154
//send Mouse LeftKeyUp to Tree Control window
1156
LOGIT( _T("Sending Mouse LeftKeyUp") );
1159
// remember current mouse position to restore
1160
wxPoint CurrentMousePosn = ::wxGetMousePosition();
1162
// move mouse into the Tree control
1163
#if defined(__WXMSW__)
1164
MSW_MouseMove( m_TreeMousePosn.x, m_TreeMousePosn.y );
1165
m_pEvtTreeCtrlBeginDrag->SetFocus();
1166
// send mouse LeftKeyUp
1168
Input.type = INPUT_MOUSE;
1169
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
1170
::SendInput(1,&Input,sizeof(INPUT));
1171
// put mouse back in pre-moved "dropped" position
1172
MSW_MouseMove( CurrentMousePosn.x, CurrentMousePosn.y );
1173
#endif //(__WXMSW__)
1175
#if defined(__WXGTK__)
1176
// move cursor to source window and send a left button up event
1177
XWarpPointer (GDK_WINDOW_XDISPLAY(GDK_ROOT_PARENT()),
1178
None, /* not source window -> move from anywhere */
1179
GDK_WINDOW_XID(GDK_ROOT_PARENT()), /* dest window */
1180
0, 0, 0, 0, /* not source window -> move from anywhere */
1181
m_TreeMousePosn.x, m_TreeMousePosn.y );
1182
// send LeftMouseRelease key
1183
m_pEvtTreeCtrlBeginDrag->SetFocus();
1184
GdkDisplay* display = gdk_display_get_default ();
1186
GdkWindow* pGdkWindow = gdk_display_get_window_at_pointer( display, &xx, &yy);
1187
// LOGIT(wxT("Tree[%p][%d %d]"), m_pEvtTreeCtrlBeginDrag,m_TreeMousePosn.x, m_TreeMousePosn.y);
1188
// LOGIT(wxT("gdk [%p][%d %d]"), pWindow, xx, yy);
1190
memset(&evb, 0, sizeof(evb));
1191
evb.type = GDK_BUTTON_RELEASE;
1192
evb.window = pGdkWindow;
1195
evb.state = GDK_BUTTON1_MASK;
1197
// gdk display put event, namely mouse release
1198
gdk_display_put_event( display, (GdkEvent*)&evb);
1199
// put mouse back in pre-moved "dropped" position
1200
XWarpPointer (GDK_WINDOW_XDISPLAY(GDK_ROOT_PARENT()),
1201
None, /* not source window -> move from anywhere */
1202
GDK_WINDOW_XID(GDK_ROOT_PARENT()), /* dest window */
1203
0, 0, 0, 0, /* not source window -> move from anywhere */
1204
CurrentMousePosn.x, CurrentMousePosn.y );
1209
delete textData; //wxTextDataObject
1210
delete fileData; //wxFileDataObject
1211
m_pEvtTreeCtrlBeginDrag = 0;
1212
m_TreeText = wxEmptyString;
1217
// ----------------------------------------------------------------------------
1218
void CodeSnippetsTreeCtrl::OnMouseMotionEvent(wxMouseEvent& event)
1219
// ----------------------------------------------------------------------------
1221
//remember event window pointer
1222
//wxObject* m_pEvtObject = event.GetEventObject();
1224
// memorize position of the mouse ctrl key as copy/delete flag
1225
m_MouseCtrlKeyDown = event.ControlDown();
1227
//LOGIT(wxT("MouseCtrlKeyDown[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
1232
// ----------------------------------------------------------------------------
1233
void CodeSnippetsTreeCtrl::OnMouseWheelEvent(wxMouseEvent& event)
1234
// ----------------------------------------------------------------------------
1236
// Ctrl-MouseWheel rotation changes treeCtrl font
1238
m_MouseCtrlKeyDown = event.ControlDown();
1240
//LOGIT(wxT("treeCtrl:OnMouseWheel[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
1242
if (not m_MouseCtrlKeyDown) {event.Skip(); return;}
1244
int nRotation = event.GetWheelRotation();
1245
wxFont ctrlFont = GetFont();
1248
ctrlFont.SetPointSize( ctrlFont.GetPointSize()-1);
1250
ctrlFont.SetPointSize( ctrlFont.GetPointSize()+1);
1255
// ----------------------------------------------------------------------------
1256
#if defined(__WXMSW__)
1257
void CodeSnippetsTreeCtrl::MSW_MouseMove(int x, int y )
1258
// ----------------------------------------------------------------------------
1260
// Move mouse uses a very strange coordinate system.
1261
// It uses screen positions with a range of 0 to 65535
1263
// Move the MSW mouse to absolute screen coords x,y
1264
double fScreenWidth = ::GetSystemMetrics( SM_CXSCREEN )-1;
1265
double fScreenHeight = ::GetSystemMetrics( SM_CYSCREEN )-1;
1266
double fx = x*(65535.0f/fScreenWidth);
1267
double fy = y*(65535.0f/fScreenHeight);
1269
Input.type = INPUT_MOUSE;
1270
Input.mi.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
1271
Input.mi.dx = (LONG)fx;
1272
Input.mi.dy = (LONG)fy;
1273
::SendInput(1,&Input,sizeof(INPUT));
1276
// ----------------------------------------------------------------------------
1277
wxTreeItemId CodeSnippetsTreeCtrl::ConvertSnippetToCategory(wxTreeItemId itemId)
1278
// ----------------------------------------------------------------------------
1280
// Convert Snippet to Category, then insert the old snippet
1281
wxTreeItemId badItemId = (void*)0;
1283
if ( not IsSnippet(itemId)) return badItemId;
1284
// memorize id of this snippet
1285
wxTreeItemId oldItemId = itemId;
1286
if ( not oldItemId.IsOk() ) return badItemId;
1287
// memorize parent id of this snippet
1288
wxTreeItemId itemParent = GetItemParent(oldItemId);
1290
// create Xml document from selected tree item
1291
TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( oldItemId );
1292
if (not pDoc) return badItemId;
1294
// Create new Category
1295
wxTreeItemId newCategoryId = AddCategory( itemParent,
1296
GetItemText(oldItemId), GetSnippetID(oldItemId), false );
1298
// Insert old Snippet Item under new Category
1299
TiXmlElement* root = pDoc->RootElement();
1302
// Get the first xml element
1303
TiXmlElement* firstChild = root->FirstChildElement("item");
1305
{ // insert Tree items from xml document
1306
//-LoadSnippets(firstChild, newCategoryId);
1307
LoadItemsFromXmlNode( firstChild, newCategoryId);
1311
// remove the old tree item
1312
RemoveItem( oldItemId );
1313
delete pDoc; pDoc = 0;
1314
return newCategoryId;
1316
// ----------------------------------------------------------------------------
1317
TiXmlDocument* CodeSnippetsTreeCtrl::CopyTreeNodeToXmlDoc(wxTreeItemId TreeItemId )
1318
// ----------------------------------------------------------------------------
1320
// Copy a Tree node to an Xml Document
1322
wxTreeItemId itemId = TreeItemId;
1323
if (not itemId.IsOk() )
1325
itemId = GetSelection();
1327
if (not itemId.IsOk()) return NULL;
1329
TiXmlDocument* pDoc = new TiXmlDocument;
1330
TiXmlDeclaration header("1.0", "UTF-8", "yes");
1331
pDoc->InsertEndChild(header);
1333
TiXmlElement snippetsElement("snippets");
1334
CopySnippetsToXmlDoc(&snippetsElement, itemId);
1336
pDoc->InsertEndChild(snippetsElement);
1340
} // end of SaveSnippetsToFile
1341
// ----------------------------------------------------------------------------
1342
void CodeSnippetsTreeCtrl::CopySnippetsToXmlDoc(TiXmlNode* Node, const wxTreeItemId& itemID)
1343
// ----------------------------------------------------------------------------
1345
// Recursively copy Tree item and all its children to an Xml document node
1347
wxTreeItemIdValue cookie;
1348
//wxTreeItemId item = GetFirstChild(parentID, cookie );
1349
wxTreeItemId item = itemID;
1351
// Loop through all items
1354
// Get the item's information
1355
const SnippetItemData* data = (SnippetItemData*)GetItemData(item);
1360
// Begin item element
1361
TiXmlElement element("item");
1363
// Write the item's name
1364
element.SetAttribute("name", GetItemText(item).mb_str());
1366
// Write the type of the item
1367
switch (data->GetType())
1369
case SnippetItemData::TYPE_CATEGORY:
1370
element.SetAttribute("type", "category");
1373
case SnippetItemData::TYPE_SNIPPET:
1374
element.SetAttribute("type", "snippet");
1382
if (data->GetType() == SnippetItemData::TYPE_SNIPPET)
1384
TiXmlElement snippetElement("snippet");
1385
TiXmlText snippetElementText(data->GetSnippet().mb_str());
1386
snippetElement.InsertEndChild(snippetElementText);
1387
element.InsertEndChild(snippetElement);
1389
// LOGIT( _T("Snippet[%s]"), data->GetSnippet().GetData() );
1393
// Check if this item has children
1394
if(ItemHasChildren(item))
1396
// If it has, check those too
1397
//-SaveSnippets(&element, item);
1398
SaveItemsToXmlNode(&element, item);
1401
// Insert the item we created as parent node's child
1402
//parentNode->InsertEndChild(element);
1403
Node->InsertEndChild(element);
1405
// Check the next child
1406
item = GetNextChild( itemID, cookie);
1408
}//CopySnippetsToXmlDoc
1409
// ----------------------------------------------------------------------------
1410
void CodeSnippetsTreeCtrl::CopyXmlDocToTreeNode(TiXmlDocument* pTiXmlDoc, wxTreeItemId targetItem )
1411
// ----------------------------------------------------------------------------
1413
TiXmlElement* root = pTiXmlDoc->RootElement();
1416
// Get the source xml element
1417
TiXmlElement* firstChild = root->FirstChildElement("item");
1419
{ // insert into target Tree items from source xml document
1420
LoadItemsFromXmlNode( firstChild, targetItem);
1425
// ----------------------------------------------------------------------------
1426
void CodeSnippetsTreeCtrl::EditSnippetAsFileLink()
1427
// ----------------------------------------------------------------------------
1429
// Open snippet text as a file name. Ie, the text should contain a filename.
1430
// Else just open a temp file with the snippet text as data.
1432
#if defined(LOGGING)
1433
LOGIT( _T("EditSnippetAsFileLink[%s]"),wxT("") );
1436
if (not IsSnippet() ) return;
1438
// If snippet is file, open it
1439
wxTreeItemId itemId = GetAssociatedItemID();
1440
SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
1441
wxString FileName = GetSnippetFileLink( itemId );
1442
LOGIT( _T("EditSnippetsAsFileLlink()FileName[%s]"),FileName.c_str() );
1444
if (FileName.Length() > 128)
1445
{ // if text is > 128 characters, open a temp file with snippet text as data.
1446
EditSnippetAsText();
1451
// no filename, edit text file
1452
if ( (FileName.IsEmpty())
1453
|| (not ::wxFileExists( FileName)) )
1454
{ // if, non-existent file, open snippet text as data
1455
EditSnippetAsText();
1251
1459
// we have an actual file link, not just text.
1252
// use user specified editor, else hard coded pgms.
1253
wxString pgmName = GetConfig()->SettingsExternalEditor;
1254
LOGIT( _T("PgmName[%s]"),pgmName.c_str() );
1256
// Do: if external pgm name is blank, or file link doesn't exists
1257
// must be text only
1258
if ( pgmName.IsEmpty() || ( not ::wxFileExists(pgmName)) )
1260
EditSnippet( pSnippetItemData, FileName);
1264
// edit file link with user settings external program.
1265
// file name must be surrounded with quotes when using wxExecute
1266
if ( ::wxFileExists(pgmName) )
1267
{ wxString execString = pgmName + wxT(" \"") + FileName + wxT("\"");
1269
LOGIT( _T("OpenAsFileLink[%s]"), execString.GetData() );
1271
::wxExecute( execString);
1276
// ----------------------------------------------------------------------------
1277
void CodeSnippetsTreeCtrl::OpenSnippetAsFileLink()
1278
// ----------------------------------------------------------------------------
1280
// Open snippet text as a file name. Ie, the first text line should contain a filename.
1282
if (not IsSnippet() ) return;
1284
// If snippet is file, open it
1285
wxTreeItemId itemId = GetAssociatedItemID();
1286
wxString FileName = GetSnippetFileLink( itemId );
1287
LOGIT( _T("OpenSnippetsAsFileLlink()FileName[%s]"),FileName.c_str() );
1289
if (FileName.Length() > 128)
1290
{ // if text is > 128 characters, open a temp file with snippet text as data.
1291
EditSnippetAsText();
1295
// user requested "MIME" type to open file
1296
EditSnippetWithMIME();
1300
// ----------------------------------------------------------------------------
1301
void CodeSnippetsTreeCtrl::EditSnippetAsText()
1302
// ----------------------------------------------------------------------------
1305
#if defined(LOGGING)
1306
LOGIT( _T("EditSnippetAsText[%s]"),wxT("") );
1308
SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
1310
// if no user specified editor, use default editor
1311
wxString editorName = GetConfig()->SettingsExternalEditor ;
1312
if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1314
EditSnippet( pSnippetItemData );
1318
if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1320
#if defined(__WXMSW__)
1321
editorName = wxT("notepad");
1322
#elif defined(__UNIX__)
1323
editorName = wxT("vi");
1325
wxString msg(wxT("Using default editor: ")+editorName+wxT("\n"));
1326
if (GetConfig()->IsApplication() ) msg = msg + wxT("Use Menu->");
1327
else msg = msg + wxT("Right click Root item. Use ");
1328
msg = msg + wxT("Settings to set a better editor.\n");
1332
// let user edit the snippet text
1333
// write text to temp file
1334
// invoke the editor
1335
// read text back into snippet
1337
wxFileName tmpFileName = wxFileName::CreateTempFileName(wxEmptyString);
1339
wxFile tmpFile( tmpFileName.GetFullPath(), wxFile::write);
1340
if (not tmpFile.IsOpened() )
1342
messageBox(wxT("Open failed for:")+tmpFileName.GetFullPath());
1345
wxString snippetData( GetSnippet() );
1346
tmpFile.Write( csU2C(snippetData), snippetData.Length());
1348
// Invoke the external editor on the temporary file
1349
// file name must be surrounded with quotes when using wxExecute
1350
wxString execString = editorName + wxT(" \"") + tmpFileName.GetFullPath() + wxT("\"");
1353
LOGIT( _T("Properties wxExecute[%s]"), execString.GetData() );
1356
// Invoke the external editor and wait for its termination
1357
::wxExecute( execString, wxEXEC_SYNC);
1358
// Read the edited data back into the snippet text
1359
tmpFile.Open(tmpFileName.GetFullPath(), wxFile::read);
1360
if (not tmpFile.IsOpened() )
1361
{ messageBox(wxT("Abort.Error reading temp data file."));
1364
unsigned long fileSize = tmpFile.Length();
1367
LOGIT( _T("New file size[%d]"),fileSize );
1370
// check the data for validity
1371
char pBuf[fileSize+1];
1372
size_t nResult = tmpFile.Read( pBuf, fileSize );
1373
if ( wxInvalidOffset == (int)nResult )
1374
messageBox(wxT("Error reading temp file"));
1379
//LOGIT( _T("pBuf[%s]"), pBuf );
1382
// convert data back to internal format
1383
snippetData = csC2U( pBuf );
1386
//LOGIT( _T("snippetData[%s]"), snippetData.GetData() );
1389
// delete the temporary file
1390
::wxRemoveFile( tmpFileName.GetFullPath() );
1393
SetSnippet( snippetData );
1396
}//EditSnippetAsText
1397
// ----------------------------------------------------------------------------
1398
void CodeSnippetsTreeCtrl::SaveSnippetAsFileLink()
1399
// ----------------------------------------------------------------------------
1401
wxTreeItemId itemId = GetAssociatedItemID();
1402
if (not itemId.IsOk()) return;
1404
if ( not IsSnippet()) return;
1406
// Dump the snippet text to file, then place the filename in the snippet text area
1408
// Dump Snippet field into a temporary file
1409
wxString snippetLabel = GetSnippetLabel();
1410
wxString snippetData = GetSnippet();
1411
wxString fileName = GetSnippetFileLink();
1415
// if file already exists preserve the old data
1416
if ( ::wxFileExists( fileName ) )
1417
{ // item snippet is already a filename
1418
answer = messageBox(
1419
wxT("Item is already a file link named:\n")+fileName
1420
+ wxT(" \n\nAre you sure you want to rewrite the file?\n"),
1421
wxT("Warning"),wxYES|wxNO); //, GetMainFrame(), mousePosn.x, mousePosn.y);
1422
if ( wxYES == answer)
1423
{ // read data from old file
1424
wxFile oldFile( fileName, wxFile::read);
1425
if (not oldFile.IsOpened() )
1426
{ messageBox(wxT("Abort.Error reading data file."));
1429
unsigned long fileSize = oldFile.Length();
1430
char* pBuf = new char[fileSize+1];
1431
oldFile.Read( pBuf, fileSize );
1433
snippetData = csC2U( pBuf );
1438
if ( wxNO == answer ) return;
1440
// filter filename, removing all illegal filename characters
1441
wxString newFileName = snippetLabel+wxT(".txt");
1442
wxFileName snippetFileName( newFileName) ;
1443
#if defined(BUILDING_PLUGIN)
1444
// substitute any $(macro) text
1445
Manager::Get()->GetMacrosManager()->ReplaceMacros(newFileName);
1446
//-LOGIT( _T("$macros substitute[%s]"),newFileName.c_str() );
1449
//newFileName = snippetFileName.GetFullName();
1450
wxString forbidden = snippetFileName.GetForbiddenChars();
1451
for (size_t i=0; i < forbidden.Length(); ++i)
1452
newFileName.Replace( wxString(forbidden[i]), wxT(""),true);
1454
// LOGIT( _T("forbidden[%s],filename[%s]"), forbidden.GetData(),newFileName.GetData());
1457
// Ask user for filename
1458
wxFileDialog dlg(this, //parent window
1459
_("Save as text file"), //message
1460
GetConfig()->SettingsSnippetsFolder, //default directory
1461
newFileName, //default file
1462
wxT("*.*"), //wildcards
1463
wxSAVE | wxOVERWRITE_PROMPT); //style
1464
// move dialog into the parents frame space
1465
wxPoint mousePosn = ::wxGetMousePosition();
1466
(&dlg)->Move(mousePosn.x, mousePosn.y);
1467
if (dlg.ShowModal() != wxID_OK) return;
1469
newFileName = dlg.GetPath();
1472
LOGIT( _T("New filename[%s]"), newFileName.GetData() );
1475
if ( newFileName.IsEmpty() ) return;
1476
// Verify filename, or create
1477
wxFile newFile( newFileName, wxFile::write);
1478
if (not newFile.IsOpened() )
1480
messageBox(wxT("Open failed for:")+newFileName);
1483
newFile.Write( csU2C(snippetData), snippetData.Length());
1486
SetSnippet( newFileName );
1488
// verify the item tree image
1489
if ( IsFileSnippet() )
1490
SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
1492
SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
1496
// ----------------------------------------------------------------------------
1497
bool CodeSnippetsTreeCtrl::EditSnippetProperties(wxTreeItemId& itemId)
1498
// ----------------------------------------------------------------------------
1500
if ( not IsSnippet(itemId) ) return false;
1503
wxSemaphore waitSem;
1504
SnippetProperty* pdlg = new SnippetProperty(GetSnippetsTreeCtrl(), itemId, &waitSem);
1505
result = ExecuteDialog(pdlg, waitSem);
1506
// Save any changed data
1507
if ( result == wxID_OK )
1509
// verify the item tree image
1510
SetSnippetImage(itemId);
1512
if (result == wxID_OK) {
1513
SetFileChanged(true);
1516
return (result = (result==wxID_OK));
1519
// ----------------------------------------------------------------------------
1520
void CodeSnippetsTreeCtrl::EditSnippet(SnippetItemData* pSnippetItemData, wxString fileName)
1521
// ----------------------------------------------------------------------------
1460
// use user specified editor, else hard coded pgms.
1461
wxString pgmName = GetConfig()->SettingsExternalEditor;
1462
#if defined(LOGGING)
1463
LOGIT( _T("PgmName[%s]"),pgmName.c_str() );
1465
// Do: if external pgm name is blank, or file link doesn't exists
1466
// must be text only
1467
if ( pgmName.IsEmpty() || ( not ::wxFileExists(pgmName)) )
1469
EditSnippet( pSnippetItemData, FileName);
1473
// edit file link with user settings external program.
1474
// file name must be surrounded with quotes when using wxExecute
1475
if ( ::wxFileExists(pgmName) )
1476
{ wxString execString = pgmName + wxT(" \"") + FileName + wxT("\"");
1478
LOGIT( _T("OpenAsFileLink[%s]"), execString.GetData() );
1480
::wxExecute( execString);
1485
// ----------------------------------------------------------------------------
1486
void CodeSnippetsTreeCtrl::OpenSnippetAsFileLink()
1487
// ----------------------------------------------------------------------------
1489
// Open snippet text as a file name. Ie, the first text line should contain a filename.
1491
if (not IsSnippet() ) return;
1493
// If snippet is file, open it
1494
wxTreeItemId itemId = GetAssociatedItemID();
1495
wxString FileName = GetSnippetFileLink( itemId );
1496
LOGIT( _T("OpenSnippetsAsFileLlink()FileName[%s]"),FileName.c_str() );
1498
if (FileName.Length() > 128)
1499
{ // if text is > 128 characters, open a temp file with snippet text as data.
1500
EditSnippetAsText();
1504
// user requested "MIME" type to open file
1505
EditSnippetWithMIME();
1509
// ----------------------------------------------------------------------------
1510
void CodeSnippetsTreeCtrl::EditSnippetAsText()
1511
// ----------------------------------------------------------------------------
1514
#if defined(LOGGING)
1515
LOGIT( _T("EditSnippetAsText[%s]"),wxT("") );
1517
SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
1519
// if no user specified editor, use default editor
1520
wxString editorName = GetConfig()->SettingsExternalEditor ;
1521
if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1523
EditSnippet( pSnippetItemData );
1527
if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1529
#if defined(__WXMSW__)
1530
editorName = wxT("notepad");
1531
#elif defined(__UNIX__)
1532
editorName = wxT("vi");
1534
wxString msg(wxT("Using default editor: ")+editorName+wxT("\n"));
1535
if (GetConfig()->IsApplication() ) msg = msg + wxT("Use Menu->");
1536
else msg = msg + wxT("Right click Root item. Use ");
1537
msg = msg + wxT("Settings to set a better editor.\n");
1538
GenericMessageBox( msg );
1541
// let user edit the snippet text
1542
// write text to temp file
1543
// invoke the editor
1544
// read text back into snippet
1546
wxFileName tmpFileName = wxFileName::CreateTempFileName(wxEmptyString);
1548
wxFile tmpFile( tmpFileName.GetFullPath(), wxFile::write);
1549
if (not tmpFile.IsOpened() )
1551
GenericMessageBox(wxT("Open failed for:")+tmpFileName.GetFullPath());
1554
wxString snippetData( GetSnippet() );
1555
tmpFile.Write( csU2C(snippetData), snippetData.Length());
1557
// Invoke the external editor on the temporary file
1558
// file name must be surrounded with quotes when using wxExecute
1559
wxString execString = editorName + wxT(" \"") + tmpFileName.GetFullPath() + wxT("\"");
1562
LOGIT( _T("Properties wxExecute[%s]"), execString.GetData() );
1565
// Invoke the external editor and wait for its termination
1566
::wxExecute( execString, wxEXEC_SYNC);
1567
// Read the edited data back into the snippet text
1568
tmpFile.Open(tmpFileName.GetFullPath(), wxFile::read);
1569
if (not tmpFile.IsOpened() )
1570
{ GenericMessageBox(wxT("Abort.Error reading temp data file."));
1573
unsigned long fileSize = tmpFile.Length();
1576
LOGIT( _T("New file size[%d]"),fileSize );
1579
// check the data for validity
1580
char pBuf[fileSize+1];
1581
size_t nResult = tmpFile.Read( pBuf, fileSize );
1582
if ( wxInvalidOffset == (int)nResult )
1583
GenericMessageBox(wxT("Error reading temp file"));
1588
//LOGIT( _T("pBuf[%s]"), pBuf );
1591
// convert data back to internal format
1592
snippetData = csC2U( pBuf );
1595
//LOGIT( _T("snippetData[%s]"), snippetData.GetData() );
1598
// delete the temporary file
1599
::wxRemoveFile( tmpFileName.GetFullPath() );
1602
SetSnippet( snippetData );
1605
}//EditSnippetAsText
1606
// ----------------------------------------------------------------------------
1607
void CodeSnippetsTreeCtrl::SaveSnippetAsFileLink()
1608
// ----------------------------------------------------------------------------
1610
wxTreeItemId itemId = GetAssociatedItemID();
1611
if (not itemId.IsOk()) return;
1613
if ( not IsSnippet()) return;
1615
// Dump the snippet text to file, then place the filename in the snippet text area
1617
// Dump Snippet field into a temporary file
1618
wxString snippetLabel = GetSnippetLabel();
1619
wxString snippetData = GetSnippet();
1620
wxString fileName = GetSnippetFileLink();
1624
// if file already exists preserve the old data
1625
if ( ::wxFileExists( fileName ) )
1626
{ // item snippet is already a filename
1627
answer = GenericMessageBox(
1628
wxT("Item is already a file link named:\n")+fileName
1629
+ wxT(" \n\nAre you sure you want to rewrite the file?\n"),
1630
wxT("Warning"),wxYES|wxNO); //, GetMainFrame(), mousePosn.x, mousePosn.y);
1631
if ( wxYES == answer)
1632
{ // read data from old file
1633
wxFile oldFile( fileName, wxFile::read);
1634
if (not oldFile.IsOpened() )
1635
{ GenericMessageBox(wxT("Abort.Error reading data file."));
1638
unsigned long fileSize = oldFile.Length();
1639
char* pBuf = new char[fileSize+1];
1640
oldFile.Read( pBuf, fileSize );
1642
snippetData = csC2U( pBuf );
1647
if ( wxNO == answer ) return;
1649
// filter filename, removing all illegal filename characters
1650
wxString newFileName = snippetLabel+wxT(".txt");
1651
wxFileName snippetFileName( newFileName) ;
1652
//-#if defined(BUILDING_PLUGIN)
1653
// substitute any $(macro) text
1654
static const wxString delim(_T("$%["));
1655
if( newFileName.find_first_of(delim) != wxString::npos )
1656
Manager::Get()->GetMacrosManager()->ReplaceMacros(newFileName);
1657
//-LOGIT( _T("$macros substitute[%s]"),newFileName.c_str() );
1660
//newFileName = snippetFileName.GetFullName();
1661
wxString forbidden = snippetFileName.GetForbiddenChars();
1662
for (size_t i=0; i < forbidden.Length(); ++i)
1663
newFileName.Replace( wxString(forbidden[i]), wxT(""),true);
1665
// LOGIT( _T("forbidden[%s],filename[%s]"), forbidden.GetData(),newFileName.GetData());
1668
// Ask user for filename
1669
wxFileDialog dlg(this, //parent window
1670
_("Save as text file"), //message
1671
GetConfig()->SettingsSnippetsFolder, //default directory
1672
newFileName, //default file
1673
wxT("*.*"), //wildcards
1674
wxFD_SAVE | wxFD_OVERWRITE_PROMPT); //style
1675
// move dialog into the parents frame space
1676
wxPoint mousePosn = ::wxGetMousePosition();
1677
(&dlg)->Move(mousePosn.x, mousePosn.y);
1678
if (dlg.ShowModal() != wxID_OK) return;
1680
newFileName = dlg.GetPath();
1683
LOGIT( _T("New filename[%s]"), newFileName.GetData() );
1686
if ( newFileName.IsEmpty() ) return;
1687
// Verify filename, or create
1688
wxFile newFile( newFileName, wxFile::write);
1689
if (not newFile.IsOpened() )
1691
GenericMessageBox(wxT("Open failed for:")+newFileName);
1694
newFile.Write( csU2C(snippetData), snippetData.Length());
1697
SetSnippet( newFileName );
1699
// verify the item tree image
1700
if ( IsFileSnippet() )
1701
SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
1703
SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
1707
// ----------------------------------------------------------------------------
1708
bool CodeSnippetsTreeCtrl::EditSnippetProperties(wxTreeItemId& itemId)
1709
// ----------------------------------------------------------------------------
1711
if ( not IsSnippet(itemId) ) return false;
1714
wxSemaphore waitSem;
1715
SnippetProperty* pdlg = new SnippetProperty(GetSnippetsTreeCtrl(), itemId, &waitSem);
1717
// Add Properties edit window to DragScroll managed windows
1718
DragScrollEvent dsevt(wxEVT_DRAGSCROLL_EVENT , idDragScrollAddWindow);
1719
dsevt.SetEventObject((wxObject*)pdlg->m_SnippetEditCtrl);
1720
GetConfig()->GetDragScrollEvtHandler()->AddPendingEvent( dsevt );
1722
result = ExecuteDialog(pdlg, waitSem);
1723
// Save any changed data
1724
if ( result == wxID_OK )
1726
// verify the item tree image
1727
SetSnippetImage(itemId);
1729
if (result == wxID_OK) {
1730
SetFileChanged(true);
1733
// Remove Properties edit window from DragScroll managed windows
1734
dsevt.SetId(idDragScrollRemoveWindow);
1735
dsevt.SetEventObject((wxObject*)pdlg->m_SnippetEditCtrl);
1736
GetConfig()->GetDragScrollEvtHandler()->AddPendingEvent( dsevt );
1739
return (result = (result==wxID_OK));
1741
// ----------------------------------------------------------------------------
1742
void CodeSnippetsTreeCtrl::EditSnippet(SnippetItemData* pSnippetItemData, wxString fileName)
1743
// ----------------------------------------------------------------------------
1523
1745
// just focus any already open snippet items
1524
int knt = m_aDlgRetcodes.GetCount();
1525
for (int i = 0; i<knt ; ++i )
1526
{ EditSnippetFrame* pesf = (EditSnippetFrame*)m_aDlgPtrs.Item(i);
1748
int knt = m_aDlgRetcodes.GetCount();
1749
for (int i = 0; i<knt ; ++i )
1750
{ EditSnippetFrame* pesf = (EditSnippetFrame*)m_aDlgPtrs.Item(i);
1527
1751
if (not pesf) continue;
1528
if ( pesf->GetSnippetId() == GetAssociatedItemID() )
1752
if (not utils.WinExists(pesf))
1755
if ( pesf->GetSnippetId() == GetAssociatedItemID() )
1530
m_aDlgPtrs.Item(i)->Iconize(false);
1531
m_aDlgPtrs.Item(i)->SetFocus();
1757
// if return code has been set, this frame is set to terminate
1758
if ( (int)m_aDlgRetcodes.GetCount() < i)
1760
if ( m_aDlgRetcodes.Item(i) not_eq 0)
1762
m_aDlgPtrs.Item(i)->Iconize(false);
1763
m_aDlgPtrs.Item(i)->SetFocus();
1535
// Create editor for snippet item
1536
if (SnippetItemData* itemData = (SnippetItemData*)(GetSnippetsTreeCtrl()->GetItemData(GetAssociatedItemID() ))) {
1537
wxString snippetText = itemData->GetSnippet();
1538
m_aDlgRetcodes.Add(0);
1539
int* pRetcode = &m_aDlgRetcodes.Last();
1768
// Create editor for snippet item
1769
if (SnippetItemData* itemData = (SnippetItemData*)( GetItemData(GetAssociatedItemID() )))
1771
wxString snippetText = itemData->GetSnippet();
1772
m_aDlgRetcodes.Add(0); // new slot for return code
1773
int* pRetcode = &m_aDlgRetcodes.Last();
1541
1775
EditSnippetFrame* pdlg = new EditSnippetFrame( GetAssociatedItemID(), pRetcode );
1542
// cascade multiple editors
1543
int knt = m_aDlgPtrs.GetCount();
1544
if (pdlg && (knt > 0) ){
1546
pdlg->GetPosition(&x, &y );
1548
pdlg->ClientToScreen(&x, &y );
1551
pdlg->Move(x+knt,y+knt);
1556
m_aDlgPtrs.Add((wxDialog*)pdlg);
1559
m_aDlgRetcodes.RemoveAt(m_aDlgRetcodes.GetCount());
1564
// ----------------------------------------------------------------------------
1565
void CodeSnippetsTreeCtrl::EditSnippetWithMIME()
1566
// ----------------------------------------------------------------------------
1568
wxTreeItemId itemId = GetAssociatedItemID();
1569
if (not itemId.IsOk()) return;
1570
if ( not IsSnippet()) return;
1572
wxString snippetLabel = GetSnippetLabel();
1573
wxString snippetData = GetSnippet();
1574
wxString fileName = GetSnippetFileLink();
1575
LOGIT( _T("EditSnippetWithMime[%s]"), fileName.c_str() );
1576
if ( fileName.IsEmpty() ) return;
1578
wxFileName file(fileName);
1579
wxString fileExt = file.GetExt();
1581
// MIME search fails on a url. Do it brute force
1582
if ( ( fileName.StartsWith(wxT("http://")) )
1583
|| ( fileName.StartsWith(wxT("file://")) )
1584
|| ( fileName.StartsWith(wxT("ftp://")) )
1585
|| ( fileExt == wxT("html") )
1586
|| ( fileExt == wxT("htm") )
1588
{ wxLaunchDefaultBrowser( fileName);
1592
if ( not ::wxFileExists(fileName) ) return;
1594
wxString fileNameExt;
1595
::wxSplitPath( fileName, /*path*/0, /*name*/0, &fileNameExt);
1596
if ( fileNameExt.IsEmpty() ) return;
1598
wxString s_defaultExt = _T("xyz");
1601
if ( !!fileNameExt )
1603
s_defaultExt = fileNameExt;
1605
// init MIME database if not done yet
1606
if ( !m_mimeDatabase )
1608
////m_mimeDatabase = new wxMimeTypesManager;
1609
// use global pointer instead of above instantiation
1610
m_mimeDatabase = wxTheMimeTypesManager;
1612
////static const wxFileTypeInfo fallbacks[] =
1614
//// wxFileTypeInfo(_T("application/xyz"),
1616
//// _T("XyZ -p %s"),
1617
//// _T("The one and only XYZ format file"),
1618
//// _T("xyz"), _T("123"), NULL),
1619
//// wxFileTypeInfo(_T("text/html"),
1621
//// _T("lynx -dump %s | lpr"),
1622
//// _T("HTML document (from fallback)"),
1623
//// _T("htm"), _T("html"), NULL),
1625
//// // must terminate the table with this!
1626
//// wxFileTypeInfo()
1629
////m_mimeDatabase->AddFallbacks(fallbacks);
1632
wxFileType *filetype = m_mimeDatabase->GetFileTypeFromExtension(fileNameExt);
1635
msg << _T("Unknown extension '") << fileNameExt << _T("'\n");
1639
wxString type, desc, open;
1640
filetype->GetMimeType(&type);
1641
filetype->GetDescription(&desc);
1643
//wxString filename = _T("filename");
1644
wxString filename = fileName;
1645
//filename << _T(".") << fileNameExt;
1646
wxFileType::MessageParameters params(filename, type);
1647
filetype->GetOpenCommand(&open, params);
1650
msg << _T("MIME information about extension '") << fileNameExt << _T('\n')
1651
<< _T("\tMIME type: ") << ( !type ? wxT("unknown")
1652
: type.c_str() ) << _T('\n')
1653
<< _T("\tDescription: ") << ( !desc ? wxEmptyString : desc.c_str() )
1655
<< _T("\tCommand to open: ") << ( !open ? wxT("no") : open.c_str() )
1661
::wxExecute( open, wxEXEC_ASYNC);
1665
LOGIT( _T("EditSnippetWithMIME()[%s]"),msg.c_str() );
1668
// Do not use these when using global wxTheMimeTypesManager pointer
1669
////if ( m_mimeDatabase ) delete m_mimeDatabase;
1670
////m_mimeDatabase = 0;
1674
// ----------------------------------------------------------------------------
1675
int CodeSnippetsTreeCtrl::ExecuteDialog(wxDialog* pdlg, wxSemaphore& waitSem)
1676
// ----------------------------------------------------------------------------
1678
if (m_pPropertiesDialog) return 0;
1680
m_pPropertiesDialog = pdlg;
1683
wxWindow* pw = this;
1684
if (pw && pw->GetParent()) //
1685
{ pw = pw->GetParent();
1687
if (pw && pw->GetParent()) //This is the SnippetWindow parent
1688
{ pw = pw->GetParent();
1691
// Grab main apps close function so dlg isn't orphaned|crashed on close
1692
GetConfig()->GetMainFrame()->Connect( wxEVT_CLOSE_WINDOW,
1693
(wxObjectEventFunction)(wxEventFunction)
1694
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown,NULL,this);
1696
// Grab parents close function so dlg isn't orphaned|crashed on close)
1697
pw->Connect( wxEVT_CLOSE_WINDOW,
1698
(wxObjectEventFunction)(wxEventFunction)
1699
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown,NULL,this);
1777
// cascade multiple editors
1778
int knt = m_aDlgPtrs.GetCount();
1779
if (pdlg && (knt > 0) ){
1781
pdlg->GetPosition(&x, &y );
1783
pdlg->ClientToScreen(&x, &y );
1786
pdlg->Move(x+knt,y+knt);
1791
m_aDlgPtrs.Add((wxScrollingDialog*)pdlg);
1794
m_aDlgRetcodes.RemoveAt(m_aDlgRetcodes.GetCount());
1799
// ----------------------------------------------------------------------------
1800
void CodeSnippetsTreeCtrl::EditSnippetWithMIME()
1801
// ----------------------------------------------------------------------------
1803
wxTreeItemId itemId = GetAssociatedItemID();
1804
if (not itemId.IsOk()) return;
1805
if ( not IsSnippet()) return;
1807
wxString snippetLabel = GetSnippetLabel();
1808
wxString snippetData = GetSnippet();
1809
wxString fileName = GetSnippetFileLink();
1810
LOGIT( _T("EditSnippetWithMime[%s]"), fileName.c_str() );
1811
if ( fileName.IsEmpty() ) return;
1813
wxFileName file(fileName);
1814
wxString fileExt = file.GetExt();
1816
// MIME search fails on a url. Do it brute force
1817
if ( ( fileName.StartsWith(wxT("http://")) )
1818
|| ( fileName.StartsWith(wxT("file://")) )
1819
|| ( fileName.StartsWith(wxT("ftp://")) )
1820
|| ( fileExt == wxT("html") )
1821
|| ( fileExt == wxT("htm") )
1823
{ wxLaunchDefaultBrowser( fileName);
1827
if ( not ::wxFileExists(fileName) ) return;
1829
wxString fileNameExt;
1830
#if wxCHECK_VERSION(2, 9, 0)
1831
wxFileName::SplitPath( fileName, /*volume*/0, /*path*/0, /*name*/0, &fileNameExt);
1833
::wxSplitPath( fileName, /*path*/0, /*name*/0, &fileNameExt);
1835
if ( fileNameExt.IsEmpty() ) return;
1837
wxString s_defaultExt = _T("xyz");
1840
if ( !!fileNameExt )
1842
s_defaultExt = fileNameExt;
1844
// init MIME database if not done yet
1845
if ( !m_mimeDatabase )
1847
////m_mimeDatabase = new wxMimeTypesManager;
1848
// use global pointer instead of above instantiation
1849
m_mimeDatabase = wxTheMimeTypesManager;
1851
////static const wxFileTypeInfo fallbacks[] =
1853
//// wxFileTypeInfo(_T("application/xyz"),
1855
//// _T("XyZ -p %s"),
1856
//// _T("The one and only XYZ format file"),
1857
//// _T("xyz"), _T("123"), NULL),
1858
//// wxFileTypeInfo(_T("text/html"),
1860
//// _T("lynx -dump %s | lpr"),
1861
//// _T("HTML document (from fallback)"),
1862
//// _T("htm"), _T("html"), NULL),
1864
//// // must terminate the table with this!
1865
//// wxFileTypeInfo()
1868
////m_mimeDatabase->AddFallbacks(fallbacks);
1871
wxFileType *filetype = m_mimeDatabase->GetFileTypeFromExtension(fileNameExt);
1874
msg << _T("Unknown extension '") << fileNameExt << _T("'\n");
1878
wxString type, desc, open;
1879
filetype->GetMimeType(&type);
1880
filetype->GetDescription(&desc);
1882
//wxString filename = _T("filename");
1883
wxString filename = fileName;
1884
//filename << _T(".") << fileNameExt;
1885
wxFileType::MessageParameters params(filename, type);
1886
filetype->GetOpenCommand(&open, params);
1889
msg << _T("MIME information about extension '") << fileNameExt << _T('\n')
1890
<< _T("\tMIME type: ") << ( !type ? wxT("unknown")
1891
: type.c_str() ) << _T('\n')
1892
<< _T("\tDescription: ") << ( !desc ? wxEmptyString : desc.c_str() )
1894
<< _T("\tCommand to open: ") << ( !open ? wxT("no") : open.c_str() )
1899
#if wxCHECK_VERSION(2, 9, 0)
1900
if ( !open.IsEmpty() )
1904
::wxExecute( open, wxEXEC_ASYNC);
1908
LOGIT( _T("EditSnippetWithMIME()[%s]"),msg.c_str() );
1911
// Do not use these when using global wxTheMimeTypesManager pointer
1912
////if ( m_mimeDatabase ) delete m_mimeDatabase;
1913
////m_mimeDatabase = 0;
1917
// ----------------------------------------------------------------------------
1918
int CodeSnippetsTreeCtrl::ExecuteDialog(wxScrollingDialog* pdlg, wxSemaphore& waitSem)
1919
// ----------------------------------------------------------------------------
1921
if (m_pPropertiesDialog) return 0;
1923
m_pPropertiesDialog = pdlg;
1926
wxWindow* pw = this;
1927
if (pw && pw->GetParent()) //
1928
{ pw = pw->GetParent();
1930
if (pw && pw->GetParent()) //This is the SnippetWindow parent
1931
{ pw = pw->GetParent();
1934
// Grab main apps close function so dlg isn't orphaned|crashed on close
1935
GetConfig()->GetMainFrame()->Connect( wxEVT_CLOSE_WINDOW,
1936
(wxObjectEventFunction)(wxEventFunction)
1937
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown,NULL,this);
1939
// Grab parents close function so dlg isn't orphaned|crashed on close)
1940
pw->Connect( wxEVT_CLOSE_WINDOW,
1941
(wxObjectEventFunction)(wxEventFunction)
1942
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown,NULL,this);
1701
1944
// The following works fine on windows, but does not disable the menu item on linux.
1702
// *and*, I no longer care.
1945
// *and*, I no longer care.
1703
1946
if ( GetConfig()->IsPlugin() )
1704
1947
GetConfig()->GetMenuBar()->Enable(idViewSnippets, false);
1708
// Just check to see if the semaphore has been posted.
1709
// Don't do a real wait, else the edit dialog will freeze
1710
while( wxSEMA_BUSY == waitSem.TryWait())
1711
{ waitSem.WaitTimeout(20);
1714
retcode = pdlg->GetReturnCode();
1716
// Release main apps closeWindow function
1717
GetConfig()->GetMainFrame()->Disconnect( wxEVT_CLOSE_WINDOW,
1718
(wxObjectEventFunction)(wxEventFunction)
1719
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1721
// Release parents closeWindow function
1722
pw->Disconnect( wxEVT_CLOSE_WINDOW,
1723
(wxObjectEventFunction)(wxEventFunction)
1724
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1951
// Just check to see if the semaphore has been posted.
1952
// Don't do a real wait, else the edit dialog will freeze
1953
while( wxSEMA_BUSY == waitSem.TryWait())
1954
{ waitSem.WaitTimeout(20);
1957
retcode = pdlg->GetReturnCode();
1959
// Release main apps closeWindow function
1960
GetConfig()->GetMainFrame()->Disconnect( wxEVT_CLOSE_WINDOW,
1961
(wxObjectEventFunction)(wxEventFunction)
1962
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1964
// Release parents closeWindow function
1965
pw->Disconnect( wxEVT_CLOSE_WINDOW,
1966
(wxObjectEventFunction)(wxEventFunction)
1967
(wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1726
1969
if ( GetConfig()->IsPlugin() )
1727
GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
1729
m_pPropertiesDialog = 0;
1733
// ----------------------------------------------------------------------------
1734
//-void CodeSnippetsTreeCtrl::OnIdle(wxIdleEvent& event)
1735
void CodeSnippetsTreeCtrl::OnIdle()
1736
// ----------------------------------------------------------------------------
1738
// check to see if an editor has been posted & finish.
1970
GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
1972
m_pPropertiesDialog = 0;
1976
// ----------------------------------------------------------------------------
1977
void CodeSnippetsTreeCtrl::SaveDataAndCloseEditorFrame()
1978
// ----------------------------------------------------------------------------
1980
// This routine is invoked from EditSnippetFrame::OnCloseWindow()
1981
// check to see if an editor has been posted & finish.
1740
1983
for (size_t i = 0; i < this->m_aDlgRetcodes.GetCount(); ++i )
1742
// if we have a return code, this editor is done
1743
if ( m_aDlgRetcodes.Item(i) == 0)
1746
// else an edit frame is done, save any changed data
1747
int retcode = m_aDlgRetcodes.Item(i);
1748
EditSnippetFrame* pdlg = (EditSnippetFrame*)m_aDlgPtrs.Item(i);
1749
pdlg->MakeModal(false);
1750
if (retcode == wxID_OK)
1752
// If XML text snippet, just save back to XML file
1753
if (pdlg->GetFileName().IsEmpty())
1755
SnippetItemData* pSnippetItemData = (SnippetItemData*)(GetSnippetsTreeCtrl()->GetItemData(pdlg->GetSnippetId()));
1756
pSnippetItemData->SetSnippet(pdlg->GetText());
1757
GetSnippetsTreeCtrl()->SetItemText(pdlg->GetSnippetId(), pdlg->GetName());
1759
else //This was an external file
1761
;// Modified external files already saved by dialog
1763
// if text item type changed to link, set corrected icon
1764
if ( pdlg->GetSnippetId().IsOk() )
1765
SetSnippetImage(pdlg->GetSnippetId());
1766
SetFileChanged(true);
1768
if (pdlg && (not m_bShutDown) )
1770
// If a pgm is started after CodeBlocks, it'll get the focus
1771
// when we destroy the editor frame *and* the frame was initiated by
1772
// a context menu item. So, here, we raise and focus CodeBlocks
1773
// if this is the last editor frame.
1774
if ( 1 == this->m_aDlgRetcodes.GetCount() )
1775
{ wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
1782
// retcode set by return frame
1783
//-retcode = pdlg->GetReturnCode();
1784
m_aDlgRetcodes.Item(i) = 0;
1785
m_aDlgPtrs.Item(i) = 0;
1788
// when all editors terminate, free array storage
1789
size_t editorsOpen = 0 ;
1790
size_t knt = m_aDlgPtrs.GetCount();
1985
// if we have a return code, this editor is done
1986
if ( m_aDlgRetcodes.Item(i) == 0)
1989
// else an edit frame is done, save any changed data
1990
int retcode = m_aDlgRetcodes.Item(i);
1991
EditSnippetFrame* pdlg = (EditSnippetFrame*)m_aDlgPtrs.Item(i);
1992
pdlg->MakeModal(false);
1993
if (retcode == wxID_OK)
1995
// If XML text snippet, just save back to XML file
1996
if (pdlg->GetFileName().IsEmpty())
1998
SnippetItemData* pSnippetItemData = (SnippetItemData*)(GetItemData(pdlg->GetSnippetId()));
1999
pSnippetItemData->SetSnippet(pdlg->GetText());
2000
SetItemText(pdlg->GetSnippetId(), pdlg->GetName());
2002
else //This was an external file
2004
;// Modified external files already saved by editor
2006
// if text item type changed to link, set corrected icon
2007
if ( pdlg->GetSnippetId().IsOk() )
2008
{ SetSnippetImage(pdlg->GetSnippetId());
2009
#if defined(LOGGING)
2010
LOGIT( _T("CodeSnippetsTreeCtrl::OnIdle() saved XML"));
2013
//-SetFileChanged(true);
2014
// Save the XML file
2015
SaveItemsToFile(GetConfig()->SettingsSnippetsXmlPath);
2018
if (pdlg && (not m_bShutDown) )
2020
// If a pgm is started after CodeBlocks, it'll get the focus
2021
// when we destroy this editor frame *and* the frame was initiated by
2022
// a context menu item. So, here, we raise and focus CodeBlocks
2023
// if this is the last editor frame.
2024
if ( 1 == this->m_aDlgRetcodes.GetCount() )
2025
{ wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
2032
// retcode set by return frame
2033
//-retcode = pdlg->GetReturnCode();
2034
m_aDlgRetcodes.Item(i) = 0;
2035
m_aDlgPtrs.Item(i) = 0;
2038
// when all editors terminate, free array storage
2039
size_t editorsOpen = 0 ;
2040
size_t knt = m_aDlgPtrs.GetCount();
1791
2041
for (size_t i = 0; i < knt; ++i )
1792
editorsOpen |= (size_t)m_aDlgPtrs.Item(i);
1793
if ( knt && (not editorsOpen) )
1794
{ m_aDlgRetcodes.Clear();
2042
editorsOpen += (size_t)m_aDlgPtrs.Item(i)?1:0;
2043
if ( knt && (not editorsOpen) )
2044
{ m_aDlgRetcodes.Clear();
2048
}//SaveAndCloseFrame
2049
// ----------------------------------------------------------------------------
2050
//-void CodeSnippetsTreeCtrl::OnIdle(wxIdleEvent& event)
2051
// This routine is invoked from codesnippets.cpp and codesnippetsapp.cpp
2052
void CodeSnippetsTreeCtrl::OnIdle()
2053
// ----------------------------------------------------------------------------
2055
// check to enable menu items and update StatusBar
1798
2057
if ( GetConfig()->IsPlugin() )
1799
GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
1801
// if search text is empty, show filename as root item
1802
// Edit the root node's title so that the user sees file name
1803
if ( GetConfig()->GetSnippetsSearchCtrl()
1804
&& GetConfig()->GetSnippetsSearchCtrl()->GetValue().IsEmpty() )
1805
{ wxString nameOnly;
1806
wxFileName::SplitPath( GetConfig()->SettingsSnippetsXmlFullPath, 0, &nameOnly, 0);
1807
// avoid excessive refresh
1808
wxString currentValue = GetItemText(GetSnippetsTreeCtrl()->GetRootItem());
1809
if (currentValue != nameOnly)
1810
GetSnippetsTreeCtrl()->SetItemText(GetSnippetsTreeCtrl()->GetRootItem(), wxString::Format(_("%s"), nameOnly.GetData()));
1813
////event.Skip(); this routine is called from another OnIdle which does the
1814
// event.Skip() itself.
1818
// ----------------------------------------------------------------------------
1819
void CodeSnippetsTreeCtrl::OnShutdown(wxCloseEvent& event)
1820
// ----------------------------------------------------------------------------
1822
//// // Here because our Connect() intercepted wxTheApp EVT_CLOSE
1823
//// // Blink this modeless dialog just like it was a modal dialog
1824
//// // wxWindow* oldTop = wxTheApp->GetTopWindow();
1825
//// // wxDialog* pdlg = this->m_pTopDialog;
1826
//// // wxTheApp->SetTopWindow( pdlg );
1827
//// // pdlg->RequestUserAttention();
1828
//// // wxTheApp->SetTopWindow(oldTop);
1829
//// // event.Veto();
1830
//// // //event.Skip(); causes app to crash
1832
//// // This bool prevents crash when CodeBlocks is shutdown;
1833
//// this->m_bShutDown = true;
1834
//// for (size_t i = 0; i < this->m_aDlgPtrs.GetCount(); ++i )
1836
//// wxDialog* pdlg = this->m_aDlgPtrs.Item(i);
1837
//// if (pdlg) pdlg->ProcessEvent(event);
1839
//// #if defined(BUILDING_PLUGIN)
1840
//// // Enable the plugin View menu item
1842
//// Manager::Get()->GetAppWindow()->GetMenuBar()->Enable(idViewSnippets, true);
1848
// ----------------------------------------------------------------------------
2058
GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
2060
// if search text is empty, show filename as root item
2061
// Edit the root node's title so that the user sees file name
2062
if ( GetConfig()->GetSnippetsSearchCtrl()
2063
&& GetConfig()->GetSnippetsSearchCtrl()->GetValue().IsEmpty() )
2064
{ wxString nameOnly;
2065
wxFileName::SplitPath( GetConfig()->SettingsSnippetsXmlPath, 0, &nameOnly, 0);
2066
// avoid excessive refresh
2067
wxString currentValue = GetItemText(GetRootItem());
2068
if (currentValue != nameOnly)
2069
SetItemText( GetRootItem(), wxString::Format(_("%s"), nameOnly.GetData()));
2072
////event.Skip(); this routine is called from another OnIdle which does the
2073
// event.Skip() itself.
2077
// ----------------------------------------------------------------------------
2078
void CodeSnippetsTreeCtrl::OnShutdown(wxCloseEvent& event)
2079
// ----------------------------------------------------------------------------
2081
event.Skip(); return;
2083
// ----------------------------------------------------------------------------
2084
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Select(CodeSnippetsEvent& event)
2085
// ----------------------------------------------------------------------------
2087
// CodeSnippetsEvent (usually issued from external ThreadSearch frame)
2088
// to focus/select a tree item via a snippet id
2092
wxString xmlString = event.GetSnippetString();
2093
#if defined(LOGGING)
2094
int snippetID = event.GetSnippetID();
2095
LOGIT( _T("CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Select[%d]String[%s]"), snippetID, xmlString.c_str());
2098
xmlString.Trim(false); // remove prefix whitespace
2099
// fetch type="category" or type="snippet"
2102
wxString idString(wxEmptyString);
2103
if ( xmlString.Contains(_T("type=\"category\"")))
2104
type = SnippetItemData::TYPE_CATEGORY;
2105
if ( xmlString.Contains(_T("type=\"snippet\"")))
2106
type = SnippetItemData::TYPE_SNIPPET;
2109
int s = xmlString.Find(_T(" ID=\""));
2110
if (wxNOT_FOUND == s) return;
2111
// parse out numeric id
2112
idString = xmlString.Mid( s+5 );
2113
idString = idString.Mid( 0 ,idString.Find('\"') );
2114
idString.ToLong(&id);
2118
wxTreeItemId rootID = GetRootItem();
2119
wxTreeItemId treeItemID = FindTreeItemBySnippetId( id, rootID );
2122
EnsureVisible( treeItemID );
2123
SelectItem( treeItemID );
2124
// Let edit event(doubleClick) raise and focus CodeSnippets window
2125
//-wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
2127
//-pWin->SetFocus();
2131
}//OnCodeSnippetsEvent_Select
2132
// ----------------------------------------------------------------------------
2133
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Edit(CodeSnippetsEvent& event)
2134
// ----------------------------------------------------------------------------
2136
// CodeSnippetsEvent (usually issued from external ThreadSearch frame)
2137
// to edit a tree item via a snippet id
2141
wxString xmlString = event.GetSnippetString();
2142
#if defined(LOGGING)
2143
LOGIT( _T("CodeSnippetsTreeCtrl::OnCodeSnippesEvent_Edit[%d][%s]"), event.GetSnippetID(), xmlString.c_str());
2146
xmlString.Trim(false); // remove prefix whitespace
2147
// fetch type="category" or type="snippet"
2150
wxString idString(wxEmptyString);
2151
if ( xmlString.Contains(_T("type=\"category\"")))
2152
type = SnippetItemData::TYPE_CATEGORY;
2153
if ( xmlString.Contains(_T("type=\"snippet\"")))
2154
type = SnippetItemData::TYPE_SNIPPET;
2157
int s = xmlString.Find(_T(" ID=\""));
2158
if (wxNOT_FOUND == s) return;
2159
// parse out numeric id
2160
idString = xmlString.Mid( s+5 );
2161
idString = idString.Mid( 0 ,idString.Find('\"') );
2162
idString.ToLong(&id);
2166
wxTreeItemId rootID = GetRootItem();
2167
wxTreeItemId treeItemID = FindTreeItemBySnippetId( id, rootID );
2170
EnsureVisible( treeItemID );
2171
SelectItem( treeItemID );
2172
if ( type == SnippetItemData::TYPE_CATEGORY )
2174
wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
2178
if ( type == SnippetItemData::TYPE_SNIPPET )
2180
SetAssociatedItemID( treeItemID );
2181
wxCommandEvent editEvt( wxEVT_COMMAND_MENU_SELECTED , idMnuEditSnippet);
2182
#if wxCHECK_VERSION(2, 9, 0)
2183
GetConfig()->GetSnippetsWindow()->GetEventHandler()->AddPendingEvent(editEvt);
2185
GetConfig()->GetSnippetsWindow()->AddPendingEvent( editEvt);
2191
}//OnCodeSnippetsEvent_Edit
2192
// ----------------------------------------------------------------------------
2193
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_GetFileLinks(CodeSnippetsEvent& event)
2194
// ----------------------------------------------------------------------------
2196
// CodeSnippetsEvent usually issued from external frame
2197
// to fill file map with file link names and snippet ids
2201
#if defined(LOGGING)
2202
LOGIT( _T("CodeSnippetsTreeCtrl::OnCodeSnippesEvent_GetFileLinks") );
2205
FileLinksMapArray& fileIDMap = GetConfig()->GetFileLinksMapArray();
2208
FillFileLinksMapArray( GetRootItem(), fileIDMap );
2211
}//OnCodeSnippetsEvent_GetFileLinks
2212
// ----------------------------------------------------------------------------
2213
wxTreeItemId CodeSnippetsTreeCtrl::ResetSnippetsIDs(const wxTreeItemId& startNode)
2214
// ----------------------------------------------------------------------------
2216
// Re-number Snippet Id's in Tree. Used for save and data inserts
2218
static wxTreeItemId dummyItem = (void*)(0);
2219
wxTreeItemIdValue cookie;
2220
wxTreeItemId item = GetFirstChild(startNode, cookie );
2222
// Loop through all items and reset their ID number
2225
if ( SnippetItemData* itemData = (SnippetItemData*)(GetItemData(item)))
2227
bool ignoreThisType = false;
2229
switch (itemData->GetType())
2231
case SnippetItemData::TYPE_ROOT:
2232
ignoreThisType = true;
2235
case SnippetItemData::TYPE_SNIPPET:
2238
case SnippetItemData::TYPE_CATEGORY:
2242
if (!ignoreThisType)
2244
//-wxString label = GetItemText(item);
2245
itemData->SetID( itemData->GetNewID() );
2248
if(ItemHasChildren(item))
2250
wxTreeItemId search = ResetSnippetsIDs( item );
2254
item = GetNextChild(startNode, cookie);
2258
// Return dummy item if search string was not found
2261
// ----------------------------------------------------------------------------
2262
wxTreeItemId CodeSnippetsTreeCtrl::FillFileLinksMapArray(const wxTreeItemId& startNode, FileLinksMapArray& fileLinksMapArray)
2263
// ----------------------------------------------------------------------------
2265
// Place Snippet item file links into array along with their snippet ID's
2267
static wxTreeItemId dummyItem = (void*)(0);
2268
wxTreeItemIdValue cookie;
2270
wxTreeItemId treeItem = GetFirstChild(startNode, cookie );
2272
// Loop through all items record their file links
2273
while(treeItem.IsOk())
2275
if ( SnippetItemData* snippetData = (SnippetItemData*)(GetItemData(treeItem)))
2277
bool ignoreThisType = false;
2279
switch (snippetData->GetType())
2281
case SnippetItemData::TYPE_ROOT:
2282
ignoreThisType = true;
2285
case SnippetItemData::TYPE_SNIPPET:
2288
case SnippetItemData::TYPE_CATEGORY:
2289
ignoreThisType = true;
2293
if (!ignoreThisType)
2295
wxString fileName = wxEmptyString;
2296
if ( wxEmptyString not_eq (fileName = snippetData->GetSnippetFileLink() ))
2298
long itemId = snippetData->GetID();
2299
fileLinksMapArray[fileName] = itemId;
2303
if(ItemHasChildren(treeItem))
2305
wxTreeItemId search = FillFileLinksMapArray( treeItem, fileLinksMapArray );
2309
treeItem = GetNextChild(startNode, cookie);
2313
// Return dummy item if search string was not found
2316
// ----------------------------------------------------------------------------
2317
void CodeSnippetsTreeCtrl::CreateDirLevels(const wxString& pathNameIn)
2318
// ----------------------------------------------------------------------------
2320
// FileImport Traverser will create any missing directories
2321
FileImportTraverser fit(_T("dummy"), pathNameIn);