~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to src/plugins/contrib/codesnippets/codesnippetstreectrl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
        This file is part of Code Snippets, a plugin for Code::Blocks
3
3
        Copyright (C) 2006 Arto Jonsson
4
 
        Copyright (C) 2007 Pecan Heber
 
4
        Copyright (C) 2007 Pecan Heber
5
5
 
6
6
        This program is free software; you can redistribute it and/or
7
7
        modify it under the terms of the GNU General Public License
17
17
        along with this program; if not, write to the Free Software
18
18
        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
19
*/
20
 
// RCS-ID: $Id: codesnippetstreectrl.cpp 112 2008-01-07 17:03:31Z Pecan $
21
 
 
22
 
#ifdef WX_PRECOMP
23
 
    #include "wx_pch.h"
24
 
#else
25
 
    #include <wx/msgdlg.h>
26
 
#endif
27
 
    #include <wx/file.h>
28
 
    #include <wx/filename.h>
29
 
    #include <wx/dataobj.h>
30
 
    #include <wx/dnd.h>
31
 
    #include <wx/filename.h>
32
 
    #include "wx/mimetype.h"
33
 
 
34
 
#if defined(BUILDING_PLUGIN)
35
 
    #include "sdk.h"
 
20
// RCS-ID: $Id: codesnippetstreectrl.cpp 113 2008-01-14 18:31:17Z Pecan $
 
21
 
 
22
#ifdef WX_PRECOMP
 
23
    #include "wx_pch.h"
 
24
#else
 
25
    #include <wx/msgdlg.h>
 
26
#endif
 
27
    #include <wx/file.h>
 
28
    #include <wx/filename.h>
 
29
    #include <wx/dataobj.h>
 
30
    #include <wx/dnd.h>
 
31
    #include <wx/filename.h>
 
32
    #include "wx/mimetype.h"
 
33
 
 
34
//-#if defined(BUILDING_PLUGIN)
 
35
    #include "sdk.h"
36
36
    #ifndef CB_PRECOMP
37
37
        #include "manager.h"
38
38
        #include "logmanager.h"
39
39
        #include "globals.h"
40
 
    #endif
41
 
#else
42
 
#endif
 
40
    #endif
 
41
//-#else
 
42
//-#endif
43
43
 
44
44
#include <tinyxml/tinyxml.h>
45
45
#include "snippetitemdata.h"
46
 
#include "codesnippetstreectrl.h"
47
 
#include "snippetsconfig.h"
48
 
#include "messagebox.h"
49
 
#include "menuidentifiers.h"
50
 
#include "editsnippetframe.h"
 
46
#include "codesnippetstreectrl.h"
 
47
#include "codesnippetswindow.h"
 
48
#include "snippetsconfig.h"
 
49
#include "GenericMessageBox.h"
 
50
#include "menuidentifiers.h"
 
51
#include "editsnippetframe.h"
 
52
#include "codesnippetsevent.h"
 
53
#include "snippetsconfig.h"
 
54
#include "dragscrollevent.h"
 
55
#include "FileImport.h"
 
56
#include "csutils.h"
 
57
#include "version.h"
 
58
 
51
59
#if defined(__WXGTK__)
52
 
    #include "wx/gtk/win_gtk.h"
53
 
    #include <gdk/gdkx.h>
54
 
#endif
55
 
 
56
 
IMPLEMENT_DYNAMIC_CLASS(CodeSnippetsTreeCtrl, wxTreeCtrl)
57
 
 
58
 
BEGIN_EVENT_TABLE(CodeSnippetsTreeCtrl, wxTreeCtrl)
59
 
        EVT_TREE_BEGIN_DRAG(idSnippetsTreeCtrl, CodeSnippetsTreeCtrl::OnBeginTreeItemDrag)
60
 
        EVT_TREE_END_DRAG(idSnippetsTreeCtrl,   CodeSnippetsTreeCtrl::OnEndTreeItemDrag)
61
 
        EVT_LEAVE_WINDOW(                       CodeSnippetsTreeCtrl::OnLeaveWindow)
62
 
        EVT_ENTER_WINDOW(                       CodeSnippetsTreeCtrl::OnEnterWindow)
63
 
        EVT_MOTION(                             CodeSnippetsTreeCtrl::OnMouseEvent)
64
 
        EVT_TREE_SEL_CHANGED(idSnippetsTreeCtrl,CodeSnippetsTreeCtrl::OnItemSelected)
65
 
        EVT_TREE_ITEM_RIGHT_CLICK(idSnippetsTreeCtrl, CodeSnippetsTreeCtrl::OnItemRightSelected)
66
 
        //-EVT_IDLE(                               CodeSnippetsTreeCtrl::OnIdle)
67
 
        //- EVT_IDLE replaced by call from plugin|appframe OnIdle routine
68
 
END_EVENT_TABLE()
69
 
 
70
 
// ----------------------------------------------------------------------------
71
 
