2
* This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3
* http://www.gnu.org/licenses/gpl-3.0.html
6
* $Id: todolist.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
7
* $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/plugins/todo/todolist.cpp $
13
#include <wx/frame.h> // GetMenuBar
14
#include <wx/fs_zip.h>
17
#include <wx/menuitem.h>
18
#include <wx/string.h>
20
#include <wx/xrc/xmlres.h>
22
#include "configmanager.h"
23
#include "editormanager.h"
25
#include "projectmanager.h"
26
#include "logmanager.h"
27
#include "sdk_events.h"
29
#include "cbstyledtextctrl.h"
31
#include "addtododlg.h"
32
#include "asktypedlg.h"
34
#include "todolistview.h"
35
#include "todosettingsdlg.h"
37
#include <wx/arrimpl.cpp>
38
WX_DEFINE_OBJARRAY(ToDoItems);
42
PluginRegistrant<ToDoList> reg(_T("ToDoList"));
45
const int idViewTodo = wxNewId();
46
const int idAddTodo = wxNewId();
47
const int idStartParsing = wxNewId();
49
BEGIN_EVENT_TABLE(ToDoList, cbPlugin)
50
EVT_UPDATE_UI(idViewTodo, ToDoList::OnUpdateUI)
51
EVT_MENU(idViewTodo, ToDoList::OnViewList)
52
EVT_MENU(idAddTodo, ToDoList::OnAddItem)
55
ToDoList::ToDoList() :
57
m_ParsePending(false),
61
if(!Manager::LoadResource(_T("todo.zip")))
63
NotifyMissingFile(_T("todo.zip"));
72
void ToDoList::OnAttach()
74
// create ToDo in bottom view
77
titles.Add(_("Type"));
78
titles.Add(_("Text"));
79
titles.Add(_("User"));
80
titles.Add(_("Prio."));
81
titles.Add(_("Line"));
82
titles.Add(_("File"));
90
m_pListLog = new ToDoListView(titles, widths, m_Types);
92
bool standalone = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("stand_alone"), true);
93
m_StandAlone = standalone;
97
LogManager* msgMan = Manager::Get()->GetLogManager();
98
m_ListPageIndex = msgMan->SetLog(m_pListLog);
99
msgMan->Slot(m_ListPageIndex).title = _("To-Do");
101
CodeBlocksLogEvent evt(cbEVT_ADD_LOG_WINDOW, m_pListLog, msgMan->Slot(m_ListPageIndex).title, msgMan->Slot(m_ListPageIndex).icon);
102
Manager::Get()->ProcessEvent(evt);
106
m_pListLog->CreateControl(Manager::Get()->GetAppWindow());
107
m_pListLog->GetWindow()->SetSize(wxSize(352,94));
108
m_pListLog->GetWindow()->SetInitialSize(wxSize(352,94));
110
CodeBlocksDockEvent evt(cbEVT_ADD_DOCK_WINDOW);
111
evt.name = _T("TodoListPanev2.0.0");
112
evt.title = _("To-Do list");
113
evt.pWindow = m_pListLog->GetWindow();
114
evt.dockSide = CodeBlocksDockEvent::dsFloating;
115
evt.desiredSize.Set(352, 94);
116
evt.floatingSize.Set(352, 94);
117
evt.minimumSize.Set(352, 94);
118
Manager::Get()->ProcessEvent(evt);
121
m_AutoRefresh = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("auto_refresh"), true);
124
// register event sink
125
Manager::Get()->RegisterEventSink(cbEVT_APP_STARTUP_DONE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnAppDoneStartup));
126
Manager::Get()->RegisterEventSink(cbEVT_EDITOR_OPEN, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
127
Manager::Get()->RegisterEventSink(cbEVT_EDITOR_SAVE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
128
Manager::Get()->RegisterEventSink(cbEVT_EDITOR_ACTIVATED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
129
Manager::Get()->RegisterEventSink(cbEVT_EDITOR_CLOSE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
130
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_CLOSE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
131
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
132
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_FILE_ADDED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
133
Manager::Get()->RegisterEventSink(cbEVT_PROJECT_FILE_REMOVED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
136
void ToDoList::OnRelease(bool appShutDown)
140
CodeBlocksDockEvent evt(cbEVT_REMOVE_DOCK_WINDOW);
141
evt.pWindow = m_pListLog->GetWindow();
142
Manager::Get()->ProcessEvent(evt);
143
// delete m_pListLog;
147
CodeBlocksLogEvent evt(cbEVT_REMOVE_LOG_WINDOW, m_pListLog);
148
evt.window = m_pListLog->GetWindow();
149
Manager::Get()->ProcessEvent(evt);
154
void ToDoList::BuildMenu(wxMenuBar* menuBar)
156
int idx = menuBar->FindMenu(_("View"));
157
if (idx != wxNOT_FOUND)
159
wxMenu* view = menuBar->GetMenu(idx);
160
wxMenuItemList& items = view->GetMenuItems();
161
// find the first separator and insert before it
162
for (size_t i = 0; i < items.GetCount(); ++i)
164
if (items[i]->IsSeparator())
166
view->InsertCheckItem(i, idViewTodo, _("To-Do list"), _("Toggle displaying the To-Do list"));
170
// not found, just append
171
view->AppendCheckItem(idViewTodo, _("To-Do list"), _("Toggle displaying the To-Do list"));
175
void ToDoList::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
177
if (!menu || !IsAttached())
179
if (type == mtEditorManager)
181
menu->AppendSeparator();
182
menu->Append(idAddTodo, _("Add To-Do item..."), _("Add new To-Do item..."));
186
bool ToDoList::BuildToolBar(wxToolBar* toolBar)
191
cbConfigurationPanel* ToDoList::GetConfigurationPanel(wxWindow* parent)
193
ToDoSettingsDlg* dlg = new ToDoSettingsDlg(parent);
197
int ToDoList::Configure()
200
// ToDoSettingsDlg dlg;
201
// PlaceWindow(&dlg);
202
// if (dlg.ShowModal() == wxID_OK)
203
// m_AutoRefresh = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("auto_refresh"), true);
207
void ToDoList::LoadTypes()
211
Manager::Get()->GetConfigManager(_T("todo_list"))->Read(_T("types"), &m_Types);
213
if(m_Types.GetCount() == 0)
215
m_Types.Add(_T("TODO"));
216
m_Types.Add(_T("@todo"));
217
m_Types.Add(_T("\\todo"));
218
m_Types.Add(_T("FIXME"));
219
m_Types.Add(_T("NOTE"));
220
m_Types.Add(_T("@note"));
221
m_Types.Add(_T("\\note"));
226
void ToDoList::SaveTypes()
228
Manager::Get()->GetConfigManager(_T("todo_list"))->Write(_T("types"), m_Types);
233
void ToDoList::OnAppDoneStartup(CodeBlocksEvent& event)
240
void ToDoList::OnUpdateUI(wxUpdateUIEvent& event)
242
Manager::Get()->GetAppFrame()->GetMenuBar()->Check(idViewTodo, IsWindowReallyShown(m_pListLog->GetWindow()));
245
void ToDoList::OnViewList(wxCommandEvent& event)
249
CodeBlocksDockEvent evt(event.IsChecked() ? cbEVT_SHOW_DOCK_WINDOW : cbEVT_HIDE_DOCK_WINDOW);
250
evt.pWindow = m_pListLog->GetWindow();
251
Manager::Get()->ProcessEvent(evt);
255
if(event.IsChecked())
257
CodeBlocksLogEvent evtShow(cbEVT_SHOW_LOG_MANAGER);
258
Manager::Get()->ProcessEvent(evtShow);
259
CodeBlocksLogEvent event(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
260
Manager::Get()->ProcessEvent(event);
265
void ToDoList::OnAddItem(wxCommandEvent& event)
267
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
271
// display todo dialog
272
AddTodoDlg dlg(Manager::Get()->GetAppWindow(), m_Types);
274
if (dlg.ShowModal() != wxID_OK)
278
cbStyledTextCtrl* control = ed->GetControl();
280
// calculate insertion point
282
int crlfLen = 0; // length of newline chars
283
int origPos = control->GetCurrentPos(); // keep current position in the document
284
int line = control->GetCurrentLine(); // current line
285
ToDoCommentType CmtType = dlg.GetCommentType();
286
if (dlg.GetPosition() == tdpCurrent)
288
idx = control->GetCurrentPos(); // current position in the document
289
// if the style is cpp comments (// ...), there's the possibility that the current position
290
// is somewhere in the middle of a line of code; this would result
291
// in everything after the insertion point to turn into comments
292
// let's double check this with the user
293
if(idx != control->GetLineEndPosition(line))
295
// let's ask the user, and present as options
296
// keep cpp style at current position, switch to c style, add the todo at the end (keeping cpp style)
297
// if user cancels out / do nothing : just return
298
// future idea : check if there's any non white space character
299
// if yes -> in the middle of code
300
// if no -> then only whitespace after the insertion point -> no harm to turn that into comments
301
AskTypeDlg dlg(Manager::Get()->GetAppWindow());
303
if (dlg.ShowModal() != wxID_OK)
305
switch(dlg.GetTypeCorrection())
308
break; // do nothing, leave things as they are
314
idx = control->GetLineEndPosition(line);
321
if (dlg.GetPosition() == tdpAbove)
322
idx = control->GetLineEndPosition(line - 1); // get previous line's end
323
else if (dlg.GetPosition() == tdpBelow)
324
idx = control->GetLineEndPosition(line); // get current line's end
325
// calculate insertion point by skipping next newline
326
switch (control->GetEOLMode())
329
case wxSCI_EOL_LF: crlfLen = 1; break;
330
case wxSCI_EOL_CRLF: crlfLen = 2; break;
335
// make sure insertion point is valid (bug #1300981)
336
if (idx > control->GetLength())
337
idx = control->GetLength();
339
// ok, construct todo line text like this:
340
// TODO (mandrav#0#): Implement code to do this and the other...
343
// start with the comment
350
buffer << _T("/// ");
353
buffer << _T("#warning ");
356
buffer << _T("#error ");
363
// continue with the type
364
buffer << dlg.GetType() << _T(" ");
365
wxString priority = wxString::Format(_T("%d"), dlg.GetPriority()); // do it like this (wx bug with int and streams)
367
// now do the () part
368
buffer << _T("(") << dlg.GetUser() << _T("#") << priority << _T("#): ");
370
wxString text = dlg.GetText();
371
if (CmtType != tdctC)
373
// make sure that multi-line notes, don't break the to-do
374
if (text.Replace(_T("\r\n"), _T("\\\r\n")) == 0)
375
text.Replace(_T("\n"), _T("\\\n"));
376
// now see if there were already a backslash before newline
377
if (text.Replace(_T("\\\\\r\n"), _T("\\\r\n")) == 0)
378
text.Replace(_T("\\\\\n"), _T("\\\n"));
381
// add the actual text
384
if (CmtType == tdctWarning || CmtType == tdctError)
387
else if (CmtType == tdctC)
390
// add newline char(s), only if dlg.GetPosition() != tdpCurrent
391
if (dlg.GetPosition() != tdpCurrent)
393
switch (control->GetEOLMode())
395
// NOTE: maybe this switch, should make it in the SDK (maybe as cbStyledTextCtrl::GetEOLString())???
396
case wxSCI_EOL_CR: buffer << _T("\n"); break;
397
case wxSCI_EOL_CRLF: buffer << _T("\r\n"); break;
398
case wxSCI_EOL_LF: buffer << _T("\r"); break;
402
// ok, insert the todo line text
403
control->InsertText(idx, buffer);
404
if (dlg.GetPosition() == tdpAbove)
405
origPos += buffer.Length() + crlfLen;
406
control->GotoPos(origPos);
407
control->EnsureCaretVisible();
410
} // end of OnAddItem
412
void ToDoList::OnReparse(CodeBlocksEvent& event)
414
if (m_InitDone && m_AutoRefresh && !(ProjectManager::IsBusy()))
420
m_ParsePending = true;
426
void ToDoList::OnReparseCurrent(CodeBlocksEvent& event)
428
bool forced = (event.GetEventType() == cbEVT_EDITOR_OPEN || event.GetEventType() == cbEVT_EDITOR_SAVE);
429
if (m_InitDone && m_AutoRefresh && !(ProjectManager::IsBusy()))
433
m_ParsePending = false;
438
ParseCurrent(forced);
444
void ToDoList::ParseCurrent(bool forced)
446
m_pListLog->ParseCurrent(forced);
449
void ToDoList::Parse()