Code::Blocks  SVN r11506
editorbase.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11313 $
6  * $Id: editorbase.cpp 11313 2018-03-10 11:00:49Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/editorbase.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/filename.h>
14  #include <wx/notebook.h>
15  #include <wx/menu.h>
16  #include "manager.h"
17  #include "editorbase.h"
18  #include "cbeditor.h"
19  #include "editormanager.h"
20  #include "pluginmanager.h"
21  #include "cbproject.h" // FileTreeData
22  #include "projectmanager.h" // ProjectsArray
23  #include <wx/wfstream.h>
24 #endif
25 
26 #include "cbauibook.h"
27 
28 #include "cbstyledtextctrl.h"
29 
30 // needed for initialization of variables
31 inline int editorbase_RegisterId(int id)
32 {
33  wxRegisterId(id);
34  return id;
35 }
36 
38 {
40  : m_pOwner(owner),
41  m_DisplayingPopupMenu(false),
42  m_CloseMe(false)
43  {}
44 
47  bool m_CloseMe;
48 };
49 
50 // The following lines reserve 255 consecutive id's
51 const int EditorMaxSwitchTo = 255;
52 const int idSwitchFile1 = wxNewId();
54 
55 const int idCloseMe = wxNewId();
56 const int idCloseAll = wxNewId();
57 const int idCloseAllOthers = wxNewId();
58 const int idSaveMe = wxNewId();
59 const int idSaveAll = wxNewId();
60 const int idSwitchTo = wxNewId();
61 
62 // Search for... in the context menu, visible with CTRL + right click
63 const long idGoogle = wxNewId();
64 const long idMsdn = wxNewId();
65 const long idStackOverflow = wxNewId();
66 const long idCodeProject = wxNewId();
67 const long idCPlusPlusCom = wxNewId();
68 
69 BEGIN_EVENT_TABLE(EditorBase, wxPanel)
76 
82 END_EVENT_TABLE()
83 
84 void EditorBase::InitFilename(const wxString& filename)
85 {
86  if (filename.IsEmpty())
87  m_Filename = realpath(CreateUniqueFilename());
88  else
89  m_Filename = realpath(filename);
90 
91  wxFileName fname;
92  fname.Assign(m_Filename);
93  m_Shortname = fname.GetFullName();
94 }
95 
97 {
98  const wxString prefix = _("Untitled");
99  const wxString path = wxGetCwd() + wxFILE_SEP_PATH;
100  wxString tmp;
101  int iter = 0;
102  while (true)
103  {
104  tmp.Clear();
105  tmp << path << prefix << wxString::Format(_T("%d"), iter);
106  if (!Manager::Get()->GetEditorManager()->GetEditor(tmp) &&
107  !wxFileExists(path + tmp))
108  {
109  return tmp;
110  }
111  ++iter;
112  }
113 }
114 
115 EditorBase::EditorBase(wxWindow* parent, const wxString& filename)
116  : wxPanel(parent, -1),
117  m_IsBuiltinEditor(false),
118  m_Shortname(_T("")),
119  m_Filename(_T("")),
120  m_WinTitle(filename)
121 {
122  m_pData = new EditorBaseInternalData(this);
123 
125  InitFilename(filename);
127 }
128 
130 {
131  if (!Manager::Get()->IsAppShuttingDown())
132  {
134 
136  event.SetEditor(this);
137  event.SetString(m_Filename);
138 
140  }
141  delete m_pData;
142 }
143 
145 {
146  return m_WinTitle;
147 }
148 
149 void EditorBase::SetTitle(const wxString& newTitle)
150 {
151  m_WinTitle = newTitle;
152  int mypage = Manager::Get()->GetEditorManager()->FindPageFromEditor(this);
153  if (mypage != -1)
154  Manager::Get()->GetEditorManager()->GetNotebook()->SetPageText(mypage, newTitle);
155 
156  // set full filename (including path) as tooltip,
157  // if possible add the appropriate project also
158  wxString toolTip = GetFilename();
159  wxFileName fname(realpath(toolTip));
161  toolTip = UnixFilename(fname.GetFullPath());
162 
163  cbProject* prj = Manager::Get()->GetProjectManager()->FindProjectForFile(toolTip, nullptr, false, true);
164  if (prj)
165  toolTip += _("\nProject: ") + prj->GetTitle();
167  if (nb)
168  {
169  int idx = nb->GetPageIndex(this);
170  nb->SetPageToolTip(idx, toolTip);
172  }
173 }
174 
176 {
178 }
179 
181 {
182  if ( GetModified() )
183  {
184  wxString msg;
185  msg.Printf(_("File %s is modified...\nDo you want to save the changes?"), GetFilename().c_str());
186  switch (cbMessageBox(msg, _("Save file"), wxICON_QUESTION | wxYES_NO | wxCANCEL))
187  {
188  case wxID_YES:
189  if (!Save())
190  return false;
191  break;
192  case wxID_NO:
193  break;
194  case wxID_CANCEL:
195  default:
196  return false;
197  }
198  SetModified(false);
199  }
200  return true;
201 }
202 
204 {
205  Destroy();
206  return true;
207 }
208 
210 {
211  return m_IsBuiltinEditor;
212 }
213 
215 {
216  return (Manager::Get()->GetEditorManager()->GetEditorsCount() > 1);
217 }
218 
219 wxMenu* EditorBase::CreateContextSubMenu(long id) // For context menus
220 {
221  wxMenu* menu = nullptr;
222 
223  if (id == idSwitchTo)
224  {
225  menu = new wxMenu;
226  m_SwitchTo.clear();
227  for (int i = 0; i < EditorMaxSwitchTo && i < Manager::Get()->GetEditorManager()->GetEditorsCount(); ++i)
228  {
230  if (!other || other == this)
231  continue;
232  id = idSwitchFile1+i;
233  m_SwitchTo[id] = other;
234  menu->Append(id, (other->GetModified() ? wxT("*") : wxEmptyString) + other->GetShortName());
235  }
236  if (!menu->GetMenuItemCount())
237  {
238  delete menu;
239  menu = nullptr;
240  }
241  }
242  return menu;
243 }
244 
246 {
247  if (type == mtOpenFilesList)
248  {
249  popup->Append(idCloseMe, _("Close"));
250  popup->Append(idCloseAll, _("Close all"));
251  popup->Append(idCloseAllOthers, _("Close all others"));
252  popup->AppendSeparator();
253  popup->Append(idSaveMe, _("Save"));
254  popup->Append(idSaveAll, _("Save all"));
255  popup->AppendSeparator();
256  // enable/disable some items, based on state
257  popup->Enable(idSaveMe, GetModified());
258 
259  bool hasOthers = ThereAreOthers();
260  popup->Enable(idCloseAll, hasOthers);
261  popup->Enable(idCloseAllOthers, hasOthers);
262  }
263  if (type != mtEditorManager) // no editor
264  {
266  if (switchto)
267  popup->Append(idSwitchTo, _("Switch to"), switchto);
268  }
269 }
270 
272 {
273  bool noeditor = (type != mtEditorManager);
274  // noeditor:
275  // True if context menu belongs to open files tree;
276  // False if belongs to cbEditor
277 
278  // inform the editors we 're just about to create a context menu
279  if (!OnBeforeBuildContextMenu(position, type))
280  return;
281 
282  wxMenu* popup = new wxMenu;
283 
284  PluginManager *pluginManager = Manager::Get()->GetPluginManager();
285  pluginManager->ResetModuleMenu();
286 
287  if (!noeditor && wxGetKeyState(WXK_CONTROL))
288  {
290  wxString text = control->GetSelectedText();
291  if (text.IsEmpty())
292  {
293  const int pos = control->GetCurrentPos();
294  text = control->GetTextRange(control->WordStartPosition(pos, true), control->WordEndPosition(pos, true));
295  }
296 
297  if (!text.IsEmpty())
298  {
299  popup->Append(idGoogle, _("Search the Internet for \"") + text + _T("\""));
300  popup->Append(idMsdn, _("Search MSDN for \"") + text + _T("\""));
301  popup->Append(idStackOverflow, _("Search StackOverflow for \"") + text + _T("\""));
302  popup->Append(idCodeProject, _("Search CodeProject for \"") + text + _T("\""));
303  popup->Append(idCPlusPlusCom, _("Search CplusPlus.com for \"") + text + _T("\""));
304  }
305  lastWord = text;
306 
308  if (switchto)
309  {
310  if (popup->GetMenuItemCount() > 0)
311  popup->AppendSeparator();
312  popup->Append(idSwitchTo, _("Switch to"), switchto);
313  }
314  }
315  else if (!noeditor && wxGetKeyState(WXK_ALT))
316  { // run a script
317  }
318  else
319  {
320  // Basic functions
321  BasicAddToContextMenu(popup, type);
322 
323  // Extended functions, part 1 (virtual)
324  AddToContextMenu(popup, type, false);
325 
326  // ask other editors / plugins if they need to add any entries in this menu...
328  ftd->SetFolder(m_Filename);
329  pluginManager->AskPluginsForModuleMenu(type, popup, ftd);
330  delete ftd;
331 
332  popup->AppendSeparator();
333  // Extended functions, part 2 (virtual)
334  AddToContextMenu(popup, type, true);
335  }
336 
337  // Check if the last item is a separator and remove it.
338  const wxMenuItemList &popupItems = popup->GetMenuItems();
339  if (popupItems.GetCount() > 0)
340  {
341  wxMenuItem *last = popupItems[popupItems.GetCount() - 1];
342  if (last && last->IsSeparator())
343  popup->Remove(last);
344  }
345 
346  // Insert a separator at the end of the "Find XXX" menu group of items.
347  const int lastFind = pluginManager->GetFindMenuItemFirst() + pluginManager->GetFindMenuItemCount();
348  if (lastFind > 0)
349  popup->Insert(lastFind, wxID_SEPARATOR, wxEmptyString);
350 
351  // inform the editors we 're done creating a context menu (just about to show it)
353 
354  // display menu
355  wxPoint clientpos;
356  if (position==wxDefaultPosition) // "context menu" key
357  {
358  // obtain the caret point (on the screen) as we assume
359  // that the user wants to work with the keyboard
361  clientpos = control->PointFromPosition(control->GetCurrentPos());
362  }
363  else
364  {
365  clientpos = ScreenToClient(position);
366  }
367 
369  PopupMenu(popup, clientpos);
370  delete popup;
372 
373  // this code *must* be the last code executed by this function
374  // because it *will* invalidate 'this'
375  if (m_pData->m_CloseMe)
376  Manager::Get()->GetEditorManager()->Close(this);
377 }
378 
380 {
381  // we have a single event handler for all popup menu entries
382  // This was ported from cbEditor and used for the basic operations:
383  // Switch to, close, save, etc.
384 
385  const int id = event.GetId();
386  m_pData->m_CloseMe = false;
387 
388  if (id == idCloseMe)
389  {
391  m_pData->m_CloseMe = true; // defer delete 'this' until after PopupMenu() call returns
392  else
393  Manager::Get()->GetEditorManager()->Close(this);
394  }
395  else if (id == idCloseAll)
396  {
398  {
400  m_pData->m_CloseMe = true; // defer delete 'this' until after PopupMenu() call returns
401  }
402  else
404  }
405  else if (id == idCloseAllOthers)
406  {
408  }
409  else if (id == idSaveMe)
410  {
411  Save();
412  }
413  else if (id == idSaveAll)
414  {
416  }
417  else if (id >= idSwitchFile1 && id <= idSwitchFileMax)
418  {
419  // "Switch to..." item
420  EditorBase* const ed = m_SwitchTo[id];
421  if (ed)
423 
424  m_SwitchTo.clear();
425  }
426  else
427  {
428  if (id == idGoogle)
429  wxLaunchDefaultBrowser(wxString(_T("http://www.google.com/search?q=")) << URLEncode(lastWord));
430  else if (id == idMsdn)
431  wxLaunchDefaultBrowser(wxString(_T("http://social.msdn.microsoft.com/Search/en-US/?query=")) << URLEncode(lastWord) << _T("&ac=8"));
432  else if (id == idStackOverflow)
433  wxLaunchDefaultBrowser(wxString(_T("http://stackoverflow.com/search?q=")) << URLEncode(lastWord));
434  else if (id == idCodeProject)
435  wxLaunchDefaultBrowser(wxString(_T("http://www.codeproject.com/search.aspx?q=")) << URLEncode(lastWord));
436  else if (id == idCPlusPlusCom)
437  wxLaunchDefaultBrowser(wxString(_T("http://www.cplusplus.com/search.do?q=")) << URLEncode(lastWord));
438  }
439 }
440 
442 {
444 }
const int idCloseAllOthers
Definition: editorbase.cpp:57
const long idCodeProject
Definition: editorbase.cpp:66
bool CloseAllInTabCtrlExcept(EditorBase *editor, bool dontsave=false)
Closes all editors in the same tab control as the active editor, except the editor passed as paramete...
virtual const wxString & GetShortName() const
Returns the editor&#39;s short name.
Definition: editorbase.h:58
virtual wxMenu * CreateContextSubMenu(long id)
Creates context submenus.
Definition: editorbase.cpp:219
const long idCPlusPlusCom
Definition: editorbase.cpp:67
int WordEndPosition(int pos, bool onlyWordCharacters)
Get position of end of word.
void BasicAddToContextMenu(wxMenu *popup, ModuleType type)
Definition: editorbase.cpp:245
int wxNewId()
PluginManager * GetPluginManager() const
Definition: manager.cpp:444
#define wxICON_QUESTION
const int idSwitchFileMax
Definition: editorbase.cpp:53
bool CloseAllInTabCtrl(bool dontsave=false)
Closes all editors in the same tab control as the active editor.
virtual void OnAfterBuildContextMenu(cb_optional ModuleType type)
Informs the editor we &#39;re done creating the context menu (just about to display it).
Definition: editorbase.h:276
void Assign(const wxFileName &filepath)
virtual const wxString & GetTitle()
The editor&#39;s title.
Definition: editorbase.cpp:144
const int idCloseMe
Definition: editorbase.cpp:55
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
virtual void AddToContextMenu(cb_optional wxMenu *popup, cb_optional ModuleType type, cb_optional bool pluginsdone)
Creates context menu items, both before and after creating plugins menu items.
Definition: editorbase.h:257
bool m_IsBuiltinEditor
Definition: editorbase.h:278
wxString lastWord
Definition: editorbase.h:290
virtual bool QueryClose()
Can this be closed (destroyed)?
Definition: editorbase.cpp:180
bool SetPageText(size_t page, const wxString &text)
void Enable(int id, bool enable)
bool wxFileExists(const wxString &filename)
const long idGoogle
Definition: editorbase.cpp:63
virtual bool IsReadOnly() const
Is the editor read-only?
Definition: editorbase.h:217
EditorBaseInternalData(EditorBase *owner)
Definition: editorbase.cpp:39
const long idMsdn
Definition: editorbase.cpp:64
DLLIMPORT bool NormalizePath(wxFileName &f, const wxString &base)
Definition: globals.cpp:942
#define wxCANCEL
const int idSaveMe
Definition: editorbase.cpp:58
bool IsSeparator() const
wxString m_Shortname
Definition: editorbase.h:279
virtual void Activate()
Activate this editor.
Definition: editorbase.cpp:175
wxMenuItem * Append(int id, const wxString &item=wxEmptyString, const wxString &helpString=wxEmptyString, wxItemKind kind=wxITEM_NORMAL)
void wxRegisterId(int id)
EditorBaseInternalData * m_pData
Use this to add new vars/functions w/out breaking the ABI.
Definition: editorbase.h:281
#define _T(string)
void SetActiveEditor(EditorBase *ed)
EditorBase * m_pOwner
Definition: editorbase.cpp:45
#define wxYES_NO
DLLIMPORT wxString URLEncode(const wxString &str)
Definition: globals.cpp:832
bool Close(const wxString &filename, bool dontsave=false)
SwitchToMap m_SwitchTo
Definition: editorbase.h:288
~EditorBase() override
Definition: editorbase.cpp:129
#define wxT(string)
const int idSwitchTo
Definition: editorbase.cpp:60
size_t GetMenuItemCount() const
const int idCloseAll
Definition: editorbase.cpp:56
A generic Code::Blocks event.
Definition: sdk_events.h:20
EditorBase(wxWindow *parent, const wxString &filename)
Definition: editorbase.cpp:115
void OnContextMenuEntry(wxCommandEvent &event)
one event handler for all popup menu entries
Definition: editorbase.cpp:379
const long idStackOverflow
Definition: editorbase.cpp:65
virtual bool ThereAreOthers() const
Are there other editors besides this?
Definition: editorbase.cpp:214
void SetFolder(const wxString &folder)
Definition: cbproject.h:70
int WordStartPosition(int pos, bool onlyWordCharacters)
Get position of start of word.
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
virtual void SetModified(bool=true)
Set the modification status.
Definition: editorbase.h:73
wxString GetSelectedText()
Retrieve the selected text.
void ResetModuleMenu()
Called by the code creating the context menu for the editor.
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
PluginManager manages plugins.
Definition: pluginmanager.h:76
virtual bool Close()
Close this editor.
Definition: editorbase.cpp:203
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
DLLIMPORT wxString UnixFilename(const wxString &filename, wxPathFormat format=wxPATH_NATIVE)
Definition: globals.cpp:228
EVTIMPORT const wxEventType cbEVT_EDITOR_CLOSE
Definition: sdk_events.cpp:80
Represents a Code::Blocks project.
Definition: cbproject.h:96
virtual void InitFilename(const wxString &filename)
Initializes filename data.
Definition: editorbase.cpp:84
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
ModuleType
The type of module offering a context menu.
Definition: globals.h:38
int FindPageFromEditor(EditorBase *eb)
wxPoint PointFromPosition(int pos)
Retrieve the point in the window where a position is displayed.
void AddCustomEditor(EditorBase *eb)
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
const wxPoint wxDefaultPosition
virtual void DisplayContextMenu(const wxPoint &position, ModuleType type=mtUnknown)
Display context menu.
Definition: editorbase.cpp:271
wxMenuItem * AppendSeparator()
Base class that all "editors" should inherit from.
Definition: editorbase.h:30
int GetCurrentPos() const
Returns the position of the caret.
virtual bool IsContextMenuOpened() const
Is there a context (right click) menu open.
Definition: editorbase.cpp:441
wxString GetTextRange(int startPos, int endPos)
Retrieve a range of text.
virtual bool IsBuiltinEditor() const
Is this a built-in editor?
Definition: editorbase.cpp:209
wxString wxEmptyString
void NotifyPlugins(CodeBlocksEvent &event)
void RemoveCustomEditor(EditorBase *eb)
static bool Access(const wxString &name, wxFile::OpenMode mode)
const wxString & _(const wxString &string)
EditorBase * GetEditor(int index)
wxString m_WinTitle
Definition: editorbase.h:289
virtual bool GetModified() const
Is it modified?
Definition: editorbase.h:67
bool SetPageToolTip(size_t page, const wxString &text)
int GetPageIndex(wxWindow *page_wnd) const
void MarkReadOnly(int page, bool readOnly=true)
bool IsEmpty() const
virtual void SetTitle(const wxString &newTitle)
Set the editor&#39;s title.
Definition: editorbase.cpp:149
void Clear()
cbAuiNotebook * GetNotebook()
Definition: editormanager.h:73
wxString GetFullName() const
void AskPluginsForModuleMenu(const ModuleType type, wxMenu *menu, const FileTreeData *data=nullptr)
A notebook class This class is derived from wxAuiNotebook, to enhance its abilities.
Definition: cbauibook.h:30
int GetFindMenuItemFirst() const
Returns the position of the first menu item in the find group.
const int idSaveAll
Definition: editorbase.cpp:59
cbProject * FindProjectForFile(const wxString &file, ProjectFile **resultFile, bool isRelative, bool isUnixFilename)
Return the project which has the file in it, also return the pointer to the ProjectFile object...
wxString m_Filename
Definition: editorbase.h:280
bool wxLaunchDefaultBrowser(const wxString &url, int flags=0)
bool FileExists() const
virtual bool OnBeforeBuildContextMenu(cb_optional const wxPoint &position, cb_optional ModuleType type)
Informs the editor we &#39;re just about to create a context menu.
Definition: editorbase.h:270
int Printf(const wxString &pszFormat,...)
int GetFindMenuItemCount() const
Returns the number of items in the find group already added to the menu.
wxMenuItemList & GetMenuItems()
const int EditorMaxSwitchTo
Definition: editorbase.cpp:51
wxString GetFullPath(wxPathFormat format=wxPATH_NATIVE) const
virtual bool Save()
Save contents.
Definition: editorbase.h:113
int editorbase_RegisterId(int id)
Definition: editorbase.cpp:31
bool wxGetKeyState(wxKeyCode key)
static wxString Format(const wxString &format,...)
wxMenuItem * Insert(size_t pos, wxMenuItem *menuItem)
wxMenuItem * Remove(int id)
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
virtual wxString CreateUniqueFilename()
Creates unique filename when asking to save the file.
Definition: editorbase.cpp:96
wxString wxGetCwd()
DLLIMPORT wxString realpath(const wxString &path)
Definition: globals.cpp:1348
const int idSwitchFile1
Definition: editorbase.cpp:52