CodeSnippetsTreeCtrl::CodeSnippetsTreeCtrl(wxWindow *parent, const wxWindowID id,
 
60
    // hack to avoid name-conflict between wxWidgets GSocket and the one defined
 
61
    // in newer glib-headers
 
62
    #define GSocket GLibSocket
 
63
    #include <gdk/gdkx.h>
 
64
    #undef GSocket
 
65
    #include "wx/gtk/win_gtk.h"
 
66
#endif
 
67
 
 
68
IMPLEMENT_DYNAMIC_CLASS(CodeSnippetsTreeCtrl, wxTreeCtrl)
 
69
 
 
70
BEGIN_EVENT_TABLE(CodeSnippetsTreeCtrl, wxTreeCtrl)
 
71
        EVT_TREE_BEGIN_DRAG(idSnippetsTreeCtrl, CodeSnippetsTreeCtrl::OnBeginTreeItemDrag)
 
72
        EVT_TREE_END_DRAG(idSnippetsTreeCtrl,   CodeSnippetsTreeCtrl::OnEndTreeItemDrag)
 
73
        EVT_LEAVE_WINDOW(                       CodeSnippetsTreeCtrl::OnLeaveWindow)
 
74
        EVT_ENTER_WINDOW(                       CodeSnippetsTreeCtrl::OnEnterWindow)
 
75
        EVT_MOTION(                             CodeSnippetsTreeCtrl::OnMouseMotionEvent)
 
76
        EVT_MOUSEWHEEL(                         CodeSnippetsTreeCtrl::OnMouseWheelEvent)
 
77
        EVT_TREE_SEL_CHANGED(idSnippetsTreeCtrl,CodeSnippetsTreeCtrl::OnItemSelected)
 
78
        EVT_TREE_ITEM_RIGHT_CLICK(idSnippetsTreeCtrl, CodeSnippetsTreeCtrl::OnItemRightSelected)
 
79
        //-EVT_IDLE(                               CodeSnippetsTreeCtrl::OnIdle)
 
80
        //- EVT_IDLE replaced by call from plugin|appframe OnIdle routine
 
81
    // --
 
82
    EVT_CODESNIPPETS_SELECT(wxID_ANY,    CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Select)
 
83
    EVT_CODESNIPPETS_EDIT  (wxID_ANY,    CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Edit)
 
84
    EVT_CODESNIPPETS_GETFILELINKS(wxID_ANY,CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_GetFileLinks)
 
85
 
 
86
END_EVENT_TABLE()
 
87
 
 
88
// ----------------------------------------------------------------------------
 
89
CodeSnippetsTreeCtrl::CodeSnippetsTreeCtrl(wxWindow *parent, const wxWindowID id,
72
90
                                const wxPoint& pos, const wxSize& size, long style)
73
 
// ----------------------------------------------------------------------------
74
 
        //-: wxTreeCtrl(parent, id, pos, size, style)
 
91
// ----------------------------------------------------------------------------
 
92
        //-: wxTreeCtrl(parent, id, pos, size, style)
75
93
        : wxTreeCtrl(parent, id, pos, size, style, wxDefaultValidator, wxT("csTreeCtrl"))
76
 
{
 
94
{
77
95
    m_fileChanged = false;
78
 
    m_bMouseLeftWindow = false;
79
 
    m_pPropertiesDialog = 0;
80
 
    m_bShutDown = false;
81
 
    m_mimeDatabase = 0;
 
96
    m_bMouseLeftWindow = false;
 
97
    m_pPropertiesDialog = 0;
 
98
    m_bShutDown = false;
 
99
    m_mimeDatabase = 0;
 
100
    m_pEvtTreeCtrlBeginDrag = 0;
 
101
    m_LastXmlModifiedTime = time_t(0);            //2009/03/15
82
102
 
83
103
    m_pSnippetsTreeCtrl = this;
84
104
    GetConfig()->SetSnippetsTreeCtrl(this);
85
 
 
86
105
}
87
 
 
88
 
// ----------------------------------------------------------------------------
 
106
// ----------------------------------------------------------------------------
89
107
CodeSnippetsTreeCtrl::~CodeSnippetsTreeCtrl()
90
 
// ----------------------------------------------------------------------------
91
 
{
92
 
    //dtor
93
 
    // Tell all that TreeCtrl is gone;
94
 
    GetConfig()->SetSnippetsTreeCtrl(0);
95
 
 
96
 
}
97
 
// ----------------------------------------------------------------------------
98
 
bool CodeSnippetsTreeCtrl::IsFileSnippet (wxTreeItemId treeItemId  )
99
 
// ----------------------------------------------------------------------------
100
 
{
101
 
    wxTreeItemId itemId = treeItemId;
102
 
    if ( itemId == (void*)0) itemId = GetSelection();
103
 
    if (not itemId.IsOk()) return false;
104
 
    if (not IsSnippet(itemId) ) return false;
105
 
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
106
 
    fileName = fileName.BeforeFirst('\n');
107
 
    // substitute $macros with actual text
108
 
    #if defined(BUILDING_PLUGIN)
109
 
        Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
110
 
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
111
 
    #endif
112
 
    if ( not ::wxFileExists( fileName) ) return false;
113
 
    return true;
114
 
}
115
 
// ----------------------------------------------------------------------------
116
 
bool CodeSnippetsTreeCtrl::IsFileLinkSnippet (wxTreeItemId treeItemId  )
117
 
// ----------------------------------------------------------------------------
118
 
{
119
 
    wxTreeItemId itemId = treeItemId;
120
 
    if ( itemId == (void*)0) itemId = GetSelection();
121
 
    if (not itemId.IsOk()) return false;
122
 
    if (not IsSnippet(itemId) ) return false;
123
 
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
124
 
    fileName = fileName.BeforeFirst('\n');
125
 
    // substitute $macros with actual text
126
 
    #if defined(BUILDING_PLUGIN)
127
 
        Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
128
 
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
129
 
    #endif
130
 
    if (fileName.Length() > 128)
131
 
    {   // if text is > 128 characters, not a filelink.
132
 
        return false;
133
 
    }
134
 
    if ( not ::wxFileExists( fileName) ) return false;
135
 
    return true;
136
 
 
137
 
}//IsFileLinkSnippet
138
 
// ----------------------------------------------------------------------------
139
 
wxString CodeSnippetsTreeCtrl::GetFileLinkExt (wxTreeItemId treeItemId  )
140
 
// ----------------------------------------------------------------------------
141
 
{
142
 
    if ( not IsFileLinkSnippet(treeItemId) ) return wxT("");
143
 
    wxTreeItemId itemId = treeItemId;
144
 
    if ( itemId == (void*)0) itemId = GetSelection();
145
 
    if (not itemId.IsOk()) return wxT("");
146
 
    if (not IsSnippet(itemId) ) return wxT("");
147
 
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
148
 
    fileName = fileName.BeforeFirst('\n');
149
 
    // substitute $macros with actual text
150
 
    #if defined(BUILDING_PLUGIN)
151
 
        Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
152
 
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
153
 
    #endif
154
 
    if ( not ::wxFileExists( fileName) ) return wxT("");
155
 
    wxFileName filename(fileName);
156
 
    return filename.GetExt();
157
 
}
158
 
// ----------------------------------------------------------------------------
159
 
void CodeSnippetsTreeCtrl::OnItemSelectChanging(wxTreeEvent& event)
160
 
// ----------------------------------------------------------------------------
161
 
{
162
 
    // UNUSED
163
 
    //-if (m_pTopDialog) event.Veto();
164
 
    return;
165
 
}
166
 
// ----------------------------------------------------------------------------
167
 
void CodeSnippetsTreeCtrl::OnItemSelected(wxTreeEvent& event)
168
 
// ----------------------------------------------------------------------------
169
 
{                                                           //(pecan 2006/9/12)
170
 
 
171
 
    //CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
172
 
    wxTreeItemId itemId = event.GetItem();
173
 
 
174
 
    //-SetStatusText(wxEmptyString);
175
 
 
176
 
    // Get the item associated with the event
177
 
        if (const SnippetItemData* eventItem =
178
 
        (SnippetItemData*)GetItemData(event.GetItem()))
179
 
        {
180
 
        wxString itemDescription;
181
 
                // Check the type of the item and add the menu items
182
 
                switch (eventItem->GetType())
183
 
                {
184
 
                        case SnippetItemData::TYPE_ROOT:
185
 
                        break;
186
 
 
187
 
                        case SnippetItemData::TYPE_CATEGORY:
188
 
                        break;
189
 
 
190
 
                        case SnippetItemData::TYPE_SNIPPET:
191
 
                        //-SetStatusText( GetSnippetDescription(itemId) );
192
 
                        break;
193
 
                }
194
 
 
195
 
                // Save the item ID for later use
196
 
                m_MnuAssociatedItemID = eventItem->GetId();
197
 
 
198
 
        }
199
 
 
200
 
}
201
 
// ----------------------------------------------------------------------------
202
 
void CodeSnippetsTreeCtrl::OnItemRightSelected(wxTreeEvent& event)
203
 
// ----------------------------------------------------------------------------
204
 
{
205
 
    // on wx2.8.3, Right click does not select the item.
206
 
    // The selection is still on the previous item.
207
 
    // So we'll select it ourself.
208
 
 
209
 
    SelectItem(event.GetItem());                                                         //(pecan 2006/9/12)
210
 
}
211
 
// ----------------------------------------------------------------------------
 
108
// ----------------------------------------------------------------------------
 
109
{
 
110
    //dtor
 
111
    // Tell all that TreeCtrl is gone;
 
112
    GetConfig()->SetSnippetsTreeCtrl(0);
 
113
 
 
114
}
 
115
// ----------------------------------------------------------------------------
 
116
bool CodeSnippetsTreeCtrl::IsFileSnippet (wxTreeItemId treeItemId  )
 
117
// ----------------------------------------------------------------------------
 
118
{
 
119
    wxTreeItemId itemId = treeItemId;
 
120
    if ( itemId == (void*)0) itemId = GetSelection();
 
121
    if (not itemId.IsOk()) return false;
 
122
    if (not IsSnippet(itemId) ) return false;
 
123
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
 
124
    fileName = fileName.BeforeFirst('\n');
 
125
    // substitute $macros with actual text
 
126
    //-#if defined(BUILDING_PLUGIN)
 
127
        static const wxString delim(_T("$%["));
 
128
        if( fileName.find_first_of(delim) != wxString::npos )
 
129
            Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
 
130
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
 
131
    //-#endif
 
132
 
 
133
    if ( not ::wxFileExists( fileName) ) return false;
 
134
    return true;
 
135
}
 
136
// ----------------------------------------------------------------------------
 
137
bool CodeSnippetsTreeCtrl::IsFileLinkSnippet (wxTreeItemId treeItemId  )
 
138
// ----------------------------------------------------------------------------
 
139
{
 
140
    wxTreeItemId itemId = treeItemId;
 
141
    if ( itemId == (void*)0) itemId = GetSelection();
 
142
    if (not itemId.IsOk()) return false;
 
143
    if (not IsSnippet(itemId) ) return false;
 
144
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
 
145
    fileName = fileName.BeforeFirst('\n');
 
146
    // substitute $macros with actual text
 
147
    //-#if defined(BUILDING_PLUGIN)
 
148
        static const wxString delim(_T("$%["));
 
149
        if( fileName.find_first_of(delim) != wxString::npos )
 
150
            Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
 
151
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
 
152
    //-#endif
 
153
    if (fileName.Length() > 128)
 
154
    {   // if text is > 128 characters, not a filelink.
 
155
        return false;
 
156
    }
 
157
    if ( not ::wxFileExists( fileName) ) return false;
 
158
    return true;
 
159
 
 
160
}//IsFileLinkSnippet
 
161
// ----------------------------------------------------------------------------
 
162
wxString CodeSnippetsTreeCtrl::GetFileLinkExt (wxTreeItemId treeItemId  )
 
163
// ----------------------------------------------------------------------------
 
164
{
 
165
    //return filename extension
 
166
 
 
167
    if ( not IsFileLinkSnippet(treeItemId) ) return wxT("");
 
168
    wxTreeItemId itemId = treeItemId;
 
169
    if ( itemId == (void*)0) itemId = GetSelection();
 
170
    if (not itemId.IsOk()) return wxT("");
 
171
    if (not IsSnippet(itemId) ) return wxT("");
 
172
    wxString fileName = GetSnippet(itemId).BeforeFirst('\r');
 
173
    fileName = fileName.BeforeFirst('\n');
 
174
    // substitute $macros with actual text
 
175
    //-#if defined(BUILDING_PLUGIN)
 
176
        static const wxString delim(_T("$%["));
 
177
        if( fileName.find_first_of(delim) != wxString::npos )
 
178
            Manager::Get()->GetMacrosManager()->ReplaceMacros(fileName);
 
179
        //-LOGIT( _T("$macros name[%s]"),fileName.c_str() );
 
180
    //-#endif
 
181
    if ( not ::wxFileExists( fileName) ) return wxT("");
 
182
    wxFileName filename(fileName);
 
183
    return filename.GetExt();
 
184
}
 
185
// ----------------------------------------------------------------------------
 
186
void CodeSnippetsTreeCtrl::OnItemSelectChanging(wxTreeEvent& event)
 
187
// ----------------------------------------------------------------------------
 
188
{
 
189
    // UNUSED
 
190
    //-if (m_pTopDialog) event.Veto();
 
191
    return;
 
192
}
 
193
// ----------------------------------------------------------------------------
 
194
void CodeSnippetsTreeCtrl::OnItemSelected(wxTreeEvent& event)
 
195
// ----------------------------------------------------------------------------
 
196
{                                                           //(pecan 2006/9/12)
 
197
    // User selected a tree item. Memorize the selection for
 
198
    // other routines.
 
199
 
 
200
    //CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
 
201
    wxTreeItemId itemId = event.GetItem();
 
202
 
 
203
    //-SetStatusText(wxEmptyString);
 
204
 
 
205
    // Get the item associated with the event
 
206
        if (const SnippetItemData* eventItem =
 
207
        (SnippetItemData*)GetItemData(event.GetItem()))
 
208
        {
 
209
        wxString itemDescription;
 
210
                // Check the type of the item and add the menu items
 
211
                switch (eventItem->GetType())
 
212
                {
 
213
                        case SnippetItemData::TYPE_ROOT:
 
214
                        break;
 
215
 
 
216
                        case SnippetItemData::TYPE_CATEGORY:
 
217
                        break;
 
218
 
 
219
                        case SnippetItemData::TYPE_SNIPPET:
 
220
                        //-SetStatusText( GetSnippetDescription(itemId) );
 
221
                        break;
 
222
                }
 
223
 
 
224
                // Save the item ID for later use
 
225
                m_MnuAssociatedItemID = eventItem->GetId();
 
226
 
 
227
        }
 
228
 
 
229
}
 
230
// ----------------------------------------------------------------------------
 
231
void CodeSnippetsTreeCtrl::OnItemRightSelected(wxTreeEvent& event)
 
232
// ----------------------------------------------------------------------------
 
233
{
 
234
    // on wx2.8.3, Right click does not select the item.
 
235
    // The selection is still on the previous item.
 
236
    // So we'll select it ourself.
 
237
 
 
238
    SelectItem(event.GetItem());                                                         //(pecan 2006/9/12)
 
239
}
 
240
// ----------------------------------------------------------------------------
212
241
int CodeSnippetsTreeCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
213
 
// ----------------------------------------------------------------------------
 
242
// ----------------------------------------------------------------------------
214
243
{
215
244
        // Get the items' data first
216
245
        const SnippetItemData* data1 = (SnippetItemData*)(GetItemData(item1));
269
298
                return 0;
270
299
        }
271
300
}
272
 
// ----------------------------------------------------------------------------
273
 
wxTreeItemId CodeSnippetsTreeCtrl::FindItemByLabel(const wxString& searchTerms, const wxTreeItemId& node, int requestType)
274
 
// ----------------------------------------------------------------------------
275
 
{
276
 
        wxTreeItemIdValue cookie;
277
 
        wxTreeItemId item = GetSnippetsTreeCtrl()->GetFirstChild(node, cookie );
278
 
 
279
 
        // Loop through all items
280
 
        while(item.IsOk())
281
 
        {
282
 
                if (const SnippetItemData* itemData = (SnippetItemData*)(GetSnippetsTreeCtrl()->GetItemData(item)))
283
 
                {
284
 
                        bool ignoreThisType = false;
285
 
 
286
 
                        switch (itemData->GetType())
287
 
                        {
288
 
                                case SnippetItemData::TYPE_ROOT:
289
 
                                        ignoreThisType = true;
290
 
                                break;
291
 
 
292
 
                                case SnippetItemData::TYPE_SNIPPET:
293
 
                                        if (requestType == CodeSnippetsConfig::SCOPE_CATEGORIES)
294
 
                                        {
295
 
                                                ignoreThisType = true;
296
 
                                        }
297
 
                                break;
298
 
 
299
 
                                case SnippetItemData::TYPE_CATEGORY:
300
 
                                        if (requestType == CodeSnippetsConfig::SCOPE_SNIPPETS)
301
 
                                        {
302
 
                                                ignoreThisType = true;
303
 
                                        }
304
 
                                break;
305
 
                        }
306
 
 
307
 
                        if (!ignoreThisType)
308
 
                        {
309
 
                                wxString label = GetSnippetsTreeCtrl()->GetItemText(item);
310
 
 
311
 
                                if(0 == label.Cmp(searchTerms))
312
 
                                {
313
 
                                        return item;
314
 
                                }
315
 
                        }
316
 
 
317
 
                        if(GetSnippetsTreeCtrl()->ItemHasChildren(item))
318
 
                        {
319
 
                                wxTreeItemId search = FindItemByLabel(searchTerms, item, requestType);
320
 
                                if(search.IsOk())
321
 
                                {
322
 
                                        return search;
323
 
                                }
324
 
                        }
325
 
                        item = GetSnippetsTreeCtrl()->GetNextChild(node, cookie);
326
 
                }
327
 
        }
328
 
 
329
 
   // Return dummy item if search string was not found
330
 
   wxTreeItemId dummyItem = (void*)(0);
331
 
   return dummyItem;
332
 
}
333
 
// ----------------------------------------------------------------------------
334
 
wxTreeItemId CodeSnippetsTreeCtrl::FindItemById(const wxTreeItemId& itemToFind, const wxTreeItemId& startNode, int itemToFindType)
335
 
// ----------------------------------------------------------------------------
336
 
{
337
 
        wxTreeItemIdValue cookie;
338
 
        wxTreeItemId item = GetSnippetsTreeCtrl()->GetFirstChild(startNode, cookie );
339
 
 
340
 
        // Loop through all items
341
 
        while(item.IsOk())
342
 
        {
343
 
                if (const SnippetItemData* itemData = (SnippetItemData*)(GetSnippetsTreeCtrl()->GetItemData(item)))
344
 
                {
345
 
                        bool ignoreThisType = false;
346
 
 
347
 
                        switch (itemData->GetType())
348
 
                        {
349
 
                                case SnippetItemData::TYPE_ROOT:
350
 
                                        ignoreThisType = true;
351
 
                                break;
352
 
 
353
 
                                case SnippetItemData::TYPE_SNIPPET:
354
 
                                        if (itemToFindType == CodeSnippetsConfig::SCOPE_CATEGORIES)
355
 
                                        {
356
 
                                                ignoreThisType = true;
357
 
                                        }
358
 
                                break;
359
 
 
360
 
                                case SnippetItemData::TYPE_CATEGORY:
361
 
                                        if (itemToFindType == CodeSnippetsConfig::SCOPE_SNIPPETS)
362
 
                                        {
363
 
                                                ignoreThisType = true;
364
 
                                        }
365
 
                                break;
366
 
                        }
367
 
 
368
 
                        if (!ignoreThisType)
369
 
                        {
370
 
                                wxString label = GetSnippetsTreeCtrl()->GetItemText(item);
371
 
 
372
 
                                if( itemToFind == item)
373
 
                                {
374
 
                                        return item;
375
 
                                }
376
 
                        }
377
 
 
378
 
                        if(GetSnippetsTreeCtrl()->ItemHasChildren(item))
379
 
                        {
380
 
                                wxTreeItemId search = FindItemById(itemToFind, item, itemToFindType);
381
 
                                if(search.IsOk())
382
 
                                {
383
 
                                        return search;
384
 
                                }
385
 
                        }
386
 
                        item = GetSnippetsTreeCtrl()->GetNextChild(startNode, cookie);
387
 
                }
388
 
        }
389
 
 
390
 
   // Return dummy item if search string was not found
391
 
   wxTreeItemId dummyItem = (void*)(0);
392
 
   return dummyItem;
393
 
}
394
 
 
395
 
// ----------------------------------------------------------------------------
 
301
// ----------------------------------------------------------------------------
 
302
wxTreeItemId CodeSnippetsTreeCtrl::FindTreeItemByLabel(const wxString& searchTerms, const wxTreeItemId& node, int requestType)
 
303
// ----------------------------------------------------------------------------
 
304
{
 
305
 
 
306
    // Return a tree item id matching string
 
307
 
 
308
        wxTreeItemIdValue cookie;
 
309
        wxTreeItemId item = GetFirstChild(node, cookie );
 
310
 
 
311
        // Loop through all items
 
312
        while(item.IsOk())
 
313
        {
 
314
                if (const SnippetItemData* itemData = (SnippetItemData*)(GetItemData(item)))
 
315
                {
 
316
                        bool ignoreThisType = false;
 
317
 
 
318
                        switch (itemData->GetType())
 
319
                        {
 
320
                                case SnippetItemData::TYPE_ROOT:
 
321
                                        ignoreThisType = true;
 
322
                                break;
 
323
 
 
324
                                case SnippetItemData::TYPE_SNIPPET:
 
325
                                        if (requestType == CodeSnippetsConfig::SCOPE_CATEGORIES)
 
326
                                        {
 
327
                                                ignoreThisType = true;
 
328
                                        }
 
329
                                break;
 
330
 
 
331
                                case SnippetItemData::TYPE_CATEGORY:
 
332
                                        if (requestType == CodeSnippetsConfig::SCOPE_SNIPPETS)
 
333
                                        {
 
334
                                                ignoreThisType = true;
 
335
                                        }
 
336
                                break;
 
337
                        }
 
338
 
 
339
                        if (!ignoreThisType)
 
340
                        {
 
341
                                wxString label = GetItemText(item);
 
342
 
 
343
                                if(0 == label.Cmp(searchTerms))
 
344
                                {
 
345
                                        return item;
 
346
                                }
 
347
                        }
 
348
 
 
349
                        if(ItemHasChildren(item))
 
350
                        {
 
351
                                wxTreeItemId search = FindTreeItemByLabel(searchTerms, item, requestType);
 
352
                                if(search.IsOk())
 
353
                                {
 
354
                                        return search;
 
355
                                }
 
356
                        }
 
357
                        item = GetNextChild(node, cookie);
 
358
                }
 
359
        }
 
360
 
 
361
   // Return dummy item if search string was not found
 
362
   wxTreeItemId dummyItem = (void*)(0);
 
363
   return dummyItem;
 
364
}
 
365
// ----------------------------------------------------------------------------
 
366
wxTreeItemId CodeSnippetsTreeCtrl::FindTreeItemByTreeId(const wxTreeItemId& itemToFind, const wxTreeItemId& startNode, int itemToFindType)
 
367
// ----------------------------------------------------------------------------
 
368
{
 
369
    // Return a tree item matching item reference
 
370
 
 
371
        wxTreeItemIdValue cookie;
 
372
        wxTreeItemId item = GetFirstChild(startNode, cookie );
 
373
 
 
374
        // Loop through all items
 
375
        while(item.IsOk())
 
376
        {
 
377
                if (const SnippetItemData* itemData = (SnippetItemData*)(GetItemData(item)))
 
378
                {
 
379
                        bool ignoreThisType = false;
 
380
 
 
381
                        switch (itemData->GetType())
 
382
                        {
 
383
                                case SnippetItemData::TYPE_ROOT:
 
384
                                        ignoreThisType = true;
 
385
                                break;
 
386
 
 
387
                                case SnippetItemData::TYPE_SNIPPET:
 
388
                                        if (itemToFindType == CodeSnippetsConfig::SCOPE_CATEGORIES)
 
389
                                        {
 
390
                                                ignoreThisType = true;
 
391
                                        }
 
392
                                break;
 
393
 
 
394
                                case SnippetItemData::TYPE_CATEGORY:
 
395
                                        if (itemToFindType == CodeSnippetsConfig::SCOPE_SNIPPETS)
 
396
                                        {
 
397
                                                ignoreThisType = true;
 
398
                                        }
 
399
                                break;
 
400
                        }
 
401
 
 
402
                        if (!ignoreThisType)
 
403
                        {
 
404
                                wxString label = GetItemText(item);
 
405
 
 
406
                                if( itemToFind == item)
 
407
                                {
 
408
                                        return item;
 
409
                                }
 
410
                        }
 
411
 
 
412
                        if(ItemHasChildren(item))
 
413
                        {
 
414
                                wxTreeItemId search = FindTreeItemByTreeId(itemToFind, item, itemToFindType);
 
415
                                if(search.IsOk())
 
416
                                {
 
417
                                        return search;
 
418
                                }
 
419
                        }
 
420
                        item = GetNextChild(startNode, cookie);
 
421
                }
 
422
        }
 
423
 
 
424
   // Return dummy item if search string was not found
 
425
   wxTreeItemId dummyItem = (void*)(0);
 
426
   return dummyItem;
 
427
}
 
428
// ----------------------------------------------------------------------------
 
429
wxTreeItemId CodeSnippetsTreeCtrl::FindTreeItemBySnippetId(const SnippetItemID& IDToFind, const wxTreeItemId& startNode)
 
430
// ----------------------------------------------------------------------------
 
431
{
 
432
    // Return a tree item matching item reference
 
433
 
 
434
    static wxTreeItemId dummyItem = (void*)(0);
 
435
        wxTreeItemIdValue cookie;
 
436
        wxTreeItemId item = GetFirstChild(startNode, cookie );
 
437
 
 
438
        // Loop through all items
 
439
        while(item.IsOk())
 
440
        {
 
441
                if (const SnippetItemData* itemData = (SnippetItemData*)(GetItemData(item)))
 
442
                {
 
443
                        bool ignoreThisItem = false;
 
444
 
 
445
            #if defined(LOGGING)
 
446
            //LOGIT( _T("itemToFind[%d] ItemID[%d],Tree[%s],Snippet[%s]"),
 
447
            //    IDToFind, itemData->GetID(), GetItemText(item).c_str(), itemData->GetSnippet().Left(16).c_str());
 
448
            #endif
 
449
 
 
450
                        switch (itemData->GetType())
 
451
                        {
 
452
                                case SnippetItemData::TYPE_ROOT:
 
453
                                        ignoreThisItem = true;
 
454
                                break;
 
455
 
 
456
                                case SnippetItemData::TYPE_SNIPPET:
 
457
                                        if ( IDToFind not_eq itemData->GetID() )
 
458
                                        {
 
459
                                                ignoreThisItem = true;
 
460
                                        }
 
461
                                break;
 
462
 
 
463
                                case SnippetItemData::TYPE_CATEGORY:
 
464
                                        if ( IDToFind not_eq itemData->GetID() )
 
465
                                        {
 
466
                                                ignoreThisItem = true;
 
467
                                        }
 
468
                                break;
 
469
                        }
 
470
 
 
471
                        if (!ignoreThisItem)
 
472
                        {
 
473
                                wxString label = GetItemText(item);
 
474
 
 
475
                                if( IDToFind == itemData->GetID() )
 
476
                                {
 
477
                                        return item;
 
478
                                }
 
479
                        }
 
480
 
 
481
                        if ( ItemHasChildren(item) )
 
482
                        {
 
483
                                wxTreeItemId search = FindTreeItemBySnippetId( IDToFind, item );
 
484
                                if(search.IsOk())
 
485
                                {
 
486
                                        return search;
 
487
                                }
 
488
                        }
 
489
                        item = GetNextChild(startNode, cookie);
 
490
 
 
491
            //if ( (item = GetNextSibling( item ) ))
 
492
            //    continue;
 
493
                }//if snippet item
 
494
        }//while ok tree item
 
495
 
 
496
   // Return dummy item if search string was not found
 
497
   return dummyItem;
 
498
}
 
499
 
 
500
// ----------------------------------------------------------------------------
396
501
void CodeSnippetsTreeCtrl::SaveItemsToXmlNode(TiXmlNode* node, const wxTreeItemId& parentID)
397
 
// ----------------------------------------------------------------------------
 
502
// ----------------------------------------------------------------------------
398
503
{
 
504
    // Translate tree items to xml data
 
505
 
399
506
        wxTreeItemIdValue cookie;
400
507
        wxTreeItemId item = GetFirstChild(parentID, cookie);
401
508
 
415
522
                        {
416
523
                                // Category
417
524
                                element.SetAttribute("type", "category");
 
525
                                element.SetAttribute("ID", csU2C(data->GetSnippetIDStr()) );
418
526
 
419
527
                                // Check if this category has children
420
528
                                if(ItemHasChildren(item))
427
535
                        {
428
536
                                // Snippet
429
537
                                element.SetAttribute("type", "snippet");
 
538
                                element.SetAttribute("ID", csU2C(data->GetSnippetIDStr()) );
430
539
 
431
540
                                TiXmlElement snippetElement("snippet");
432
541
                                TiXmlText snippetElementText(csU2C(data->GetSnippet()));
449
558
        }
450
559
}
451
560
 
452
 
// ----------------------------------------------------------------------------
 
561
// ----------------------------------------------------------------------------
453
562
void CodeSnippetsTreeCtrl::LoadItemsFromXmlNode(const TiXmlElement* node, const wxTreeItemId& parentID)
454
 
// ----------------------------------------------------------------------------
 
563
// ----------------------------------------------------------------------------
455
564
{
 
565
    // Translate xml data to tree data
 
566
 
456
567
        for (; node; node = node->NextSiblingElement())
457
568
        {
458
569
                // Check if the node has attributes
459
570
                const wxString itemName(csC2U(node->Attribute("name")));
460
571
                const wxString itemType(csC2U(node->Attribute("type")));
 
572
                const wxString itemIDstr(csC2U(node->Attribute("ID")));
 
573
                long itemID;
 
574
                itemIDstr.ToLong(&itemID);
461
575
 
462
576
                // Check the item type
463
577
                if (itemType == _T("category"))
464
578
                {
465
579
                        // Add new category
466
 
                        wxTreeItemId newCategoryId = AddCategory(parentID, itemName, false);
 
580
                        wxTreeItemId newCategoryId = AddCategory(parentID, itemName, itemID, /*editNow*/false);
467
581
 
468
582
                        // Load the child items
469
583
                        if (!node->NoChildren())
480
594
                                {
481
595
                                        if (snippetElementText->ToText())
482
596
                                        {
483
 
                                                AddCodeSnippet(parentID, itemName, csC2U(snippetElementText->Value()), false);
 
597
                                                AddCodeSnippet(parentID, itemName, csC2U(snippetElementText->Value()), itemID,  /*editNow*/false);
484
598
                                        }
485
599
                                }
486
600
                                else
487
601
                                {
488
602
                                        // Create a new snippet with no code in it
489
 
                                        AddCodeSnippet(parentID, itemName, wxEmptyString, false);
 
603
                                        AddCodeSnippet(parentID, itemName, wxEmptyString, itemID, /*editNow*/false);
490
604
                                }
491
605
                        }
492
606
                        else
493
 
                        {
494
 
                                messageBox(_T("CodeSnippets: Error loading XML file; element \"snippet\" cannot be found."));
 
607
                        {
 
608
                GenericMessageBox(_T("CodeSnippets: Error loading XML file; element \"snippet\" cannot be found."));
495
609
                        }
496
610
                }
497
611
                else
498
 
                {
499
 
                    messageBox(_T("CodeSnippets: Error loading XML file; attribute \"type\" is \"") + itemType + _T("\" which is invalid item type."));
 
612
                {
 
613
                    GenericMessageBox(_T("CodeSnippets: Error loading XML file; attribute \"type\" is \"") + itemType + _T("\" which is invalid item type."));
500
614
                        return;
501
615
                }
502
616
        } // end for
503
617
}
504
618
 
505
 
// ----------------------------------------------------------------------------
 
619
// ----------------------------------------------------------------------------
506
620
void CodeSnippetsTreeCtrl::SaveItemsToFile(const wxString& fileName)
507
 
// ----------------------------------------------------------------------------
508
 
{
509
 
    // This routine also called from codesnippets.cpp::OnRelease()
510
 
 
 
621
// ----------------------------------------------------------------------------
 
622
{
 
623
    // This routine also called from codesnippets.cpp::OnRelease()
 
624
 
 
625
    // verify all dir levels exist
 
626
    CreateDirLevels(fileName);
 
627
 
 
628
    SnippetItemData::SetHighestSnippetID( 0 );
 
629
    ResetSnippetsIDs( GetRootItem() );
 
630
 
511
631
        TiXmlDocument doc;
512
632
        TiXmlDeclaration header("1.0", "UTF-8", "yes");
513
633
        doc.InsertEndChild(header);
521
641
 
522
642
        doc.InsertEndChild(snippetsElement);
523
643
 
524
 
        doc.SaveFile(fileName.mb_str());
525
 
        SetFileChanged(false);
526
 
        SaveFileModificationTime();
527
 
 
528
 
    #ifdef LOGGING
529
 
     LOGIT( _T("File saved:[%s]"),fileName.c_str() );
 
644
        int rc = doc.SaveFile(fileName.mb_str());
 
645
    if(not rc)
 
646
    {   wxString msg = wxString::Format(_T("ERROR: Failed to save %s"), fileName.c_str());
 
647
        wxMessageBox(msg, _T("ERROR"));
 
648
    }
 
649
        SetFileChanged(false);
 
650
        SnippetItemData::SetSnippetsItemsChangedCount(0);
 
651
        FetchFileModificationTime();
 
652
 
 
653
    // Give Snippets Search the .xml index filename
 
654
    // indicating possible content changes
 
655
    CodeSnippetsEvent evt( wxEVT_CODESNIPPETS_NEW_INDEX, 0);
 
656
    evt.SetSnippetString( GetConfig()->SettingsSnippetsXmlPath );
 
657
    evt.PostCodeSnippetsEvent(evt);
 
658
 
 
659
    #ifdef LOGGING
 
660
     if (rc) LOGIT( _T("File saved:[%s]"),fileName.c_str() );
530
661
    #endif //LOGGING
531
662
}
532
663
 
533
 
// ----------------------------------------------------------------------------
 
664
// ----------------------------------------------------------------------------
534
665
bool CodeSnippetsTreeCtrl::LoadItemsFromFile(const wxString& fileName, bool bAppendItems)
535
 
// ----------------------------------------------------------------------------
536
 
{
537
 
        if (!bAppendItems)
538
 
        DeleteChildren( GetRootItem() );
539
 
 
 
666
// ----------------------------------------------------------------------------
 
667
{
 
668
        if (!bAppendItems)
 
669
    {
 
670
        DeleteChildren( GetRootItem() );
 
671
        SnippetItemData::SetHighestSnippetID( 0 );
 
672
        SnippetItemData::SetSnippetsItemsChangedCount(0);
 
673
    }
 
674
 
540
675
    bool retcode = true;
541
676
        if (wxFileExists(fileName))
542
677
        {
559
694
                        }
560
695
                }
561
696
                else
562
 
                {
 
697
                {
563
698
                    retcode = false;
564
699
                        // Create a backup copy of the offending file
565
700
                        wxString backupFile = fileName;
567
702
 
568
703
                        // Overwrite it
569
704
                        wxCopyFile(fileName, backupFile, true);
570
 
           #if defined(BUILDING_PLUGIN)
571
 
                        Manager::Get()->GetLogManager()->DebugLog(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
572
 
                        Manager::Get()->GetLogManager()->DebugLog(_T("CodeSnippets: Backup of the failed file has been created."));
573
 
                   #else
574
 
            //-wxMessageBox(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
575
 
            messageBox(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
576
 
                        //-wxMessageBox(_T("CodeSnippets: Backup of the failed file has been created."));
577
 
                        messageBox(_T("CodeSnippets: Backup of the failed file has been created."));
578
 
                   #endif
 
705
           //-#if defined(BUILDING_PLUGIN)
 
706
           if ( GetConfig()->IsPlugin() )
 
707
           {
 
708
                Manager::Get()->GetLogManager()->DebugLog(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
 
709
                Manager::Get()->GetLogManager()->DebugLog(_T("CodeSnippets: Backup of the failed file has been created."));
 
710
           }
 
711
                   //-#else
 
712
                   else //IsApplication
 
713
                   {
 
714
                //-wxMessageBox(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
 
715
                GenericMessageBox(_T("CodeSnippets: Cannot load file \"") + fileName + _T("\": ") + csC2U(doc.ErrorDesc()));
 
716
                //-wxMessageBox(_T("CodeSnippets: Backup of the failed file has been created."));
 
717
                GenericMessageBox(_T("CodeSnippets: Backup of the failed file has been created."));
 
718
                   }
 
719
                   //-#endif
579
720
                }
580
 
        }
581
 
        // Show the first level of items
582
 
        if (  GetRootItem() && GetRootItem().IsOk())
583
 
        Expand( GetRootItem() );
584
 
 
585
 
    // show filename window banner
586
 
    wxString nameOnly;
587
 
    wxFileName::SplitPath( fileName, 0, &nameOnly, 0);
588
 
    // Edit the root node's title so that the user sees file name
589
 
    GetSnippetsTreeCtrl()->SetItemText(GetSnippetsTreeCtrl()->GetRootItem(), wxString::Format(_("%s"), nameOnly.GetData()));
590
 
 
591
 
    SetFileChanged(false);
592
 
    SaveFileModificationTime();
593
 
    return retcode;
594
 
 
 
721
        }
 
722
        // Show the first level of items
 
723
        if (  GetRootItem() && GetRootItem().IsOk())
 
724
        Expand( GetRootItem() );
 
725
 
 
726
    // show filename window banner
 
727
    wxString nameOnly;
 
728
    wxFileName::SplitPath( fileName, 0, &nameOnly, 0);
 
729
    // Edit the root node's title so that the user sees file name
 
730
    SetItemText( GetRootItem(), wxString::Format(_("%s"), nameOnly.GetData()));
 
731
 
 
732
    if (not SnippetItemData::GetSnippetsItemsChangedCount() )
 
733
        SetFileChanged(false);
 
734
    FetchFileModificationTime();
 
735
 
 
736
    // Issue event for new snippets index file
 
737
    CodeSnippetsEvent evt( wxEVT_CODESNIPPETS_NEW_INDEX, 0);
 
738
    evt.SetSnippetString( fileName );
 
739
    evt.PostCodeSnippetsEvent(evt);
 
740
 
 
741
    return retcode;
595
742
}
596
 
 
597
 
// ----------------------------------------------------------------------------
598
 
void CodeSnippetsTreeCtrl::AddCodeSnippet(const wxTreeItemId& parent,
599
 
                            wxString title, wxString codeSnippet, bool editNow)
600
 
// ----------------------------------------------------------------------------
 
743
// ----------------------------------------------------------------------------
 
744
void CodeSnippetsTreeCtrl::AddCodeSnippet(const wxTreeItemId& parent,
 
745
                            wxString title, wxString codeSnippet, long ID, bool editNow)
 
746
// ----------------------------------------------------------------------------
601
747
{
602
 
        wxTreeItemId newItemID = InsertItem(parent, GetLastChild(parent), title, 2, -1,
603
 
                new SnippetItemData(SnippetItemData::TYPE_SNIPPET, codeSnippet));
 
748
    SnippetItemData* pSnippetDataItem = new SnippetItemData(SnippetItemData::TYPE_SNIPPET, codeSnippet, ID);
 
749
        wxTreeItemId newItemID = InsertItem(parent, GetLastChild(parent), title, 2, -1,
 
750
                pSnippetDataItem );
604
751
 
605
752
        // Sort 'em
606
753
        SortChildren(parent);
607
 
 
608
 
    bool ok = false;
 
754
 
 
755
    bool ok = false;
609
756
    if ( newItemID && newItemID.IsOk() ) ok = true;
610
757
        if (editNow)
611
758
        {
612
759
                // Let the user edit the item
613
760
                EnsureVisible(newItemID);
614
 
                ////-EditLabel(newItemID);
615
 
                ok = EditSnippetProperties( newItemID );
616
 
                if (not ok) RemoveItem(newItemID);
 
761
                ////-EditLabel(newItemID);
 
762
                ok = EditSnippetProperties( newItemID );
 
763
                if (not ok) RemoveItem(newItemID);
617
764
                else SelectItem( newItemID );
618
 
        }
619
 
 
620
 
        if ( ok && newItemID.IsOk() )
621
 
    {   SetSnippetImage(newItemID);
622
 
        SetFileChanged(true);
623
 
    }
 
765
        }
 
766
 
 
767
        if ( ok && newItemID.IsOk() )
 
768
    {   SetSnippetImage(newItemID);
 
769
        SetFileChanged(true);
 
770
    }
624
771
 
625
772
}
626
773
 
627
 
// ----------------------------------------------------------------------------
628
 
wxTreeItemId CodeSnippetsTreeCtrl::AddCategory(const wxTreeItemId& parent, wxString title, bool editNow)
629
 
// ----------------------------------------------------------------------------
 
774
// ----------------------------------------------------------------------------
 
775
wxTreeItemId CodeSnippetsTreeCtrl::AddCategory(const wxTreeItemId& parent, wxString title, long ID, bool editNow)
 
776
// ----------------------------------------------------------------------------
630
777
{
631
 
        wxTreeItemId newCategoryID = InsertItem(parent, GetLastChild(parent), title, 1, -1, new SnippetItemData(SnippetItemData::TYPE_CATEGORY));
 
778
        wxTreeItemId newCategoryID = InsertItem(parent, GetLastChild(parent), title, 1, -1,
 
779
            new SnippetItemData(SnippetItemData::TYPE_CATEGORY, ID));
632
780
 
633
781
        // Sort 'em
634
782
        SortChildren(parent);
637
785
        {
638
786
                // Let the user edit the category
639
787
                EnsureVisible(newCategoryID);
640
 
                EditLabel(newCategoryID);
641
 
        SetFileChanged(true);
 
788
                EditLabel(newCategoryID);
 
789
        SetFileChanged(true);
642
790
        }
643
791
 
644
792
        return newCategoryID;
645
 
}
646
 
// ----------------------------------------------------------------------------
647
 
bool CodeSnippetsTreeCtrl::RemoveItem(const wxTreeItemId RemoveItemId)
648
 
// ----------------------------------------------------------------------------
649
 
{
650
 
        // Get the associated item id
651
 
        wxTreeItemId itemId = RemoveItemId;
652
 
        // Sanity checks
653
 
        if (not itemId.IsOk()) return false;
654
 
        if (itemId == GetRootItem() ) return false;
655
 
 
656
 
    SnippetItemData* pItemData = (SnippetItemData*)(GetItemData(itemId));
657
 
    if (not pItemData) return false;
658
 
 
659
 
    bool shiftKeyIsDown = ::wxGetKeyState(WXK_SHIFT);
660
 
    wxString itemText = GetItemText(RemoveItemId);
661
 
 
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")) )
665
 
    {
666
 
        canceledItem = true;
667
 
        shiftKeyIsDown = true;
668
 
    }
669
 
    bool trashItem = false;
670
 
 
671
 
    // if shift key is up, copy item to .trash category
672
 
    if (not shiftKeyIsDown)
673
 
    {
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);
678
 
 
679
 
        // if item is NOT already in the trash, copy item to .trash category
680
 
        if (not ( FindItemById( itemId, trashId, pItemData->GetType()) ))
681
 
        {
682
 
            TiXmlDocument* pDoc =  CopyTreeNodeToXmlDoc( itemId);
683
 
            CopyXmlDocToTreeNode(pDoc, trashId);
684
 
            delete pDoc;
685
 
        }
686
 
        else // item already in .trash, delete it
687
 
        {
688
 
            trashItem = true;
689
 
        }
690
 
    }//if not shiftKeyIsDown
691
 
 
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 )
695
 
    {
696
 
        // if FileLink, memorize the filename
697
 
        wxString filename = wxEmptyString;
698
 
        if ( IsFileSnippet(itemId) )
699
 
           filename = GetSnippetFileLink(itemId);
700
 
 
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);
707
 
        }
708
 
    }//if trashItem
709
 
 
710
 
    // Delete the original Snippet Tree Item
711
 
    DeleteChildren(itemId);
712
 
    Delete(itemId);
713
 
    SetFileChanged(true);
714
 
 
715
 
        return true;
716
 
}
717
 
 
718
 
// ----------------------------------------------------------------------------
719
 
void CodeSnippetsTreeCtrl::SetSnippetImage(wxTreeItemId itemId)
720
 
// ----------------------------------------------------------------------------
721
 
{
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);
727
 
    else
728
 
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
729
 
    return;
730
 
}
731
 
// ----------------------------------------------------------------------------
732
 
void CodeSnippetsTreeCtrl::SaveFileModificationTime(wxDateTime savedTime)
733
 
// ----------------------------------------------------------------------------
734
 
{
735
 
    if (savedTime != time_t(0))
736
 
    {   m_LastXmlModifiedTime = savedTime;
737
 
        return;
738
 
    }
739
 
    if (::wxFileExists(GetConfig()->SettingsSnippetsXmlFullPath) )
740
 
    {   wxFileName fname( GetConfig()->SettingsSnippetsXmlFullPath );
741
 
        m_LastXmlModifiedTime = fname.GetModificationTime();
742
 
    }
743
 
}
744
 
// ----------------------------------------------------------------------------
745
 
void CodeSnippetsTreeCtrl::OnBeginTreeItemDrag(wxTreeEvent& event)
746
 
// ----------------------------------------------------------------------------
747
 
{
748
 
    // -----------------------
749
 
    // TREE_BEGIN_DRAG
750
 
    // -----------------------
751
 
    CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
752
 
 
753
 
    //#ifdef LOGGING
754
 
    //   LOGIT( wxT("ScrapList::OnTreeCtrlEvent %p"), pTree );
755
 
    //#endif //LOGGING
756
 
 
757
 
    #ifdef LOGGING
758
 
     LOGIT( _T("TREE_CTRL_BEGIN_DRAG %p"), pTree );
759
 
    #endif //LOGGING
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() );
775
 
    event.Allow();
776
 
 
777
 
    // -----------------------------------------
778
 
    // Do *not* event.Skip() or GTK will break
779
 
    //event.Skip();
780
 
    // -----------------------------------------
781
 
 
782
 
    return;
783
 
}//OnBeginTreeItemDrag
784
 
// ----------------------------------------------------------------------------
785
 
void CodeSnippetsTreeCtrl::OnEndTreeItemDrag(wxTreeEvent& event)
786
 
// ----------------------------------------------------------------------------
787
 
{
788
 
    // -----------------------
789
 
    // TREE_END_DRAG
790
 
    // -----------------------
791
 
 
792
 
 
793
 
    #ifdef LOGGING
794
 
     wxTreeCtrl* pTree = (wxTreeCtrl*)event.GetEventObject();
795
 
     LOGIT( _T("TREE_CTRL_END_DRAG %p"), pTree );
796
 
    #endif //LOGGING
 
793
}
 
794
// ----------------------------------------------------------------------------
 
795
bool CodeSnippetsTreeCtrl::RemoveItem(const wxTreeItemId RemoveItemId)
 
796
// ----------------------------------------------------------------------------
 
797
{
 
798
        // Get the associated item id
 
799
        wxTreeItemId itemId = RemoveItemId;
 
800
        // Sanity checks
 
801
        if (not itemId.IsOk()) return false;
 
802
        if (itemId == GetRootItem() ) return false;
 
803
 
 
804
    SnippetItemData* pItemData = (SnippetItemData*)(GetItemData(itemId));
 
805
    if (not pItemData) return false;
 
806
 
 
807
    bool shiftKeyIsDown = ::wxGetKeyState(WXK_SHIFT);
 
808
    wxString itemText = GetItemText(RemoveItemId);
 
809
 
 
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")) )
 
813
    {
 
814
        canceledItem = true;
 
815
        shiftKeyIsDown = true;
 
816
    }
 
817
    bool trashItem = false;
 
818
 
 
819
    // if shift key is up, copy item to .trash category
 
820
    if (not shiftKeyIsDown)
 
821
    {
 
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);
 
826
 
 
827
        // if item is NOT already in the trash, copy item to .trash category
 
828
        if (not ( FindTreeItemByTreeId( itemId, trashId, pItemData->GetType()) ))
 
829
        {
 
830
            TiXmlDocument* pDoc =  CopyTreeNodeToXmlDoc( itemId);
 
831
            CopyXmlDocToTreeNode(pDoc, trashId);
 
832
            delete pDoc;
 
833
        }
 
834
        else // item already in .trash, delete it
 
835
        {
 
836
            trashItem = true;
 
837
        }
 
838
    }//if not shiftKeyIsDown
 
839
 
 
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 )
 
843
    {
 
844
        // if FileLink, memorize the filename
 
845
        wxString filename = wxEmptyString;
 
846
        if ( IsFileSnippet(itemId) )
 
847
           filename = GetSnippetFileLink(itemId);
 
848
 
 
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);
 
855
        }
 
856
    }//if trashItem
 
857
 
 
858
    // Delete the original Snippet Tree Item
 
859
    DeleteChildren(itemId);
 
860
    Delete(itemId);
 
861
    SetFileChanged(true);
 
862
 
 
863
        return true;
 
864
}
 
865
 
 
866
// ----------------------------------------------------------------------------
 
867
void CodeSnippetsTreeCtrl::SetSnippetImage(wxTreeItemId itemId)
 
868
// ----------------------------------------------------------------------------
 
869
{
 
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);
 
875
    else
 
876
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
 
877
    return;
 
878
}
 
879
// ----------------------------------------------------------------------------
 
880
void CodeSnippetsTreeCtrl::FetchFileModificationTime(wxDateTime savedTime)
 
881
// ----------------------------------------------------------------------------
 
882
{
 
883
    if (savedTime != time_t(0))
 
884
    {   m_LastXmlModifiedTime = savedTime;
 
885
        return;
 
886
    }
 
887
    if (::wxFileExists(GetConfig()->SettingsSnippetsXmlPath) )
 
888
    {   wxFileName fname( GetConfig()->SettingsSnippetsXmlPath );
 
889
        m_LastXmlModifiedTime = fname.GetModificationTime();
 
890
    }
 
891
}
 
892
// ----------------------------------------------------------------------------
 
893
void CodeSnippetsTreeCtrl::OnBeginTreeItemDrag(wxTreeEvent& event)
 
894
// ----------------------------------------------------------------------------
 
895
{
 
896
    // -----------------------
 
897
    // TREE_BEGIN_DRAG
 
898
    // -----------------------
 
899
    CodeSnippetsTreeCtrl* pTree = (CodeSnippetsTreeCtrl*)event.GetEventObject();
 
900
 
 
901
    #ifdef LOGGING
 
902
     LOGIT( _T("TREE_CTRL_BEGIN_DRAG %p"), pTree );
 
903
    #endif //LOGGING
 
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;
 
918
    event.Allow();
 
919
 
 
920
    // -----------------------------------------
 
921
    // Do *not* event.Skip() or GTK will break.
 
922
    //event.Skip();
 
923
    // -----------------------------------------
 
924
 
 
925
    return;
 
926
}//OnBeginTreeItemDrag
 
927
// ----------------------------------------------------------------------------
 
928
void CodeSnippetsTreeCtrl::OnEndTreeItemDrag(wxTreeEvent& event)
 
929
// ----------------------------------------------------------------------------
 
930
{
 
931
    // -----------------------
 
932
    // TREE_END_DRAG
 
933
    // -----------------------
 
934
 
 
935
 
 
936
    #ifdef LOGGING
 
937
     wxTreeCtrl* pTree = (wxTreeCtrl*)event.GetEventObject();
 
938
     LOGIT( _T("TREE_CTRL_END_DRAG %p"), pTree );
 
939
    #endif //LOGGING
797
940
 
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)
803
946
    {
804
947
        event.Skip(); return;
805
 
    }
806
 
 
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() )
812
 
        //    event.Allow();
813
 
        //else return;
814
 
 
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.
 
948
    }
 
949
 
 
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() )
 
955
        //    event.Allow();
 
956
        //else return;
 
957
 
 
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;
820
963
        return;
821
964
    }
822
 
 
 
965
 
823
966
    event.Allow();
824
 
    // if source and target are snippets, create a new category and enclose both.
825
 
    if ( IsSnippet(targetItem) )
826
 
    {
827
 
        if ( targetItem = ConvertSnippetToCategory(targetItem)) {;}//ok
828
 
        else return;
829
 
        // now targetItem is a category
830
 
    }
831
 
 
832
 
 
833
 
    // Save the source item node to an Xml Document
834
 
    // Load it into the target item node
835
 
    // delete the source item node
836
 
 
837
 
    // create Xml document from source(dragged) tree item
838
 
    TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( sourceItem );
839
 
    if (not pDoc) return;
840
 
 
841
 
    TiXmlElement* root = pDoc->RootElement();
842
 
    if (root)
843
 
    {
844
 
        // Get the source xml element
845
 
        TiXmlElement* firstChild = root->FirstChildElement("item");
846
 
        if (firstChild)
847
 
        {   // insert into target Tree items from source xml document
848
 
            LoadItemsFromXmlNode( firstChild, targetItem);
849
 
        }
850
 
    }
851
 
    // remove the old tree item
852
 
    if (not m_MouseCtrlKeyDown){
853
 
            RemoveItem( sourceItem );
854
 
    }
855
 
 
856
 
    delete pDoc; pDoc = 0;
857
 
 
858
 
    // -----------------------------------------
859
 
    // Do *not* event.Skip() or GTK will break
860
 
    //event.Skip();
861
 
    // -----------------------------------------
862
 
 
863
 
    return;
864
 
 
865
 
}//OnEndTreeItemDrag
866
 
// ----------------------------------------------------------------------------
867
 
void CodeSnippetsTreeCtrl::OnEnterWindow(wxMouseEvent& event)
868
 
// ----------------------------------------------------------------------------
869
 
{
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();
873
 
    pw->Enable();
874
 
    pw->SetFocus();
875
 
    event.Skip();
876
 
}
877
 
// ----------------------------------------------------------------------------
878
 
void CodeSnippetsTreeCtrl::OnLeaveWindow(wxMouseEvent& event)
879
 
// ----------------------------------------------------------------------------
880
 
{
881
 
    // -----------------------
882
 
    // LEAVE_WINDOW
883
 
    // -----------------------
884
 
 
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.
888
 
 
889
 
    #ifdef LOGGING
890
 
     //LOGIT( _T("MOUSE EVT_LEAVE_WINDOW") );
891
 
    #endif //LOGGING
892
 
 
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;}
898
 
 
899
 
    #ifdef LOGGING
900
 
     LOGIT( _T("LEAVE_WINDOW %p"), event.GetEventObject() );
901
 
    #endif //LOGGING
 
967
    // if source and target are snippets, create a new category and enclose both.
 
968
    if ( IsSnippet(targetItem) )
 
969
    {
 
970
        if ( (targetItem = ConvertSnippetToCategory(targetItem)) )
 
971
        {;}//ok
 
972
        else return;
 
973
        // now targetItem is a category
 
974
    }
 
975
 
 
976
 
 
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
 
980
 
 
981
    // create Xml document from source(dragged) tree item
 
982
    TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( sourceItem );
 
983
    if (not pDoc) return;
 
984
 
 
985
    TiXmlElement* root = pDoc->RootElement();
 
986
    if (root)
 
987
    {
 
988
        // Get the source xml element
 
989
        TiXmlElement* firstChild = root->FirstChildElement("item");
 
990
        if (firstChild)
 
991
        {   // insert into target Tree items from source xml document
 
992
            LoadItemsFromXmlNode( firstChild, targetItem);
 
993
        }
 
994
    }
 
995
    // remove the old tree item
 
996
    if (not m_MouseCtrlKeyDown){
 
997
            RemoveItem( sourceItem );
 
998
    }
 
999
 
 
1000
    delete pDoc; pDoc = 0;
 
1001
 
 
1002
    // -----------------------------------------
 
1003
    // Do *not* event.Skip() or GTK will break.
 
1004
    //event.Skip();
 
1005
    // -----------------------------------------
 
1006
 
 
1007
    return;
 
1008
 
 
1009
}//OnEndTreeItemDrag
 
1010
// ----------------------------------------------------------------------------
 
1011
void CodeSnippetsTreeCtrl::OnEnterWindow(wxMouseEvent& event)
 
1012
// ----------------------------------------------------------------------------
 
1013
{
 
1014
    //*WARNING* child windows of wxAUI windows do not get common events.
 
1015
    // unless the parent wxAUI window has/had focus.
 
1016
 
 
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.
 
1024
 
 
1025
    #if defined(LOGGING)
 
1026
    //LOGIT( _T("CodeSnippetsTreeCtrl::OnEnterWindow"));
 
1027
    #endif
 
1028
 
 
1029
    // If the user is editing a label, don't refocus the control
 
1030
    if ( not GetConfig()->GetSnippetsWindow()->IsEditingLabel() )
 
1031
    if ( GetConfig()->IsFloatingWindow())
 
1032
    {
 
1033
        #if defined(LOGGING)
 
1034
        //LOGIT( _T("CodeSnippetsCtrl IsFloatingWindow[%s]"), _T("TRUE"));
 
1035
        #endif
 
1036
        wxWindow* pw = (wxWindow*)event.GetEventObject();
 
1037
        // only if forground is our window, set focus
 
1038
        if ( pw == ::wxGetActiveWindow() )
 
1039
        {   pw->Enable();
 
1040
            pw->SetFocus();
 
1041
        }
 
1042
    }
 
1043
 
 
1044
    event.Skip();
 
1045
}
 
1046
// ----------------------------------------------------------------------------
 
1047
void CodeSnippetsTreeCtrl::OnLeaveWindow(wxMouseEvent& event)
 
1048
// ----------------------------------------------------------------------------
 
1049
{
 
1050
    // -----------------------
 
1051
    // LEAVE_WINDOW
 
1052
    // -----------------------
 
1053
 
 
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.
 
1057
 
 
1058
    #ifdef LOGGING
 
1059
     //LOGIT( _T("CodeSnippetsTreeCtrl::OnLeaveWindow") );
 
1060
    #endif //LOGGING
 
1061
 
 
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;}
 
1067
 
 
1068
    #ifdef LOGGING
 
1069
     LOGIT( _T("LEAVE_WINDOW %p"), event.GetEventObject() );
 
1070
    #endif //LOGGING
902
1071
 
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;
906
 
 
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() );
916
 
    #endif
917
 
    wxDropSource textSource( *textData, (wxWindow*)event.GetEventObject() );
918
 
    textData->SetText( textStr );
919
 
 
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()  );
930
 
 
931
 
    #ifdef LOGGING
932
 
     LOGIT( _T("DropSource Text[%s],File[%s]"),
933
 
                textData->GetText().GetData(),
934
 
                fileData->GetFilenames().Item(0).GetData() );
935
 
    #endif //LOGGING
936
 
        // allow both copy and move
937
 
    int flags = 0;
938
 
    flags |= wxDrag_AllowMove;
939
 
    // do the dragNdrop
940
 
    wxDragResult result = source.DoDragDrop(flags);
941
 
    // report the results
942
 
    #if LOGGING
943
 
        wxString pc;
944
 
        switch ( result )
945
 
        {
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;
952
 
        }
953
 
        LOGIT( wxT("ScrapList::OnLeftDown DoDragDrop returned[%s]"),pc.GetData() );
954
 
    #else
955
 
        wxUnusedVar(result);
956
 
    #endif
957
 
 
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.
963
 
    // Hack:
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.
966
 
 
967
 
    if ( m_pEvtTreeCtrlBeginDrag )
968
 
    {
969
 
        //send Mouse LeftKeyUp to Tree Control window
970
 
        #ifdef LOGGING
971
 
         //LOGIT( _T("Sending Mouse LeftKeyUp") );
972
 
        #endif //LOGGING
973
 
 
974
 
        // move mouse into the Tree control
975
 
        wxPoint CurrentMousePosn = ::wxGetMousePosition();
976
 
 
977
 
      #if defined(__WXMSW__)
978
 
        MSW_MouseMove( m_TreeMousePosn.x, m_TreeMousePosn.y );
979
 
        // send mouse LeftKeyUp
980
 
        INPUT    Input={0};
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 );
986
 
      #endif //(__WXMSW__)
987
 
 
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 ();
998
 
        int xx=0,yy=0;
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);
1002
 
        GdkEventButton evb;
1003
 
        memset(&evb, 0, sizeof(evb));
1004
 
        evb.type = GDK_BUTTON_RELEASE;
1005
 
        evb.window = pGdkWindow;
1006
 
        evb.x = xx;
1007
 
        evb.y = yy;
1008
 
        evb.state = GDK_BUTTON1_MASK;
1009
 
        evb.button = 1;
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 );
1018
 
      #endif//(__WXGTK__)
1019
 
 
1020
 
    }//if
1021
 
 
1022
 
    delete textData; //wxTextDataObject
1023
 
    delete fileData; //wxFileDataObject
1024
 
    m_pEvtTreeCtrlBeginDrag = 0;
1025
 
    m_TreeText = wxEmptyString;
1026
 
 
1027
 
    event.Skip();
1028
 
    return;
1029
 
}//OnLeaveWindow
1030
 
// ----------------------------------------------------------------------------
1031
 
void CodeSnippetsTreeCtrl::OnMouseEvent(wxMouseEvent& event)
1032
 
// ----------------------------------------------------------------------------
1033
 
{
1034
 
    //remember event window pointer
1035
 
    //wxObject* m_pEvtObject = event.GetEventObject();
1036
 
 
1037
 
    // memorize position of the mouse ctrl key as copy/delete flag
1038
 
    m_MouseCtrlKeyDown = event.ControlDown();
1039
 
    #ifdef LOGGING
1040
 
     //LOGIT(wxT("MouseCtrlKeyDown[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
1041
 
    #endif
1042
 
    event.Skip();
1043
 
 
1044
 
}
1045
 
// ----------------------------------------------------------------------------
1046
 
#if defined(__WXMSW__)
1047
 
void CodeSnippetsTreeCtrl::MSW_MouseMove(int x, int y )
1048
 
// ----------------------------------------------------------------------------
1049
 
{
1050
 
    // Move mouse uses a very strange coordinate system.
1051
 
    // It uses screen positions with a range of 0 to 65535
1052
 
 
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);
1058
 
      INPUT  Input={0};
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));
1064
 
}
1065
 
#endif
1066
 
// ----------------------------------------------------------------------------
1067
 
wxTreeItemId CodeSnippetsTreeCtrl::ConvertSnippetToCategory(wxTreeItemId itemId)
1068
 
// ----------------------------------------------------------------------------
1069
 
{
1070
 
    // Convert Snippet to Category, then insert the old snippet
1071
 
    wxTreeItemId badItemId = (void*)0;
1072
 
 
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);
1079
 
 
1080
 
        // create Xml document from selected tree item
1081
 
    TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( oldItemId );
1082
 
    if (not pDoc) return badItemId;
1083
 
 
1084
 
    // Create new Category
1085
 
    wxTreeItemId newCategoryId = AddCategory( itemParent,
1086
 
                GetItemText(oldItemId), false );
1087
 
 
1088
 
    // Insert old Snippet Item under new Category
1089
 
    TiXmlElement* root = pDoc->RootElement();
1090
 
    if (root)
1091
 
    {
1092
 
            // Get the first xml element
1093
 
        TiXmlElement* firstChild = root->FirstChildElement("item");
1094
 
        if (firstChild)
1095
 
        {   // insert Tree items from xml document
1096
 
            //-LoadSnippets(firstChild, newCategoryId);
1097
 
            LoadItemsFromXmlNode( firstChild, newCategoryId);
1098
 
 
1099
 
        }
1100
 
    }
1101
 
        // remove the old tree item
1102
 
    RemoveItem( oldItemId );
1103
 
    delete pDoc; pDoc = 0;
1104
 
    return newCategoryId;
1105
 
}
1106
 
// ----------------------------------------------------------------------------
1107
 
TiXmlDocument* CodeSnippetsTreeCtrl::CopyTreeNodeToXmlDoc(wxTreeItemId TreeItemId  )
1108
 
// ----------------------------------------------------------------------------
1109
 
{
1110
 
    // Copy a Tree node to an Xml Document
1111
 
 
1112
 
    wxTreeItemId itemId = TreeItemId;
1113
 
    if (not itemId.IsOk() )
1114
 
    {
1115
 
        itemId = GetSelection();
1116
 
    }
1117
 
    if (not itemId.IsOk()) return NULL;
1118
 
 
1119
 
        TiXmlDocument* pDoc = new TiXmlDocument;
1120
 
        TiXmlDeclaration header("1.0", "UTF-8", "yes");
1121
 
        pDoc->InsertEndChild(header);
1122
 
 
1123
 
        TiXmlElement snippetsElement("snippets");
1124
 
        CopySnippetsToXmlDoc(&snippetsElement, itemId);
1125
 
 
1126
 
        pDoc->InsertEndChild(snippetsElement);
1127
 
 
1128
 
        return pDoc;
1129
 
 
1130
 
} // end of SaveSnippetsToFile
1131
 
// ----------------------------------------------------------------------------
1132
 
void CodeSnippetsTreeCtrl::CopySnippetsToXmlDoc(TiXmlNode* Node, const wxTreeItemId& itemID)
1133
 
// ----------------------------------------------------------------------------
1134
 
{
1135
 
    // Recursively copy Tree item and all its children to an Xml document node
1136
 
 
1137
 
        wxTreeItemIdValue cookie;
1138
 
        //wxTreeItemId item = GetSnippetsTreeCtrl->GetFirstChild(parentID, cookie );
1139
 
    wxTreeItemId item = itemID;
1140
 
 
1141
 
        // Loop through all items
1142
 
        while(item.IsOk())
1143
 
        {
1144
 
                // Get the item's information
1145
 
                const SnippetItemData* data = (SnippetItemData*)GetItemData(item);
1146
 
 
1147
 
                if (!data)
1148
 
                {
1149
 
                        return;
1150
 
                }
1151
 
 
1152
 
                // Begin item element
1153
 
                TiXmlElement element("item");
1154
 
 
1155
 
                // Write the item's name
1156
 
                element.SetAttribute("name", GetItemText(item).mb_str());
1157
 
 
1158
 
                // Write the type of the item
1159
 
                switch (data->GetType())
1160
 
                {
1161
 
                        case SnippetItemData::TYPE_CATEGORY:
1162
 
                                element.SetAttribute("type", "category");
1163
 
                        break;
1164
 
 
1165
 
                        case SnippetItemData::TYPE_SNIPPET:
1166
 
                                element.SetAttribute("type", "snippet");
1167
 
                        break;
1168
 
 
1169
 
                        default:
1170
 
                        break;
1171
 
                }
1172
 
 
1173
 
                // And the snippet
1174
 
                if (data->GetType() == SnippetItemData::TYPE_SNIPPET)
1175
 
                {
1176
 
                        TiXmlElement snippetElement("snippet");
1177
 
                        TiXmlText snippetElementText(data->GetSnippet().mb_str());
1178
 
            snippetElement.InsertEndChild(snippetElementText);
1179
 
                        element.InsertEndChild(snippetElement);
1180
 
                        //#ifdef LOGGING
1181
 
                        // LOGIT( _T("Snippet[%s]"), data->GetSnippet().GetData() );
1182
 
                        //#endif //LOGGING
1183
 
                }
1184
 
 
1185
 
                // Check if this item has children
1186
 
                if(ItemHasChildren(item))
1187
 
                {
1188
 
                        // If it has, check those too
1189
 
                        //-SaveSnippets(&element, item);
1190
 
                        SaveItemsToXmlNode(&element, item);
1191
 
                }
1192
 
 
1193
 
                // Insert the item we created as parent node's child
1194
 
                //parentNode->InsertEndChild(element);
1195
 
                Node->InsertEndChild(element);
1196
 
 
1197
 
                // Check the next child
1198
 
                item = GetNextChild( itemID, cookie);
1199
 
        }
1200
 
}//CopySnippetsToXmlDoc
1201
 
// ----------------------------------------------------------------------------
1202
 
void CodeSnippetsTreeCtrl::CopyXmlDocToTreeNode(TiXmlDocument* pTiXmlDoc, wxTreeItemId targetItem  )
1203
 
// ----------------------------------------------------------------------------
1204
 
{
1205
 
    TiXmlElement* root = pTiXmlDoc->RootElement();
1206
 
    if (root)
1207
 
    {
1208
 
        // Get the source xml element
1209
 
        TiXmlElement* firstChild = root->FirstChildElement("item");
1210
 
        if (firstChild)
1211
 
        {   // insert into target Tree items from source xml document
1212
 
            LoadItemsFromXmlNode( firstChild, targetItem);
1213
 
        }
1214
 
    }
1215
 
 
1216
 
}
1217
 
// ----------------------------------------------------------------------------
1218
 
void CodeSnippetsTreeCtrl::EditSnippetAsFileLink()
1219
 
// ----------------------------------------------------------------------------
1220
 
{
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.
1223
 
 
1224
 
    #if defined(LOGGING)
1225
 
    LOGIT( _T("EditSnippetAsFileLink[%s]"),wxT("") );
1226
 
    #endif
1227
 
 
1228
 
    if (not IsSnippet() ) return;
1229
 
 
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() );
1235
 
 
1236
 
    if (FileName.Length() > 128)
1237
 
    {   // if text is > 128 characters, open a temp file with snippet text as data.
1238
 
        EditSnippetAsText();
1239
 
        return;
1240
 
    }
1241
 
 
1242
 
 
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();
1248
 
        return;
1249
 
    }
1250
 
 
 
1075
 
 
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() );
 
1087
    //-#endif
 
1088
 
 
1089
    wxDropSource textSource( *textData, (wxWindow*)event.GetEventObject() );
 
1090
    textData->SetText( textStr );
 
1091
 
 
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://")))
 
1098
            fileName = textStr;
 
1099
        if (textStr.StartsWith(_T("file://")))
 
1100
            fileName = textStr;
 
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 );
 
1105
    }
 
1106
    fileData->AddFile( (fileName.Len() > 128) ? wxString(wxEmptyString) : fileName );
 
1107
 
 
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()  );
 
1114
 
 
1115
    #ifdef LOGGING
 
1116
     LOGIT( _T("DropSource Text[%s], File[%s]"),
 
1117
                textData->GetText().c_str(),
 
1118
                fileData->GetFilenames().Item(0).c_str() );
 
1119
    #endif //LOGGING
 
1120
        // allow both copy and move
 
1121
    int flags = 0;
 
1122
    flags |= wxDrag_AllowMove;
 
1123
    // do the dragNdrop
 
1124
    wxDragResult result = source.DoDragDrop(flags);
 
1125
    // report the results
 
1126
    #if LOGGING
 
1127
        wxString pc;
 
1128
        switch ( result )
 
1129
        {
 
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;
 
1137
        }
 
1138
        LOGIT( wxT("OnLeaveWindow::OnLeftDown DoDragDrop returned[%s]"),pc.GetData() );
 
1139
    #else
 
1140
        wxUnusedVar(result);
 
1141
    #endif
 
1142
 
 
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.
 
1148
    // Hack:
 
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.
 
1151
 
 
1152
    if ( m_pEvtTreeCtrlBeginDrag )
 
1153
    {
 
1154
        //send Mouse LeftKeyUp to Tree Control window
 
1155
        #ifdef LOGGING
 
1156
         LOGIT( _T("Sending Mouse LeftKeyUp") );
 
1157
        #endif //LOGGING
 
1158
 
 
1159
        // remember current mouse position to restore
 
1160
        wxPoint CurrentMousePosn = ::wxGetMousePosition();
 
1161
 
 
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
 
1167
        INPUT    Input={0};
 
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__)
 
1174
 
 
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 ();
 
1185
        int xx=0,yy=0;
 
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);
 
1189
        GdkEventButton evb;
 
1190
        memset(&evb, 0, sizeof(evb));
 
1191
        evb.type = GDK_BUTTON_RELEASE;
 
1192
        evb.window = pGdkWindow;
 
1193
        evb.x = xx;
 
1194
        evb.y = yy;
 
1195
        evb.state = GDK_BUTTON1_MASK;
 
1196
        evb.button = 1;
 
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 );
 
1205
      #endif//(__WXGTK__)
 
1206
 
 
1207
    }//if
 
1208
 
 
1209
    delete textData; //wxTextDataObject
 
1210
    delete fileData; //wxFileDataObject
 
1211
    m_pEvtTreeCtrlBeginDrag = 0;
 
1212
    m_TreeText = wxEmptyString;
 
1213
 
 
1214
    event.Skip();
 
1215
    return;
 
1216
}//OnLeaveWindow
 
1217
// ----------------------------------------------------------------------------
 
1218
void CodeSnippetsTreeCtrl::OnMouseMotionEvent(wxMouseEvent& event)
 
1219
// ----------------------------------------------------------------------------
 
1220
{
 
1221
    //remember event window pointer
 
1222
    //wxObject* m_pEvtObject = event.GetEventObject();
 
1223
 
 
1224
    // memorize position of the mouse ctrl key as copy/delete flag
 
1225
    m_MouseCtrlKeyDown = event.ControlDown();
 
1226
    #ifdef LOGGING
 
1227
     //LOGIT(wxT("MouseCtrlKeyDown[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
 
1228
    #endif
 
1229
    event.Skip();
 
1230
 
 
1231
}
 
1232
// ----------------------------------------------------------------------------
 
1233
void CodeSnippetsTreeCtrl::OnMouseWheelEvent(wxMouseEvent& event)
 
1234
// ----------------------------------------------------------------------------
 
1235
{
 
1236
    // Ctrl-MouseWheel rotation changes treeCtrl font
 
1237
 
 
1238
    m_MouseCtrlKeyDown = event.ControlDown();
 
1239
    #ifdef LOGGING
 
1240
     //LOGIT(wxT("treeCtrl:OnMouseWheel[%s]"), m_MouseCtrlKeyDown?wxT("Down"):wxT("UP") );
 
1241
    #endif
 
1242
    if (not m_MouseCtrlKeyDown) {event.Skip(); return;}
 
1243
 
 
1244
    int nRotation = event.GetWheelRotation();
 
1245
    wxFont ctrlFont = GetFont();
 
1246
 
 
1247
    if ( nRotation > 0)
 
1248
        ctrlFont.SetPointSize( ctrlFont.GetPointSize()-1);
 
1249
    else
 
1250
        ctrlFont.SetPointSize( ctrlFont.GetPointSize()+1);
 
1251
 
 
1252
    SetFont(ctrlFont);
 
1253
    return;
 
1254
}
 
1255
// ----------------------------------------------------------------------------
 
1256
#if defined(__WXMSW__)
 
1257
void CodeSnippetsTreeCtrl::MSW_MouseMove(int x, int y )
 
1258
// ----------------------------------------------------------------------------
 
1259
{
 
1260
    // Move mouse uses a very strange coordinate system.
 
1261
    // It uses screen positions with a range of 0 to 65535
 
1262
 
 
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);
 
1268
      INPUT  Input={0};
 
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));
 
1274
}
 
1275
#endif
 
1276
// ----------------------------------------------------------------------------
 
1277
wxTreeItemId CodeSnippetsTreeCtrl::ConvertSnippetToCategory(wxTreeItemId itemId)
 
1278
// ----------------------------------------------------------------------------
 
1279
{
 
1280
    // Convert Snippet to Category, then insert the old snippet
 
1281
    wxTreeItemId badItemId = (void*)0;
 
1282
 
 
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);
 
1289
 
 
1290
        // create Xml document from selected tree item
 
1291
    TiXmlDocument* pDoc = CopyTreeNodeToXmlDoc( oldItemId );
 
1292
    if (not pDoc) return badItemId;
 
1293
 
 
1294
    // Create new Category
 
1295
    wxTreeItemId newCategoryId = AddCategory( itemParent,
 
1296
                GetItemText(oldItemId), GetSnippetID(oldItemId), false );
 
1297
 
 
1298
    // Insert old Snippet Item under new Category
 
1299
    TiXmlElement* root = pDoc->RootElement();
 
1300
    if (root)
 
1301
    {
 
1302
            // Get the first xml element
 
1303
        TiXmlElement* firstChild = root->FirstChildElement("item");
 
1304
        if (firstChild)
 
1305
        {   // insert Tree items from xml document
 
1306
            //-LoadSnippets(firstChild, newCategoryId);
 
1307
            LoadItemsFromXmlNode( firstChild, newCategoryId);
 
1308
 
 
1309
        }
 
1310
    }
 
1311
        // remove the old tree item
 
1312
    RemoveItem( oldItemId );
 
1313
    delete pDoc; pDoc = 0;
 
1314
    return newCategoryId;
 
1315
}
 
1316
// ----------------------------------------------------------------------------
 
1317
TiXmlDocument* CodeSnippetsTreeCtrl::CopyTreeNodeToXmlDoc(wxTreeItemId TreeItemId  )
 
1318
// ----------------------------------------------------------------------------
 
1319
{
 
1320
    // Copy a Tree node to an Xml Document
 
1321
 
 
1322
    wxTreeItemId itemId = TreeItemId;
 
1323
    if (not itemId.IsOk() )
 
1324
    {
 
1325
        itemId = GetSelection();
 
1326
    }
 
1327
    if (not itemId.IsOk()) return NULL;
 
1328
 
 
1329
        TiXmlDocument* pDoc = new TiXmlDocument;
 
1330
        TiXmlDeclaration header("1.0", "UTF-8", "yes");
 
1331
        pDoc->InsertEndChild(header);
 
1332
 
 
1333
        TiXmlElement snippetsElement("snippets");
 
1334
        CopySnippetsToXmlDoc(&snippetsElement, itemId);
 
1335
 
 
1336
        pDoc->InsertEndChild(snippetsElement);
 
1337
 
 
1338
        return pDoc;
 
1339
 
 
1340
} // end of SaveSnippetsToFile
 
1341
// ----------------------------------------------------------------------------
 
1342
void CodeSnippetsTreeCtrl::CopySnippetsToXmlDoc(TiXmlNode* Node, const wxTreeItemId& itemID)
 
1343
// ----------------------------------------------------------------------------
 
1344
{
 
1345
    // Recursively copy Tree item and all its children to an Xml document node
 
1346
 
 
1347
        wxTreeItemIdValue cookie;
 
1348
        //wxTreeItemId item = GetFirstChild(parentID, cookie );
 
1349
    wxTreeItemId item = itemID;
 
1350
 
 
1351
        // Loop through all items
 
1352
        while(item.IsOk())
 
1353
        {
 
1354
                // Get the item's information
 
1355
                const SnippetItemData* data = (SnippetItemData*)GetItemData(item);
 
1356
 
 
1357
                if (!data)
 
1358
                        return;
 
1359
 
 
1360
                // Begin item element
 
1361
                TiXmlElement element("item");
 
1362
 
 
1363
                // Write the item's name
 
1364
                element.SetAttribute("name", GetItemText(item).mb_str());
 
1365
 
 
1366
                // Write the type of the item
 
1367
                switch (data->GetType())
 
1368
                {
 
1369
                        case SnippetItemData::TYPE_CATEGORY:
 
1370
                                element.SetAttribute("type", "category");
 
1371
                        break;
 
1372
 
 
1373
                        case SnippetItemData::TYPE_SNIPPET:
 
1374
                                element.SetAttribute("type", "snippet");
 
1375
                        break;
 
1376
 
 
1377
                        default:
 
1378
                        break;
 
1379
                }
 
1380
 
 
1381
                // And the snippet
 
1382
                if (data->GetType() == SnippetItemData::TYPE_SNIPPET)
 
1383
                {
 
1384
                        TiXmlElement snippetElement("snippet");
 
1385
                        TiXmlText snippetElementText(data->GetSnippet().mb_str());
 
1386
            snippetElement.InsertEndChild(snippetElementText);
 
1387
                        element.InsertEndChild(snippetElement);
 
1388
                        //#ifdef LOGGING
 
1389
                        // LOGIT( _T("Snippet[%s]"), data->GetSnippet().GetData() );
 
1390
                        //#endif //LOGGING
 
1391
                }
 
1392
 
 
1393
                // Check if this item has children
 
1394
                if(ItemHasChildren(item))
 
1395
                {
 
1396
                        // If it has, check those too
 
1397
                        //-SaveSnippets(&element, item);
 
1398
                        SaveItemsToXmlNode(&element, item);
 
1399
                }
 
1400
 
 
1401
                // Insert the item we created as parent node's child
 
1402
                //parentNode->InsertEndChild(element);
 
1403
                Node->InsertEndChild(element);
 
1404
 
 
1405
                // Check the next child
 
1406
                item = GetNextChild( itemID, cookie);
 
1407
        }
 
1408
}//CopySnippetsToXmlDoc
 
1409
// ----------------------------------------------------------------------------
 
1410
void CodeSnippetsTreeCtrl::CopyXmlDocToTreeNode(TiXmlDocument* pTiXmlDoc, wxTreeItemId targetItem  )
 
1411
// ----------------------------------------------------------------------------
 
1412
{
 
1413
    TiXmlElement* root = pTiXmlDoc->RootElement();
 
1414
    if (root)
 
1415
    {
 
1416
        // Get the source xml element
 
1417
        TiXmlElement* firstChild = root->FirstChildElement("item");
 
1418
        if (firstChild)
 
1419
        {   // insert into target Tree items from source xml document
 
1420
            LoadItemsFromXmlNode( firstChild, targetItem);
 
1421
        }
 
1422
    }
 
1423
 
 
1424
}
 
1425
// ----------------------------------------------------------------------------
 
1426
void CodeSnippetsTreeCtrl::EditSnippetAsFileLink()
 
1427
// ----------------------------------------------------------------------------
 
1428
{
 
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.
 
1431
 
 
1432
    #if defined(LOGGING)
 
1433
    LOGIT( _T("EditSnippetAsFileLink[%s]"),wxT("") );
 
1434
    #endif
 
1435
 
 
1436
    if (not IsSnippet() ) return;
 
1437
 
 
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() );
 
1443
 
 
1444
    if (FileName.Length() > 128)
 
1445
    {   // if text is > 128 characters, open a temp file with snippet text as data.
 
1446
        EditSnippetAsText();
 
1447
        return;
 
1448
    }
 
1449
 
 
1450
 
 
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();
 
1456
        return;
 
1457
    }
 
1458
 
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() );
1255
 
 
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)) )
1259
 
        {
1260
 
            EditSnippet( pSnippetItemData, FileName);
1261
 
            return;
1262
 
        }
1263
 
 
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("\"");
1268
 
        #ifdef LOGGING
1269
 
        LOGIT( _T("OpenAsFileLink[%s]"), execString.GetData() );
1270
 
        #endif //LOGGING
1271
 
        ::wxExecute( execString);
1272
 
    }
1273
 
 
1274
 
    return;
1275
 
}
1276
 
// ----------------------------------------------------------------------------
1277
 
void CodeSnippetsTreeCtrl::OpenSnippetAsFileLink()
1278
 
// ----------------------------------------------------------------------------
1279
 
{
1280
 
    // Open snippet text as a file name. Ie, the first text line should contain a filename.
1281
 
 
1282
 
    if (not IsSnippet() ) return;
1283
 
 
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() );
1288
 
 
1289
 
    if (FileName.Length() > 128)
1290
 
    {   // if text is > 128 characters, open a temp file with snippet text as data.
1291
 
        EditSnippetAsText();
1292
 
        return;
1293
 
    }
1294
 
 
1295
 
    // user requested "MIME" type to open file
1296
 
    EditSnippetWithMIME();
1297
 
 
1298
 
    return;
1299
 
}
1300
 
// ----------------------------------------------------------------------------
1301
 
void CodeSnippetsTreeCtrl::EditSnippetAsText()
1302
 
// ----------------------------------------------------------------------------
1303
 
{
1304
 
 
1305
 
    #if defined(LOGGING)
1306
 
    LOGIT( _T("EditSnippetAsText[%s]"),wxT("") );
1307
 
    #endif
1308
 
        SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
1309
 
 
1310
 
    // if no user specified editor, use default editor
1311
 
    wxString editorName = GetConfig()->SettingsExternalEditor ;
1312
 
    if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1313
 
    {
1314
 
        EditSnippet( pSnippetItemData );
1315
 
        return;
1316
 
    }
1317
 
 
1318
 
    if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
1319
 
    {
1320
 
        #if defined(__WXMSW__)
1321
 
                editorName = wxT("notepad");
1322
 
        #elif defined(__UNIX__)
1323
 
                editorName = wxT("vi");
1324
 
        #endif
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");
1329
 
        messageBox( msg );
1330
 
    }
1331
 
 
1332
 
    // let user edit the snippet text
1333
 
    // write text to temp file
1334
 
    // invoke the editor
1335
 
    // read text back into snippet
1336
 
 
1337
 
    wxFileName tmpFileName = wxFileName::CreateTempFileName(wxEmptyString);
1338
 
 
1339
 
    wxFile tmpFile( tmpFileName.GetFullPath(), wxFile::write);
1340
 
    if (not tmpFile.IsOpened() )
1341
 
    {
1342
 
        messageBox(wxT("Open failed for:")+tmpFileName.GetFullPath());
1343
 
        return ;
1344
 
    }
1345
 
    wxString snippetData( GetSnippet() );
1346
 
    tmpFile.Write( csU2C(snippetData), snippetData.Length());
1347
 
    tmpFile.Close();
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("\"");
1351
 
 
1352
 
    #ifdef LOGGING
1353
 
     LOGIT( _T("Properties wxExecute[%s]"), execString.GetData() );
1354
 
    #endif //LOGGING
1355
 
 
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."));
1362
 
        return;
1363
 
    }
1364
 
    unsigned long fileSize = tmpFile.Length();
1365
 
 
1366
 
    #ifdef LOGGING
1367
 
     LOGIT( _T("New file size[%d]"),fileSize );
1368
 
    #endif //LOGGING
1369
 
 
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"));
1375
 
    pBuf[fileSize] = 0;
1376
 
    tmpFile.Close();
1377
 
 
1378
 
    #ifdef LOGGING
1379
 
      //LOGIT( _T("pBuf[%s]"), pBuf );
1380
 
    #endif //LOGGING
1381
 
 
1382
 
        // convert data back to internal format
1383
 
    snippetData = csC2U( pBuf );
1384
 
 
1385
 
     #ifdef LOGGING
1386
 
      //LOGIT( _T("snippetData[%s]"), snippetData.GetData() );
1387
 
     #endif //LOGGING
1388
 
 
1389
 
        // delete the temporary file
1390
 
    ::wxRemoveFile( tmpFileName.GetFullPath() );
1391
 
 
1392
 
        // update Tree item
1393
 
    SetSnippet( snippetData );
1394
 
 
1395
 
    return;
1396
 
}//EditSnippetAsText
1397
 
// ----------------------------------------------------------------------------
1398
 
void CodeSnippetsTreeCtrl::SaveSnippetAsFileLink()
1399
 
// ----------------------------------------------------------------------------
1400
 
{
1401
 
    wxTreeItemId itemId = GetAssociatedItemID();
1402
 
    if (not itemId.IsOk()) return;
1403
 
 
1404
 
    if ( not IsSnippet()) return;
1405
 
 
1406
 
    // Dump the snippet text to file, then place the filename in the snippet text area
1407
 
 
1408
 
    // Dump Snippet field into a temporary file
1409
 
    wxString snippetLabel = GetSnippetLabel();
1410
 
    wxString snippetData = GetSnippet();
1411
 
    wxString fileName = GetSnippetFileLink();
1412
 
 
1413
 
    int answer = wxYES;
1414
 
 
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."));
1427
 
                return;
1428
 
            }
1429
 
            unsigned long fileSize = oldFile.Length();
1430
 
            char* pBuf = new char[fileSize+1];
1431
 
            oldFile.Read( pBuf, fileSize );
1432
 
            pBuf[fileSize] = 0;
1433
 
            snippetData = csC2U(  pBuf );
1434
 
            oldFile.Close();
1435
 
            delete [] pBuf;
1436
 
        }
1437
 
    }
1438
 
    if ( wxNO == answer ) return;
1439
 
 
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() );
1447
 
    #endif
1448
 
 
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);
1453
 
        //#ifdef LOGGING
1454
 
        // LOGIT( _T("forbidden[%s],filename[%s]"), forbidden.GetData(),newFileName.GetData());
1455
 
        //#endif //LOGGING
1456
 
 
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;
1468
 
 
1469
 
    newFileName = dlg.GetPath();
1470
 
 
1471
 
    #ifdef LOGGING
1472
 
     LOGIT( _T("New filename[%s]"), newFileName.GetData() );
1473
 
    #endif //LOGGING;
1474
 
 
1475
 
    if ( newFileName.IsEmpty() ) return;
1476
 
    // Verify filename, or create
1477
 
    wxFile newFile( newFileName, wxFile::write);
1478
 
    if (not newFile.IsOpened() )
1479
 
    {
1480
 
        messageBox(wxT("Open failed for:")+newFileName);
1481
 
        return ;
1482
 
    }
1483
 
    newFile.Write( csU2C(snippetData), snippetData.Length());
1484
 
    newFile.Close();
1485
 
    // update Tree item
1486
 
    SetSnippet( newFileName );
1487
 
 
1488
 
    // verify the item tree image
1489
 
    if ( IsFileSnippet() )
1490
 
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
1491
 
    else
1492
 
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
1493
 
 
1494
 
    return;
1495
 
}//OnMnuSaveAsFile
1496
 
// ----------------------------------------------------------------------------
1497
 
bool CodeSnippetsTreeCtrl::EditSnippetProperties(wxTreeItemId& itemId)
1498
 
// ----------------------------------------------------------------------------
1499
 
{
1500
 
    if ( not IsSnippet(itemId) ) return false;
1501
 
 
1502
 
    int result = 0;
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 )
1508
 
        {
1509
 
        // verify the item tree image
1510
 
        SetSnippetImage(itemId);
1511
 
        }
1512
 
    if (result == wxID_OK) {
1513
 
        SetFileChanged(true);
1514
 
    }
1515
 
    pdlg->Destroy();
1516
 
    return (result = (result==wxID_OK));
1517
 
}
1518
 
 
1519
 
// ----------------------------------------------------------------------------
1520
 
void CodeSnippetsTreeCtrl::EditSnippet(SnippetItemData* pSnippetItemData, wxString fileName)
1521
 
// ----------------------------------------------------------------------------
1522
 
{
 
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() );
 
1464
    #endif
 
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)) )
 
1468
        {
 
1469
            EditSnippet( pSnippetItemData, FileName);
 
1470
            return;
 
1471
        }
 
1472
 
 
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("\"");
 
1477
        #ifdef LOGGING
 
1478
        LOGIT( _T("OpenAsFileLink[%s]"), execString.GetData() );
 
1479
        #endif //LOGGING
 
1480
        ::wxExecute( execString);
 
1481
    }
 
1482
 
 
1483
    return;
 
1484
}
 
1485
// ----------------------------------------------------------------------------
 
1486
void CodeSnippetsTreeCtrl::OpenSnippetAsFileLink()
 
1487
// ----------------------------------------------------------------------------
 
1488
{
 
1489
    // Open snippet text as a file name. Ie, the first text line should contain a filename.
 
1490
 
 
1491
    if (not IsSnippet() ) return;
 
1492
 
 
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() );
 
1497
 
 
1498
    if (FileName.Length() > 128)
 
1499
    {   // if text is > 128 characters, open a temp file with snippet text as data.
 
1500
        EditSnippetAsText();
 
1501
        return;
 
1502
    }
 
1503
 
 
1504
    // user requested "MIME" type to open file
 
1505
    EditSnippetWithMIME();
 
1506
 
 
1507
    return;
 
1508
}
 
1509
// ----------------------------------------------------------------------------
 
1510
void CodeSnippetsTreeCtrl::EditSnippetAsText()
 
1511
// ----------------------------------------------------------------------------
 
1512
{
 
1513
 
 
1514
    #if defined(LOGGING)
 
1515
    LOGIT( _T("EditSnippetAsText[%s]"),wxT("") );
 
1516
    #endif
 
1517
        SnippetItemData* pSnippetItemData = (SnippetItemData*)GetItemData(GetAssociatedItemID());
 
1518
 
 
1519
    // if no user specified editor, use default editor
 
1520
    wxString editorName = GetConfig()->SettingsExternalEditor ;
 
1521
    if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
 
1522
    {
 
1523
        EditSnippet( pSnippetItemData );
 
1524
        return;
 
1525
    }
 
1526
 
 
1527
    if ( editorName.IsEmpty() || (not ::wxFileExists(editorName)) )
 
1528
    {
 
1529
        #if defined(__WXMSW__)
 
1530
                editorName = wxT("notepad");
 
1531
        #elif defined(__UNIX__)
 
1532
                editorName = wxT("vi");
 
1533
        #endif
 
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 );
 
1539
    }
 
1540
 
 
1541
    // let user edit the snippet text
 
1542
    // write text to temp file
 
1543
    // invoke the editor
 
1544
    // read text back into snippet
 
1545
 
 
1546
    wxFileName tmpFileName = wxFileName::CreateTempFileName(wxEmptyString);
 
1547
 
 
1548
    wxFile tmpFile( tmpFileName.GetFullPath(), wxFile::write);
 
1549
    if (not tmpFile.IsOpened() )
 
1550
    {
 
1551
        GenericMessageBox(wxT("Open failed for:")+tmpFileName.GetFullPath());
 
1552
        return ;
 
1553
    }
 
1554
    wxString snippetData( GetSnippet() );
 
1555
    tmpFile.Write( csU2C(snippetData), snippetData.Length());
 
1556
    tmpFile.Close();
 
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("\"");
 
1560
 
 
1561
    #ifdef LOGGING
 
1562
     LOGIT( _T("Properties wxExecute[%s]"), execString.GetData() );
 
1563
    #endif //LOGGING
 
1564
 
 
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."));
 
1571
        return;
 
1572
    }
 
1573
    unsigned long fileSize = tmpFile.Length();
 
1574
 
 
1575
    #ifdef LOGGING
 
1576
     LOGIT( _T("New file size[%d]"),fileSize );
 
1577
    #endif //LOGGING
 
1578
 
 
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"));
 
1584
    pBuf[fileSize] = 0;
 
1585
    tmpFile.Close();
 
1586
 
 
1587
    #ifdef LOGGING
 
1588
      //LOGIT( _T("pBuf[%s]"), pBuf );
 
1589
    #endif //LOGGING
 
1590
 
 
1591
        // convert data back to internal format
 
1592
    snippetData = csC2U( pBuf );
 
1593
 
 
1594
     #ifdef LOGGING
 
1595
      //LOGIT( _T("snippetData[%s]"), snippetData.GetData() );
 
1596
     #endif //LOGGING
 
1597
 
 
1598
        // delete the temporary file
 
1599
    ::wxRemoveFile( tmpFileName.GetFullPath() );
 
1600
 
 
1601
        // update Tree item
 
1602
    SetSnippet( snippetData );
 
1603
 
 
1604
    return;
 
1605
}//EditSnippetAsText
 
1606
// ----------------------------------------------------------------------------
 
1607
void CodeSnippetsTreeCtrl::SaveSnippetAsFileLink()
 
1608
// ----------------------------------------------------------------------------
 
1609
{
 
1610
    wxTreeItemId itemId = GetAssociatedItemID();
 
1611
    if (not itemId.IsOk()) return;
 
1612
 
 
1613
    if ( not IsSnippet()) return;
 
1614
 
 
1615
    // Dump the snippet text to file, then place the filename in the snippet text area
 
1616
 
 
1617
    // Dump Snippet field into a temporary file
 
1618
    wxString snippetLabel = GetSnippetLabel();
 
1619
    wxString snippetData = GetSnippet();
 
1620
    wxString fileName = GetSnippetFileLink();
 
1621
 
 
1622
    int answer = wxYES;
 
1623
 
 
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."));
 
1636
                return;
 
1637
            }
 
1638
            unsigned long fileSize = oldFile.Length();
 
1639
            char* pBuf = new char[fileSize+1];
 
1640
            oldFile.Read( pBuf, fileSize );
 
1641
            pBuf[fileSize] = 0;
 
1642
            snippetData = csC2U(  pBuf );
 
1643
            oldFile.Close();
 
1644
            delete [] pBuf;
 
1645
        }
 
1646
    }
 
1647
    if ( wxNO == answer ) return;
 
1648
 
 
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() );
 
1658
    //-#endif
 
1659
 
 
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);
 
1664
        //#ifdef LOGGING
 
1665
        // LOGIT( _T("forbidden[%s],filename[%s]"), forbidden.GetData(),newFileName.GetData());
 
1666
        //#endif //LOGGING
 
1667
 
 
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;
 
1679
 
 
1680
    newFileName = dlg.GetPath();
 
1681
 
 
1682
    #ifdef LOGGING
 
1683
     LOGIT( _T("New filename[%s]"), newFileName.GetData() );
 
1684
    #endif //LOGGING;
 
1685
 
 
1686
    if ( newFileName.IsEmpty() ) return;
 
1687
    // Verify filename, or create
 
1688
    wxFile newFile( newFileName, wxFile::write);
 
1689
    if (not newFile.IsOpened() )
 
1690
    {
 
1691
        GenericMessageBox(wxT("Open failed for:")+newFileName);
 
1692
        return ;
 
1693
    }
 
1694
    newFile.Write( csU2C(snippetData), snippetData.Length());
 
1695
    newFile.Close();
 
1696
    // update Tree item
 
1697
    SetSnippet( newFileName );
 
1698
 
 
1699
    // verify the item tree image
 
1700
    if ( IsFileSnippet() )
 
1701
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_FILE);
 
1702
    else
 
1703
        SetItemImage( itemId, TREE_IMAGE_SNIPPET_TEXT);
 
1704
 
 
1705
    return;
 
1706
}//OnMnuSaveAsFile
 
1707
// ----------------------------------------------------------------------------
 
1708
bool CodeSnippetsTreeCtrl::EditSnippetProperties(wxTreeItemId& itemId)
 
1709
// ----------------------------------------------------------------------------
 
1710
{
 
1711
    if ( not IsSnippet(itemId) ) return false;
 
1712
 
 
1713
    int result = 0;
 
1714
    wxSemaphore waitSem;
 
1715
    SnippetProperty* pdlg = new SnippetProperty(GetSnippetsTreeCtrl(), itemId, &waitSem);
 
1716
 
 
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 );
 
1721
 
 
1722
    result = ExecuteDialog(pdlg, waitSem);
 
1723
    // Save any changed data
 
1724
        if ( result == wxID_OK )
 
1725
        {
 
1726
        // verify the item tree image
 
1727
        SetSnippetImage(itemId);
 
1728
        }
 
1729
    if (result == wxID_OK) {
 
1730
        SetFileChanged(true);
 
1731
    }
 
1732
 
 
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 );
 
1737
 
 
1738
    pdlg->Destroy();
 
1739
    return (result = (result==wxID_OK));
 
1740
}
 
1741
// ----------------------------------------------------------------------------
 
1742
void CodeSnippetsTreeCtrl::EditSnippet(SnippetItemData* pSnippetItemData, wxString fileName)
 
1743
// ----------------------------------------------------------------------------
 
1744
{
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);
 
1746
 
 
1747
    Utils utils;
 
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))
 
1753
            continue;
 
1754
 
 
1755
        if ( pesf->GetSnippetId() == GetAssociatedItemID() )
1529
1756
        {
1530
 
            m_aDlgPtrs.Item(i)->Iconize(false);
1531
 
            m_aDlgPtrs.Item(i)->SetFocus();
1532
 
            return;
1533
 
        }
 
1757
            // if return code has been set, this frame is set to terminate
 
1758
            if ( (int)m_aDlgRetcodes.GetCount() < i)
 
1759
                continue;
 
1760
            if ( m_aDlgRetcodes.Item(i) not_eq 0)
 
1761
                continue;
 
1762
            m_aDlgPtrs.Item(i)->Iconize(false);
 
1763
            m_aDlgPtrs.Item(i)->SetFocus();
 
1764
            return;
 
1765
        }
1534
1766
    }//for
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();
1540
 
 
 
1767
 
 
1768
    // Create editor for snippet item
 
1769
    if (SnippetItemData* itemData = (SnippetItemData*)( GetItemData(GetAssociatedItemID() )))
 
1770
    {
 
1771
        wxString snippetText = itemData->GetSnippet();
 
1772
        m_aDlgRetcodes.Add(0);          // new slot for return code
 
1773
        int* pRetcode = &m_aDlgRetcodes.Last();
 
1774
 
1541
1775
        EditSnippetFrame* pdlg = new EditSnippetFrame( GetAssociatedItemID(), pRetcode );
1542
 
        // cascade multiple editors
1543
 
        int knt = m_aDlgPtrs.GetCount();
1544
 
        if (pdlg && (knt > 0) ){
1545
 
            int x,y;
1546
 
            pdlg->GetPosition(&x, &y );
1547
 
             if (0 == x){
1548
 
                pdlg->ClientToScreen(&x, &y );
1549
 
             }
1550
 
            knt = knt<<5;
1551
 
            pdlg->Move(x+knt,y+knt);
1552
 
        }
1553
 
 
1554
 
        if ( pdlg->Show() )
1555
 
        {
1556
 
            m_aDlgPtrs.Add((wxDialog*)pdlg);
1557
 
        }
1558
 
        else
1559
 
            m_aDlgRetcodes.RemoveAt(m_aDlgRetcodes.GetCount());
1560
 
 
1561
 
        }//if
1562
 
}//EditSnippet
1563
 
 
1564
 
// ----------------------------------------------------------------------------
1565
 
void CodeSnippetsTreeCtrl::EditSnippetWithMIME()
1566
 
// ----------------------------------------------------------------------------
1567
 
{
1568
 
    wxTreeItemId itemId = GetAssociatedItemID();
1569
 
    if (not itemId.IsOk()) return;
1570
 
    if ( not IsSnippet()) return;
1571
 
 
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;
1577
 
 
1578
 
    wxFileName file(fileName);
1579
 
    wxString fileExt = file.GetExt();
1580
 
 
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") )
1587
 
       )
1588
 
    {   wxLaunchDefaultBrowser( fileName);
1589
 
        return;
1590
 
    }
1591
 
 
1592
 
    if ( not ::wxFileExists(fileName) ) return;
1593
 
 
1594
 
    wxString fileNameExt;
1595
 
    ::wxSplitPath( fileName, /*path*/0, /*name*/0, &fileNameExt);
1596
 
    if ( fileNameExt.IsEmpty() ) return;
1597
 
 
1598
 
    wxString s_defaultExt = _T("xyz");
1599
 
    wxString msg;
1600
 
 
1601
 
    if ( !!fileNameExt )
1602
 
    {
1603
 
        s_defaultExt = fileNameExt;
1604
 
 
1605
 
        // init MIME database if not done yet
1606
 
        if ( !m_mimeDatabase )
1607
 
        {
1608
 
            ////m_mimeDatabase = new wxMimeTypesManager;
1609
 
            // use global pointer instead of above instantiation
1610
 
            m_mimeDatabase = wxTheMimeTypesManager;
1611
 
 
1612
 
            ////static const wxFileTypeInfo fallbacks[] =
1613
 
            ////{
1614
 
            ////    wxFileTypeInfo(_T("application/xyz"),
1615
 
            ////                   _T("XyZ %s"),
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"),
1620
 
            ////                   _T("lynx %s"),
1621
 
            ////                   _T("lynx -dump %s | lpr"),
1622
 
            ////                   _T("HTML document (from fallback)"),
1623
 
            ////                   _T("htm"), _T("html"), NULL),
1624
 
            ////
1625
 
            ////    // must terminate the table with this!
1626
 
            ////    wxFileTypeInfo()
1627
 
            ////};
1628
 
            ////
1629
 
            ////m_mimeDatabase->AddFallbacks(fallbacks);
1630
 
        }//if
1631
 
 
1632
 
        wxFileType *filetype = m_mimeDatabase->GetFileTypeFromExtension(fileNameExt);
1633
 
        if ( !filetype )
1634
 
        {
1635
 
            msg << _T("Unknown extension '") << fileNameExt << _T("'\n");
1636
 
        }
1637
 
        else
1638
 
        {
1639
 
            wxString type, desc, open;
1640
 
            filetype->GetMimeType(&type);
1641
 
            filetype->GetDescription(&desc);
1642
 
 
1643
 
            //wxString filename = _T("filename");
1644
 
            wxString filename = fileName;
1645
 
            //filename << _T(".") << fileNameExt;
1646
 
            wxFileType::MessageParameters params(filename, type);
1647
 
            filetype->GetOpenCommand(&open, params);
1648
 
 
1649
 
           #if LOGGING
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() )
1654
 
                        << _T('\n')
1655
 
                     << _T("\tCommand to open: ") << ( !open ? wxT("no") : open.c_str() )
1656
 
                        << _T('\n');
1657
 
           #endif
1658
 
 
1659
 
            delete filetype;
1660
 
            if ( open )
1661
 
                ::wxExecute( open, wxEXEC_ASYNC);
1662
 
        }
1663
 
    }
1664
 
    #ifdef LOGGING
1665
 
        LOGIT( _T("EditSnippetWithMIME()[%s]"),msg.c_str() );
1666
 
    #endif //LOGGING
1667
 
 
1668
 
    // Do not use these when using global wxTheMimeTypesManager pointer
1669
 
    ////if ( m_mimeDatabase ) delete m_mimeDatabase;
1670
 
    ////m_mimeDatabase = 0;
1671
 
 
1672
 
    return;
1673
 
}
1674
 
// ----------------------------------------------------------------------------
1675
 
int CodeSnippetsTreeCtrl::ExecuteDialog(wxDialog* pdlg, wxSemaphore& waitSem)
1676
 
// ----------------------------------------------------------------------------
1677
 
{
1678
 
    if (m_pPropertiesDialog) return 0;
1679
 
 
1680
 
    m_pPropertiesDialog = pdlg;
1681
 
    int retcode = 0;
1682
 
 
1683
 
    wxWindow* pw = this;
1684
 
    if (pw && pw->GetParent()) //
1685
 
    {   pw = pw->GetParent();
1686
 
    }
1687
 
    if (pw && pw->GetParent())  //This is the SnippetWindow parent
1688
 
    {   pw = pw->GetParent();
1689
 
    }
1690
 
 
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);
1695
 
 
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);
1700
 
 
 
1776
 
 
1777
        // cascade multiple editors
 
1778
        int knt = m_aDlgPtrs.GetCount();
 
1779
        if (pdlg && (knt > 0) ){
 
1780
            int x,y;
 
1781
            pdlg->GetPosition(&x, &y );
 
1782
             if (0 == x){
 
1783
                pdlg->ClientToScreen(&x, &y );
 
1784
             }
 
1785
            knt = knt<<5;
 
1786
            pdlg->Move(x+knt,y+knt);
 
1787
        }
 
1788
 
 
1789
        if ( pdlg->Show() )
 
1790
        {
 
1791
            m_aDlgPtrs.Add((wxScrollingDialog*)pdlg);
 
1792
        }
 
1793
        else
 
1794
            m_aDlgRetcodes.RemoveAt(m_aDlgRetcodes.GetCount());
 
1795
 
 
1796
        }//if
 
1797
}//EditSnippet
 
1798
 
 
1799
// ----------------------------------------------------------------------------
 
1800
void CodeSnippetsTreeCtrl::EditSnippetWithMIME()
 
1801
// ----------------------------------------------------------------------------
 
1802
{
 
1803
    wxTreeItemId itemId = GetAssociatedItemID();
 
1804
    if (not itemId.IsOk()) return;
 
1805
    if ( not IsSnippet()) return;
 
1806
 
 
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;
 
1812
 
 
1813
    wxFileName file(fileName);
 
1814
    wxString fileExt = file.GetExt();
 
1815
 
 
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") )
 
1822
       )
 
1823
    {   wxLaunchDefaultBrowser( fileName);
 
1824
        return;
 
1825
    }
 
1826
 
 
1827
    if ( not ::wxFileExists(fileName) ) return;
 
1828
 
 
1829
    wxString fileNameExt;
 
1830
    #if wxCHECK_VERSION(2, 9, 0)
 
1831
    wxFileName::SplitPath( fileName, /*volume*/0, /*path*/0, /*name*/0, &fileNameExt);
 
1832
    #else
 
1833
    ::wxSplitPath( fileName, /*path*/0, /*name*/0, &fileNameExt);
 
1834
    #endif
 
1835
    if ( fileNameExt.IsEmpty() ) return;
 
1836
 
 
1837
    wxString s_defaultExt = _T("xyz");
 
1838
    wxString msg;
 
1839
 
 
1840
    if ( !!fileNameExt )
 
1841
    {
 
1842
        s_defaultExt = fileNameExt;
 
1843
 
 
1844
        // init MIME database if not done yet
 
1845
        if ( !m_mimeDatabase )
 
1846
        {
 
1847
            ////m_mimeDatabase = new wxMimeTypesManager;
 
1848
            // use global pointer instead of above instantiation
 
1849
            m_mimeDatabase = wxTheMimeTypesManager;
 
1850
 
 
1851
            ////static const wxFileTypeInfo fallbacks[] =
 
1852
            ////{
 
1853
            ////    wxFileTypeInfo(_T("application/xyz"),
 
1854
            ////                   _T("XyZ %s"),
 
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"),
 
1859
            ////                   _T("lynx %s"),
 
1860
            ////                   _T("lynx -dump %s | lpr"),
 
1861
            ////                   _T("HTML document (from fallback)"),
 
1862
            ////                   _T("htm"), _T("html"), NULL),
 
1863
            ////
 
1864
            ////    // must terminate the table with this!
 
1865
            ////    wxFileTypeInfo()
 
1866
            ////};
 
1867
            ////
 
1868
            ////m_mimeDatabase->AddFallbacks(fallbacks);
 
1869
        }//if
 
1870
 
 
1871
        wxFileType *filetype = m_mimeDatabase->GetFileTypeFromExtension(fileNameExt);
 
1872
        if ( !filetype )
 
1873
        {
 
1874
            msg << _T("Unknown extension '") << fileNameExt << _T("'\n");
 
1875
        }
 
1876
        else
 
1877
        {
 
1878
            wxString type, desc, open;
 
1879
            filetype->GetMimeType(&type);
 
1880
            filetype->GetDescription(&desc);
 
1881
 
 
1882
            //wxString filename = _T("filename");
 
1883
            wxString filename = fileName;
 
1884
            //filename << _T(".") << fileNameExt;
 
1885
            wxFileType::MessageParameters params(filename, type);
 
1886
            filetype->GetOpenCommand(&open, params);
 
1887
 
 
1888
           #if LOGGING
 
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() )
 
1893
                        << _T('\n')
 
1894
                     << _T("\tCommand to open: ") << ( !open ? wxT("no") : open.c_str() )
 
1895
                        << _T('\n');
 
1896
           #endif
 
1897
 
 
1898
            delete filetype;
 
1899
            #if wxCHECK_VERSION(2, 9, 0)
 
1900
            if ( !open.IsEmpty() )
 
1901
            #else
 
1902
            if ( open )
 
1903
            #endif
 
1904
                ::wxExecute( open, wxEXEC_ASYNC);
 
1905
        }
 
1906
    }
 
1907
    #ifdef LOGGING
 
1908
        LOGIT( _T("EditSnippetWithMIME()[%s]"),msg.c_str() );
 
1909
    #endif //LOGGING
 
1910
 
 
1911
    // Do not use these when using global wxTheMimeTypesManager pointer
 
1912
    ////if ( m_mimeDatabase ) delete m_mimeDatabase;
 
1913
    ////m_mimeDatabase = 0;
 
1914
 
 
1915
    return;
 
1916
}
 
1917
// ----------------------------------------------------------------------------
 
1918
int CodeSnippetsTreeCtrl::ExecuteDialog(wxScrollingDialog* pdlg, wxSemaphore& waitSem)
 
1919
// ----------------------------------------------------------------------------
 
1920
{
 
1921
    if (m_pPropertiesDialog) return 0;
 
1922
 
 
1923
    m_pPropertiesDialog = pdlg;
 
1924
    int retcode = 0;
 
1925
 
 
1926
    wxWindow* pw = this;
 
1927
    if (pw && pw->GetParent()) //
 
1928
    {   pw = pw->GetParent();
 
1929
    }
 
1930
    if (pw && pw->GetParent())  //This is the SnippetWindow parent
 
1931
    {   pw = pw->GetParent();
 
1932
    }
 
1933
 
 
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);
 
1938
 
 
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);
 
1943
 
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);
1705
 
 
1706
 
        if ( pdlg->Show() )
1707
 
        {
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);
1712
 
                wxYield();
1713
 
            }
1714
 
            retcode = pdlg->GetReturnCode();
1715
 
        }
1716
 
        // Release main apps closeWindow function
1717
 
        GetConfig()->GetMainFrame()->Disconnect( wxEVT_CLOSE_WINDOW,
1718
 
            (wxObjectEventFunction)(wxEventFunction)
1719
 
            (wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1720
 
 
1721
 
        // Release parents closeWindow function
1722
 
        pw->Disconnect( wxEVT_CLOSE_WINDOW,
1723
 
            (wxObjectEventFunction)(wxEventFunction)
1724
 
            (wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
1725
 
 
 
1948
 
 
1949
        if ( pdlg->Show() )
 
1950
        {
 
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);
 
1955
                wxYield();
 
1956
            }
 
1957
            retcode = pdlg->GetReturnCode();
 
1958
        }
 
1959
        // Release main apps closeWindow function
 
1960
        GetConfig()->GetMainFrame()->Disconnect( wxEVT_CLOSE_WINDOW,
 
1961
            (wxObjectEventFunction)(wxEventFunction)
 
1962
            (wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
 
1963
 
 
1964
        // Release parents closeWindow function
 
1965
        pw->Disconnect( wxEVT_CLOSE_WINDOW,
 
1966
            (wxObjectEventFunction)(wxEventFunction)
 
1967
            (wxCloseEventFunction) &CodeSnippetsTreeCtrl::OnShutdown);
 
1968
 
1726
1969
        if ( GetConfig()->IsPlugin() )
1727
 
            GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
1728
 
 
1729
 
        m_pPropertiesDialog = 0;
1730
 
 
1731
 
        return retcode;
1732
 
}
1733
 
// ----------------------------------------------------------------------------
1734
 
//-void CodeSnippetsTreeCtrl::OnIdle(wxIdleEvent& event)
1735
 
void CodeSnippetsTreeCtrl::OnIdle()
1736
 
// ----------------------------------------------------------------------------
1737
 
{
1738
 
    // check to see if an editor has been posted & finish.
1739
 
 
 
1970
            GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
 
1971
 
 
1972
        m_pPropertiesDialog = 0;
 
1973
 
 
1974
        return retcode;
 
1975
}
 
1976
// ----------------------------------------------------------------------------
 
1977
void CodeSnippetsTreeCtrl::SaveDataAndCloseEditorFrame()
 
1978
// ----------------------------------------------------------------------------
 
1979
{
 
1980
    // This routine is invoked from EditSnippetFrame::OnCloseWindow()
 
1981
    // check to see if an editor has been posted & finish.
 
1982
 
1740
1983
    for (size_t i = 0; i < this->m_aDlgRetcodes.GetCount(); ++i )
1741
 
    {
1742
 
        // if we have a return code, this editor is done
1743
 
        if ( m_aDlgRetcodes.Item(i) == 0)
1744
 
            continue;
1745
 
 
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)
1751
 
                {
1752
 
            // If XML text snippet, just save back to XML file
1753
 
            if (pdlg->GetFileName().IsEmpty())
1754
 
            {
1755
 
                SnippetItemData* pSnippetItemData = (SnippetItemData*)(GetSnippetsTreeCtrl()->GetItemData(pdlg->GetSnippetId()));
1756
 
                pSnippetItemData->SetSnippet(pdlg->GetText());
1757
 
                GetSnippetsTreeCtrl()->SetItemText(pdlg->GetSnippetId(), pdlg->GetName());
1758
 
            }
1759
 
            else //This was an external file
1760
 
            {
1761
 
                ;// Modified external files already saved by dialog
1762
 
            }
1763
 
            // if text item type changed to link, set corrected icon
1764
 
            if ( pdlg->GetSnippetId().IsOk() )
1765
 
                SetSnippetImage(pdlg->GetSnippetId());
1766
 
                        SetFileChanged(true);
1767
 
                }//if
1768
 
                if (pdlg && (not m_bShutDown) )
1769
 
        {
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());
1776
 
                pWin->Raise();
1777
 
                pWin->SetFocus();
1778
 
            }
1779
 
            pdlg->Destroy();
1780
 
        }
1781
 
 
1782
 
        // retcode set by return frame
1783
 
        //-retcode = pdlg->GetReturnCode();
1784
 
        m_aDlgRetcodes.Item(i) = 0;
1785
 
        m_aDlgPtrs.Item(i) = 0;
1786
 
    }//for
1787
 
 
1788
 
    // when all editors terminate, free array storage
1789
 
    size_t editorsOpen = 0 ;
1790
 
    size_t knt = m_aDlgPtrs.GetCount();
 
1984
    {
 
1985
        // if we have a return code, this editor is done
 
1986
        if ( m_aDlgRetcodes.Item(i) == 0)
 
1987
            continue;
 
1988
 
 
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)
 
1994
                {
 
1995
            // If XML text snippet, just save back to XML file
 
1996
            if (pdlg->GetFileName().IsEmpty())
 
1997
            {
 
1998
                SnippetItemData* pSnippetItemData = (SnippetItemData*)(GetItemData(pdlg->GetSnippetId()));
 
1999
                pSnippetItemData->SetSnippet(pdlg->GetText());
 
2000
                SetItemText(pdlg->GetSnippetId(), pdlg->GetName());
 
2001
            }
 
2002
            else //This was an external file
 
2003
            {
 
2004
                ;// Modified external files already saved by editor
 
2005
            }
 
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"));
 
2011
                #endif
 
2012
            }
 
2013
                        //-SetFileChanged(true);
 
2014
                        // Save the XML file
 
2015
                        SaveItemsToFile(GetConfig()->SettingsSnippetsXmlPath);
 
2016
                }//if
 
2017
 
 
2018
                if (pdlg && (not m_bShutDown) )
 
2019
        {
 
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());
 
2026
                pWin->Raise();
 
2027
                pWin->SetFocus();
 
2028
            }
 
2029
            pdlg->Destroy();
 
2030
        }
 
2031
 
 
2032
        // retcode set by return frame
 
2033
        //-retcode = pdlg->GetReturnCode();
 
2034
        m_aDlgRetcodes.Item(i) = 0;
 
2035
        m_aDlgPtrs.Item(i) = 0;
 
2036
    }//for
 
2037
 
 
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();
1795
 
        m_aDlgPtrs.Clear();
1796
 
    }
1797
 
 
 
2042
        editorsOpen += (size_t)m_aDlgPtrs.Item(i)?1:0;
 
2043
    if ( knt && (not editorsOpen) )
 
2044
    {   m_aDlgRetcodes.Clear();
 
2045
        m_aDlgPtrs.Clear();
 
2046
    }
 
2047
 
 
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
// ----------------------------------------------------------------------------
 
2054
{
 
2055
    // check to enable menu items and update StatusBar
 
2056
 
1798
2057
    if ( GetConfig()->IsPlugin() )
1799
 
        GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
1800
 
 
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()));
1811
 
    }
1812
 
 
1813
 
    ////event.Skip(); this routine is called from another OnIdle which does the
1814
 
    // event.Skip() itself.
1815
 
    return;
1816
 
}//OnIdle
1817
 
 
1818
 
// ----------------------------------------------------------------------------
1819
 
void CodeSnippetsTreeCtrl::OnShutdown(wxCloseEvent& event)
1820
 
// ----------------------------------------------------------------------------
1821
 
{
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
1831
 
////
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 )
1835
 
////    {
1836
 
////        wxDialog* pdlg = this->m_aDlgPtrs.Item(i);
1837
 
////        if (pdlg) pdlg->ProcessEvent(event);
1838
 
////    }
1839
 
////    #if defined(BUILDING_PLUGIN)
1840
 
////      // Enable the plugin View menu item
1841
 
////        asm("int3");
1842
 
////        Manager::Get()->GetAppWindow()->GetMenuBar()->Enable(idViewSnippets, true);
1843
 
////    #endif
1844
 
////
1845
 
////    event.Skip();
1846
 
////    return;
1847
 
}
1848
 
// ----------------------------------------------------------------------------
 
2058
        GetConfig()->GetMenuBar()->Enable(idViewSnippets, true);
 
2059
 
 
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()));
 
2070
    }
 
2071
 
 
2072
    ////event.Skip(); this routine is called from another OnIdle which does the
 
2073
    // event.Skip() itself.
 
2074
    return;
 
2075
}//OnIdle
 
2076
 
 
2077
// ----------------------------------------------------------------------------
 
2078
void CodeSnippetsTreeCtrl::OnShutdown(wxCloseEvent& event)
 
2079
// ----------------------------------------------------------------------------
 
2080
{
 
2081
    event.Skip(); return;
 
2082
}
 
2083
// ----------------------------------------------------------------------------
 
2084
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Select(CodeSnippetsEvent& event)
 
2085
// ----------------------------------------------------------------------------
 
2086
{
 
2087
    // CodeSnippetsEvent (usually issued from external ThreadSearch frame)
 
2088
    // to focus/select a tree item via a snippet id
 
2089
 
 
2090
    event.Skip();
 
2091
 
 
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());
 
2096
    #endif
 
2097
 
 
2098
    xmlString.Trim(false);  // remove prefix whitespace
 
2099
    // fetch type="category" or type="snippet"
 
2100
    int type = 0;
 
2101
    long id  = 0;
 
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;
 
2107
    if ( type )
 
2108
    {
 
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);
 
2115
    }
 
2116
    if ( id )
 
2117
    {
 
2118
        wxTreeItemId rootID = GetRootItem();
 
2119
        wxTreeItemId treeItemID = FindTreeItemBySnippetId( id, rootID );
 
2120
        if (treeItemID)
 
2121
        {
 
2122
            EnsureVisible( treeItemID );
 
2123
            SelectItem( treeItemID );
 
2124
            // Let edit event(doubleClick) raise and focus CodeSnippets window
 
2125
            //-wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
 
2126
            //-pWin->Raise();
 
2127
            //-pWin->SetFocus();
 
2128
        }
 
2129
    }//if id
 
2130
 
 
2131
}//OnCodeSnippetsEvent_Select
 
2132
// ----------------------------------------------------------------------------
 
2133
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_Edit(CodeSnippetsEvent& event)
 
2134
// ----------------------------------------------------------------------------
 
2135
{
 
2136
    // CodeSnippetsEvent (usually issued from external ThreadSearch frame)
 
2137
    // to edit a tree item via a snippet id
 
2138
 
 
2139
    event.Skip();
 
2140
 
 
2141
    wxString xmlString = event.GetSnippetString();
 
2142
    #if defined(LOGGING)
 
2143
    LOGIT( _T("CodeSnippetsTreeCtrl::OnCodeSnippesEvent_Edit[%d][%s]"), event.GetSnippetID(), xmlString.c_str());
 
2144
    #endif
 
2145
 
 
2146
    xmlString.Trim(false);  // remove prefix whitespace
 
2147
    // fetch type="category" or type="snippet"
 
2148
    int type = 0;
 
2149
    long id  = 0;
 
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;
 
2155
    if ( type )
 
2156
    {
 
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);
 
2163
    }
 
2164
    if ( id )
 
2165
    {
 
2166
        wxTreeItemId rootID = GetRootItem();
 
2167
        wxTreeItemId treeItemID = FindTreeItemBySnippetId( id, rootID );
 
2168
        if (treeItemID)
 
2169
        {
 
2170
            EnsureVisible( treeItemID );
 
2171
            SelectItem( treeItemID );
 
2172
            if ( type == SnippetItemData::TYPE_CATEGORY )
 
2173
            {
 
2174
                wxWindow* pWin = (wxWindow*)(GetConfig()->GetMainFrame());
 
2175
                pWin->Raise();
 
2176
                pWin->SetFocus();
 
2177
            }
 
2178
            if ( type == SnippetItemData::TYPE_SNIPPET )
 
2179
            {
 
2180
                SetAssociatedItemID( treeItemID );
 
2181
                wxCommandEvent editEvt( wxEVT_COMMAND_MENU_SELECTED , idMnuEditSnippet);
 
2182
                #if wxCHECK_VERSION(2, 9, 0)
 
2183
                GetConfig()->GetSnippetsWindow()->GetEventHandler()->AddPendingEvent(editEvt);
 
2184
                #else
 
2185
                GetConfig()->GetSnippetsWindow()->AddPendingEvent( editEvt);
 
2186
                #endif
 
2187
            }
 
2188
        }
 
2189
    }//if id
 
2190
 
 
2191
}//OnCodeSnippetsEvent_Edit
 
2192
// ----------------------------------------------------------------------------
 
2193
void CodeSnippetsTreeCtrl::OnCodeSnippetsEvent_GetFileLinks(CodeSnippetsEvent& event)
 
2194
// ----------------------------------------------------------------------------
 
2195
{
 
2196
    // CodeSnippetsEvent usually issued from external frame
 
2197
    // to fill file map with file link names and snippet ids
 
2198
 
 
2199
    event.Skip();
 
2200
 
 
2201
    #if defined(LOGGING)
 
2202
    LOGIT( _T("CodeSnippetsTreeCtrl::OnCodeSnippesEvent_GetFileLinks") );
 
2203
    #endif
 
2204
 
 
2205
    FileLinksMapArray& fileIDMap = GetConfig()->GetFileLinksMapArray();
 
2206
    fileIDMap.clear();
 
2207
 
 
2208
    FillFileLinksMapArray( GetRootItem(), fileIDMap );
 
2209
    return;
 
2210
 
 
2211
}//OnCodeSnippetsEvent_GetFileLinks
 
2212
// ----------------------------------------------------------------------------
 
2213
wxTreeItemId CodeSnippetsTreeCtrl::ResetSnippetsIDs(const wxTreeItemId& startNode)
 
2214
// ----------------------------------------------------------------------------
 
2215
{
 
2216
    // Re-number Snippet Id's in Tree. Used for save and data inserts
 
2217
 
 
2218
    static wxTreeItemId dummyItem = (void*)(0);
 
2219
        wxTreeItemIdValue cookie;
 
2220
        wxTreeItemId item = GetFirstChild(startNode, cookie );
 
2221
 
 
2222
        // Loop through all items and reset their ID number
 
2223
        while(item.IsOk())
 
2224
        {
 
2225
                if ( SnippetItemData* itemData = (SnippetItemData*)(GetItemData(item)))
 
2226
                {
 
2227
                        bool ignoreThisType = false;
 
2228
 
 
2229
                        switch (itemData->GetType())
 
2230
                        {
 
2231
                                case SnippetItemData::TYPE_ROOT:
 
2232
                                        ignoreThisType = true;
 
2233
                                break;
 
2234
 
 
2235
                                case SnippetItemData::TYPE_SNIPPET:
 
2236
                                break;
 
2237
 
 
2238
                                case SnippetItemData::TYPE_CATEGORY:
 
2239
                                break;
 
2240
                        }
 
2241
 
 
2242
                        if (!ignoreThisType)
 
2243
                        {
 
2244
                                //-wxString label = GetItemText(item);
 
2245
                itemData->SetID( itemData->GetNewID() );
 
2246
                        }
 
2247
 
 
2248
                        if(ItemHasChildren(item))
 
2249
                        {
 
2250
                                wxTreeItemId search = ResetSnippetsIDs( item );
 
2251
                                if(search.IsOk())
 
2252
                                        return search;
 
2253
                        }
 
2254
                        item = GetNextChild(startNode, cookie);
 
2255
                }
 
2256
        }
 
2257
 
 
2258
   // Return dummy item if search string was not found
 
2259
   return dummyItem;
 
2260
}
 
2261
// ----------------------------------------------------------------------------
 
2262
wxTreeItemId CodeSnippetsTreeCtrl::FillFileLinksMapArray(const wxTreeItemId& startNode, FileLinksMapArray& fileLinksMapArray)
 
2263
// ----------------------------------------------------------------------------
 
2264
{
 
2265
    // Place Snippet item file links into array along with their snippet ID's
 
2266
 
 
2267
    static wxTreeItemId dummyItem = (void*)(0);
 
2268
        wxTreeItemIdValue cookie;
 
2269
 
 
2270
        wxTreeItemId treeItem = GetFirstChild(startNode, cookie );
 
2271
 
 
2272
        // Loop through all items record their file links
 
2273
        while(treeItem.IsOk())
 
2274
        {
 
2275
                if ( SnippetItemData* snippetData = (SnippetItemData*)(GetItemData(treeItem)))
 
2276
                {
 
2277
                        bool ignoreThisType = false;
 
2278
 
 
2279
                        switch (snippetData->GetType())
 
2280
                        {
 
2281
                                case SnippetItemData::TYPE_ROOT:
 
2282
                                        ignoreThisType = true;
 
2283
                                break;
 
2284
 
 
2285
                                case SnippetItemData::TYPE_SNIPPET:
 
2286
                                break;
 
2287
 
 
2288
                                case SnippetItemData::TYPE_CATEGORY:
 
2289
                    ignoreThisType = true;
 
2290
                                break;
 
2291
                        }
 
2292
 
 
2293
                        if (!ignoreThisType)
 
2294
                        {
 
2295
                            wxString fileName = wxEmptyString;
 
2296
                                if ( wxEmptyString not_eq (fileName = snippetData->GetSnippetFileLink() ))
 
2297
                {
 
2298
                    long itemId = snippetData->GetID();
 
2299
                    fileLinksMapArray[fileName] = itemId;
 
2300
                }
 
2301
                        }
 
2302
 
 
2303
                        if(ItemHasChildren(treeItem))
 
2304
                        {
 
2305
                                wxTreeItemId search = FillFileLinksMapArray( treeItem, fileLinksMapArray );
 
2306
                                if(search.IsOk())
 
2307
                                        return search;
 
2308
                        }
 
2309
                        treeItem = GetNextChild(startNode, cookie);
 
2310
                }
 
2311
        }
 
2312
 
 
2313
   // Return dummy item if search string was not found
 
2314
   return dummyItem;
 
2315
}
 
2316
// ----------------------------------------------------------------------------
 
2317
void CodeSnippetsTreeCtrl::CreateDirLevels(const wxString& pathNameIn)
 
2318
// ----------------------------------------------------------------------------
 
2319
{
 
2320
    // FileImport Traverser will create any missing directories
 
2321
    FileImportTraverser fit(_T("dummy"), pathNameIn);
 
2322
    return;
 
2323
}